Skip to content

Commit 47ae191

Browse files
committed
structural changes
1 parent 1785a24 commit 47ae191

9 files changed

Lines changed: 265 additions & 193 deletions

File tree

apps/website/app/api/supabase/agent-identifier/route.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NextResponse, NextRequest } from "next/server";
22

33
import { createClient } from "~/utils/supabase/server";
4-
import { getOrCreateEntity, ItemValidator } from "~/utils/supabase/dbUtils";
4+
import { getOrCreateEntity } from "~/utils/supabase/dbUtils";
55
import { asPostgrestFailure } from "@repo/database/lib/contextFunctions";
66
import {
77
createApiResponse,
@@ -11,25 +11,26 @@ import {
1111
import { type TablesInsert, Constants } from "@repo/database/dbTypes";
1212

1313
type AgentIdentifierDataInput = TablesInsert<"AgentIdentifier">;
14+
// eslint-disable-next-line @typescript-eslint/naming-convention
1415
const { AgentIdentifierType } = Constants.public.Enums;
1516

16-
const agentIdentifierValidator: ItemValidator<AgentIdentifierDataInput> = (
17-
agent_identifier: any,
18-
) => {
17+
// ItemValidator<"AgentIdentifier">
18+
const agentIdentifierValidator = (
19+
// eslint-disable-next-line @typescript-eslint/naming-convention
20+
agent_identifier: AgentIdentifierDataInput,
21+
): string | null => {
1922
if (!agent_identifier || typeof agent_identifier !== "object")
2023
return "Invalid request body: expected a JSON object.";
24+
// eslint-disable-next-line @typescript-eslint/naming-convention
2125
const { identifier_type, account_id, value, trusted } = agent_identifier;
2226

2327
if (!AgentIdentifierType.includes(identifier_type))
2428
return "Invalid identifier_type";
2529
if (!value || typeof value !== "string" || value.trim() === "")
2630
return "Missing or invalid value";
27-
if (!account_id || Number.isNaN(Number.parseInt(account_id, 10)))
31+
if (!account_id || typeof account_id !== "number" || Number.isNaN(account_id))
2832
return "Missing or invalid account_id";
29-
if (
30-
trusted !== undefined &&
31-
!["true", "false", true, false].includes(trusted)
32-
)
33+
if (trusted !== undefined && typeof trusted !== "boolean")
3334
return "if included, trusted should be a boolean";
3435

3536
const keys = ["identifier_type", "account_id", "value", "trusted"];
@@ -42,18 +43,16 @@ export const POST = async (request: NextRequest): Promise<NextResponse> => {
4243
const supabasePromise = createClient();
4344

4445
try {
45-
const body = await request.json();
46+
const body = (await request.json()) as AgentIdentifierDataInput;
4647
const error = agentIdentifierValidator(body);
4748
if (error !== null)
4849
return createApiResponse(request, asPostgrestFailure(error, "invalid"));
4950

50-
body.account_id = Number.parseInt(body.account_id, 10);
51-
body.trusted = body.trusted === true || body.trusted === "true" || false;
5251
const supabase = await supabasePromise;
53-
const result = await getOrCreateEntity<"AgentIdentifier">({
52+
const result = await getOrCreateEntity({
5453
supabase,
5554
tableName: "AgentIdentifier",
56-
insertData: body as AgentIdentifierDataInput,
55+
insertData: body,
5756
uniqueOn: ["value", "identifier_type", "account_id"],
5857
});
5958

apps/website/app/api/supabase/content-embedding/batch/route.ts

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import {
1313
KNOWN_EMBEDDING_TABLES,
1414
} from "~/utils/supabase/dbUtils";
1515
import {
16-
ApiInputEmbeddingItem,
17-
ApiOutputEmbeddingRecord,
16+
type ContentEmbeddingVecTablesInsert,
17+
type ContentEmbeddingVecTables,
1818
embeddingInputProcessing,
1919
embeddingOutputProcessing,
2020
} from "~/utils/supabase/validators";
@@ -23,19 +23,19 @@ const DEFAULT_MODEL = "openai_text_embedding_3_small_1536";
2323

2424
const batchInsertEmbeddingsProcess = async (
2525
supabase: Awaited<ReturnType<typeof createClient>>,
26-
embeddingItems: ApiInputEmbeddingItem[],
27-
): Promise<PostgrestResponse<ApiOutputEmbeddingRecord>> => {
26+
embeddingItems: ContentEmbeddingVecTablesInsert[],
27+
): Promise<PostgrestResponse<ContentEmbeddingVecTables>> => {
2828
// groupBy is node21 only, we are using 20. Group by model, by hand.
2929
// Note: This means that later index values may be totally wrong.
3030
// Note2: The key is a ModelName, but I cannot use an enum as a key.
31-
const byModel: { [key: string]: ApiInputEmbeddingItem[] } = {};
31+
const byModel: { [key: string]: ContentEmbeddingVecTablesInsert[] } = {};
3232
try {
3333
embeddingItems.reduce((acc, item) => {
3434
const model = item?.model || DEFAULT_MODEL;
3535
if (acc[model] === undefined) {
3636
acc[model] = [];
3737
}
38-
acc[model]!.push(item);
38+
acc[model].push(item);
3939
return acc;
4040
}, byModel);
4141
} catch (error) {
@@ -45,7 +45,7 @@ const batchInsertEmbeddingsProcess = async (
4545
throw error;
4646
}
4747

48-
const globalResults: ApiOutputEmbeddingRecord[] = [];
48+
const globalResults: ContentEmbeddingVecTables[] = [];
4949
const partialErrors: string[] = [];
5050
let created = false,
5151
count = 0,
@@ -55,15 +55,11 @@ const batchInsertEmbeddingsProcess = async (
5555
if (embeddingItemsSet === undefined) continue;
5656
const tableData = KNOWN_EMBEDDING_TABLES[modelName];
5757
if (tableData === undefined) continue;
58-
const results = await processAndInsertBatch<
59-
// any ContentEmbedding table for type checking purposes only
60-
"ContentEmbedding_openai_text_embedding_3_small_1536",
61-
ApiInputEmbeddingItem,
62-
ApiOutputEmbeddingRecord
63-
>({
58+
const { tableName } = tableData;
59+
const results = await processAndInsertBatch({
6460
supabase,
6561
items: embeddingItemsSet,
66-
tableName: tableData.tableName,
62+
tableName,
6763
inputProcessor: embeddingInputProcessing,
6864
outputProcessor: embeddingOutputProcessing,
6965
});
@@ -81,6 +77,7 @@ const batchInsertEmbeddingsProcess = async (
8177
return {
8278
data: globalResults,
8379
error: null,
80+
success: true,
8481
status: has_400 ? 400 : 500,
8582
count,
8683
statusText: partialErrors.join("; "),
@@ -89,6 +86,7 @@ const batchInsertEmbeddingsProcess = async (
8986
return {
9087
data: globalResults,
9188
error: null,
89+
success: true,
9290
status: created ? 201 : 200,
9391
count,
9492
statusText: created ? "created" : "success",
@@ -106,7 +104,7 @@ export const POST = async (request: NextRequest): Promise<NextResponse> => {
106104
const supabase = await createClient();
107105

108106
try {
109-
const body: ApiInputEmbeddingItem[] = await request.json();
107+
const body = (await request.json()) as ContentEmbeddingVecTablesInsert[];
110108
if (!Array.isArray(body)) {
111109
return createApiResponse(
112110
request,

apps/website/app/api/supabase/content-embedding/route.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import {
1313
KNOWN_EMBEDDING_TABLES,
1414
} from "~/utils/supabase/dbUtils";
1515
import {
16-
ApiInputEmbeddingItem,
17-
ApiOutputEmbeddingRecord,
16+
ContentEmbeddingVecTablesInsert,
17+
ContentEmbeddingVecTables,
1818
embeddingInputProcessing,
1919
embeddingOutputProcessing,
2020
} from "~/utils/supabase/validators";
@@ -23,9 +23,11 @@ const DEFAULT_MODEL = "openai_text_embedding_3_small_1536";
2323

2424
const processAndCreateEmbedding = async (
2525
supabasePromise: ReturnType<typeof createClient>,
26-
data: ApiInputEmbeddingItem,
27-
): Promise<PostgrestSingleResponse<ApiOutputEmbeddingRecord>> => {
28-
const { valid, error, processedItem } = embeddingInputProcessing(data);
26+
data: ContentEmbeddingVecTablesInsert,
27+
): Promise<PostgrestSingleResponse<ContentEmbeddingVecTables>> => {
28+
const processed = embeddingInputProcessing(data);
29+
if (!processed) return asPostgrestFailure("Could not process input", "valid");
30+
const { valid, error, processedItem } = processed;
2931
if (
3032
!valid ||
3133
processedItem === undefined ||
@@ -41,14 +43,11 @@ const processAndCreateEmbedding = async (
4143
const { tableName } = tableData;
4244
// Using getOrCreateEntity, forcing create path by providing non-matching criteria
4345
// This standardizes return type and error handling (e.g., FK violations from dbUtils)
44-
const result =
45-
await getOrCreateEntity<"ContentEmbedding_openai_text_embedding_3_small_1536">(
46-
{
47-
supabase,
48-
tableName,
49-
insertData: processedItem,
50-
},
51-
);
46+
const result = await getOrCreateEntity({
47+
supabase,
48+
tableName,
49+
insertData: processedItem,
50+
});
5251

5352
if (result.error) {
5453
return result;
@@ -81,7 +80,7 @@ export const POST = async (request: NextRequest): Promise<NextResponse> => {
8180
const supabasePromise = createClient();
8281

8382
try {
84-
const body: ApiInputEmbeddingItem = await request.json();
83+
const body = (await request.json()) as ContentEmbeddingVecTablesInsert;
8584
const result = await processAndCreateEmbedding(supabasePromise, body);
8685
return createApiResponse(request, result);
8786
} catch (e: unknown) {

apps/website/app/api/supabase/content/route.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ const processAndUpsertContentEntry = async (
2727
// If no solid matchCriteria for a "get", getOrCreateEntity will likely proceed to "create".
2828
// If there are unique constraints other than (space_id, source_local_id), it will handle race conditions.
2929

30-
const result = await getOrCreateEntity<"Content">({
30+
const result = await getOrCreateEntity({
3131
supabase,
3232
tableName: "Content",
3333
insertData: data,

apps/website/app/api/supabase/document/route.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { NextResponse, NextRequest } from "next/server";
22
import type { PostgrestSingleResponse } from "@supabase/supabase-js";
33

44
import { createClient } from "~/utils/supabase/server";
5-
import { getOrCreateEntity, ItemValidator } from "~/utils/supabase/dbUtils";
5+
import { getOrCreateEntity } from "~/utils/supabase/dbUtils";
66
import { asPostgrestFailure } from "@repo/database/lib/contextFunctions";
77
import {
88
createApiResponse,
@@ -14,9 +14,11 @@ import type { Tables, TablesInsert } from "@repo/database/dbTypes";
1414
type DocumentDataInput = TablesInsert<"Document">;
1515
type DocumentRecord = Tables<"Document">;
1616

17-
const validateDocument: ItemValidator<DocumentDataInput> = (data) => {
17+
// ItemValidator<"Document">
18+
const validateDocument = (data: DocumentDataInput): string | null => {
1819
if (!data || typeof data !== "object")
1920
return "Invalid request body: expected a JSON object.";
21+
// eslint-disable-next-line @typescript-eslint/naming-convention
2022
const { space_id, author_id, source_local_id } = data;
2123

2224
if (!author_id) return "Missing required author_id field.";
@@ -32,7 +34,7 @@ const createDocument = async (
3234
): Promise<PostgrestSingleResponse<DocumentRecord>> => {
3335
const supabase = await supabasePromise;
3436

35-
const result = await getOrCreateEntity<"Document">({
37+
const result = await getOrCreateEntity({
3638
supabase,
3739
tableName: "Document",
3840
insertData: data,
@@ -49,7 +51,7 @@ export const POST = async (request: NextRequest): Promise<NextResponse> => {
4951
const supabasePromise = createClient();
5052

5153
try {
52-
const body: DocumentDataInput = await request.json();
54+
const body = (await request.json()) as DocumentDataInput;
5355
const error = validateDocument(body);
5456
if (error !== null)
5557
return createApiResponse(request, asPostgrestFailure(error, "invalid"));

apps/website/app/api/supabase/platform-account/route.ts

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { NextResponse, NextRequest } from "next/server";
22

33
import { createClient } from "~/utils/supabase/server";
4-
import { getOrCreateEntity, ItemValidator } from "~/utils/supabase/dbUtils";
4+
import { getOrCreateEntity } from "~/utils/supabase/dbUtils";
55
import { asPostgrestFailure } from "@repo/database/lib/contextFunctions";
66
import {
77
createApiResponse,
@@ -10,15 +10,16 @@ import {
1010
} from "~/utils/supabase/apiUtils";
1111
import { type TablesInsert, Constants } from "@repo/database/dbTypes";
1212

13+
// eslint-disable-next-line @typescript-eslint/naming-convention
1314
const { AgentType, Platform } = Constants.public.Enums;
1415

1516
type PlatformAccountDataInput = TablesInsert<"PlatformAccount">;
1617

17-
const accountValidator: ItemValidator<PlatformAccountDataInput> = (
18-
account: any,
19-
) => {
18+
// ItemValidator<"PlatformAccount">
19+
const accountValidator = (account: PlatformAccountDataInput): string | null => {
2020
if (!account || typeof account !== "object")
2121
return "Invalid request body: expected a JSON object.";
22+
/* eslint-disable @typescript-eslint/naming-convention */
2223
const {
2324
name,
2425
platform,
@@ -29,6 +30,7 @@ const accountValidator: ItemValidator<PlatformAccountDataInput> = (
2930
metadata,
3031
dg_account,
3132
} = account;
33+
/* eslint-enable @typescript-eslint/naming-convention */
3234

3335
if (!name || typeof name !== "string" || name.trim() === "")
3436
return "Missing or invalid name";
@@ -81,16 +83,16 @@ export const POST = async (request: NextRequest): Promise<NextResponse> => {
8183
const supabasePromise = createClient();
8284

8385
try {
84-
const body = await request.json();
86+
const body = (await request.json()) as PlatformAccountDataInput;
8587
const error = accountValidator(body);
8688
if (error !== null)
8789
return createApiResponse(request, asPostgrestFailure(error, "invalid"));
8890

8991
const supabase = await supabasePromise;
90-
const result = await getOrCreateEntity<"PlatformAccount">({
92+
const result = await getOrCreateEntity({
9193
supabase,
9294
tableName: "PlatformAccount",
93-
insertData: body as PlatformAccountDataInput,
95+
insertData: body,
9496
uniqueOn: ["account_local_id", "platform"],
9597
});
9698

0 commit comments

Comments
 (0)