aboutsummaryrefslogtreecommitdiff
path: root/packages/sdk/src/supabase-store.ts
diff options
context:
space:
mode:
Diffstat (limited to 'packages/sdk/src/supabase-store.ts')
-rw-r--r--packages/sdk/src/supabase-store.ts167
1 files changed, 167 insertions, 0 deletions
diff --git a/packages/sdk/src/supabase-store.ts b/packages/sdk/src/supabase-store.ts
new file mode 100644
index 0000000..acb9364
--- /dev/null
+++ b/packages/sdk/src/supabase-store.ts
@@ -0,0 +1,167 @@
+import type { SupabaseClient } from "@supabase/supabase-js";
+import type { MemoryNotFoundError, MemoryStore } from "./memory-store.js";
+import { failure, type Result, success } from "./result.js";
+import type {
+ Memory,
+ MemoryCreateInput,
+ MemoryFilter,
+ MemoryUpdateInput,
+ Tag,
+} from "./types.js";
+
+type MemoryRow = {
+ id: string;
+ user_id: string;
+ project_id: string;
+ folder_id: string | null;
+ content: string;
+ tags: Tag[];
+ metadata: Record<string, unknown>;
+ embedding: unknown;
+ created_at: string;
+ updated_at: string;
+};
+
+function memoryNotFoundError(memoryId: string): MemoryNotFoundError {
+ return { type: "MEMORY_NOT_FOUND", memoryId };
+}
+
+function rowToMemory(row: MemoryRow): Memory {
+ return {
+ id: row.id,
+ content: row.content,
+ projectId: row.project_id,
+ folderId: row.folder_id,
+ tags: row.tags ?? [],
+ metadata: row.metadata ?? {},
+ createdAt: new Date(row.created_at),
+ updatedAt: new Date(row.updated_at),
+ };
+}
+
+export class SupabaseStore implements MemoryStore {
+ private client: SupabaseClient;
+ private userId: string;
+
+ constructor(client: SupabaseClient, userId: string) {
+ this.client = client;
+ this.userId = userId;
+ }
+
+ async create(input: MemoryCreateInput): Promise<Memory> {
+ const { data, error } = await this.client
+ .from("memories")
+ .insert({
+ user_id: this.userId,
+ project_id: input.projectId,
+ folder_id: input.folderId ?? null,
+ content: input.content,
+ tags: input.tags ?? [],
+ metadata: input.metadata ?? {},
+ })
+ .select()
+ .single();
+
+ if (error) {
+ throw new Error(`Failed to create memory: ${error.message}`);
+ }
+
+ return rowToMemory(data as MemoryRow);
+ }
+
+ async read(id: string): Promise<Result<Memory, MemoryNotFoundError>> {
+ const { data, error } = await this.client
+ .from("memories")
+ .select()
+ .eq("id", id)
+ .eq("user_id", this.userId)
+ .single();
+
+ if (error || !data) {
+ return failure(memoryNotFoundError(id));
+ }
+
+ return success(rowToMemory(data as MemoryRow));
+ }
+
+ async update(
+ id: string,
+ input: MemoryUpdateInput,
+ ): Promise<Result<Memory, MemoryNotFoundError>> {
+ const updates: Record<string, unknown> = {};
+
+ if (input.content !== undefined) {
+ updates.content = input.content;
+ }
+
+ if (input.folderId !== undefined) {
+ updates.folder_id = input.folderId;
+ }
+
+ if (input.tags !== undefined) {
+ updates.tags = input.tags;
+ }
+
+ if (input.metadata !== undefined) {
+ updates.metadata = input.metadata;
+ }
+
+ const { data, error } = await this.client
+ .from("memories")
+ .update(updates)
+ .eq("id", id)
+ .eq("user_id", this.userId)
+ .select()
+ .single();
+
+ if (error || !data) {
+ return failure(memoryNotFoundError(id));
+ }
+
+ return success(rowToMemory(data as MemoryRow));
+ }
+
+ async delete(id: string): Promise<Result<void, MemoryNotFoundError>> {
+ const { error, count } = await this.client
+ .from("memories")
+ .delete({ count: "exact" })
+ .eq("id", id)
+ .eq("user_id", this.userId);
+
+ if (error || count === 0) {
+ return failure(memoryNotFoundError(id));
+ }
+
+ return success(undefined);
+ }
+
+ async list(filter?: MemoryFilter): Promise<Memory[]> {
+ let query = this.client
+ .from("memories")
+ .select()
+ .eq("user_id", this.userId);
+
+ if (filter?.projectId) {
+ query = query.eq("project_id", filter.projectId);
+ }
+
+ if (filter?.folderId) {
+ query = query.eq("folder_id", filter.folderId);
+ }
+
+ if (filter?.tags && filter.tags.length > 0) {
+ query = query.contains(
+ "tags",
+ filter.tags.map((id) => ({ id })),
+ );
+ }
+
+ const { data, error } = await query;
+
+ if (error) {
+ throw new Error(`Failed to list memories: ${error.message}`);
+ }
+
+ return (data as MemoryRow[]).map(rowToMemory);
+ }
+}