transition to postgresql for persistence layer
This commit is contained in:
+58
-6
@@ -1,9 +1,61 @@
|
||||
export interface Entity<T, ID> {
|
||||
import type { CommittedMessage } from "../types";
|
||||
|
||||
export type Conversation = {
|
||||
id: string;
|
||||
title: string;
|
||||
userId: string;
|
||||
createdAt?: string;
|
||||
};
|
||||
|
||||
export type Fact = {
|
||||
id: string;
|
||||
userId: string;
|
||||
sourceMessageId: string;
|
||||
content: string;
|
||||
createdAt?: string;
|
||||
};
|
||||
|
||||
export type FactTrigger = {
|
||||
id: string;
|
||||
sourceFactId: string;
|
||||
content: string;
|
||||
priorityMultiplier: number;
|
||||
priorityMultiplierReason: string | null;
|
||||
scopeConversationId: string;
|
||||
createdAt?: string;
|
||||
};
|
||||
|
||||
export interface Entity<T> {
|
||||
construct: (data: T) => T;
|
||||
create: (data: T) => Promise<T>;
|
||||
createMany: (data: T[]) => Promise<T[]>;
|
||||
create: (data: Omit<T, "id">) => Promise<T>;
|
||||
createMany: (data: Omit<T, "id">[]) => Promise<T[]>;
|
||||
findAll: () => Promise<T[]>;
|
||||
findById: (id: ID) => Promise<T | undefined>;
|
||||
update: (id: ID, data: Partial<T>) => Promise<void>;
|
||||
delete: (id: ID) => Promise<void>;
|
||||
findById: (id: string) => Promise<T | undefined>;
|
||||
update: (id: string, data: Partial<T>) => Promise<void>;
|
||||
delete: (id: string) => Promise<void>;
|
||||
}
|
||||
|
||||
export interface ConversationEntity extends Entity<Conversation> {
|
||||
fetchMessages: (conversationId: string) => Promise<Array<CommittedMessage>>;
|
||||
}
|
||||
|
||||
export interface FactEntity extends Entity<Fact> {
|
||||
findByConversationId: (conversationId: string) => Promise<Array<Fact>>;
|
||||
}
|
||||
|
||||
export interface MessageEntity extends Entity<CommittedMessage> {
|
||||
findByConversationId: (
|
||||
conversationId: string
|
||||
) => Promise<Array<CommittedMessage>>;
|
||||
}
|
||||
|
||||
export type FactTriggerEntity = Entity<FactTrigger> & {
|
||||
findByFactId: (factId: string) => Promise<Array<FactTrigger>>;
|
||||
};
|
||||
|
||||
export interface ApplicationDatabase {
|
||||
conversations: ConversationEntity;
|
||||
factTriggers: FactTriggerEntity;
|
||||
facts: FactEntity;
|
||||
messages: MessageEntity;
|
||||
}
|
||||
|
||||
@@ -5,17 +5,17 @@ import type { UsersId } from './Users';
|
||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||
|
||||
/** Identifier type for public.conversations */
|
||||
export type ConversationsId = number & { __brand: 'public.conversations' };
|
||||
export type ConversationsId = string;
|
||||
|
||||
/** Represents the table public.conversations */
|
||||
export default interface ConversationsTable {
|
||||
id: ColumnType<ConversationsId, never, never>;
|
||||
id: ColumnType<ConversationsId, ConversationsId | undefined, ConversationsId>;
|
||||
|
||||
title: ColumnType<string | null, string | null, string | null>;
|
||||
title: ColumnType<string, string, string>;
|
||||
|
||||
createdAt: ColumnType<string | null, string | null, string | null>;
|
||||
createdAt: ColumnType<string, string | undefined, string>;
|
||||
|
||||
userId: ColumnType<UsersId | null, UsersId | null, UsersId | null>;
|
||||
userId: ColumnType<UsersId, UsersId, UsersId>;
|
||||
}
|
||||
|
||||
export type Conversations = Selectable<ConversationsTable>;
|
||||
|
||||
@@ -2,27 +2,26 @@
|
||||
// This file is automatically generated by Kanel. Do not modify manually.
|
||||
|
||||
import type { FactsId } from './Facts';
|
||||
import type { ConversationsId } from './Conversations';
|
||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||
|
||||
/** Identifier type for public.fact_triggers */
|
||||
export type FactTriggersId = number & { __brand: 'public.fact_triggers' };
|
||||
export type FactTriggersId = string;
|
||||
|
||||
/** Represents the table public.fact_triggers */
|
||||
export default interface FactTriggersTable {
|
||||
id: ColumnType<FactTriggersId, never, never>;
|
||||
id: ColumnType<FactTriggersId, FactTriggersId | undefined, FactTriggersId>;
|
||||
|
||||
sourceFactId: ColumnType<FactsId | null, FactsId | null, FactsId | null>;
|
||||
sourceFactId: ColumnType<FactsId, FactsId, FactsId>;
|
||||
|
||||
content: ColumnType<string | null, string | null, string | null>;
|
||||
content: ColumnType<string, string, string>;
|
||||
|
||||
priorityMultiplier: ColumnType<number | null, number | null, number | null>;
|
||||
priorityMultiplier: ColumnType<number, number | undefined, number>;
|
||||
|
||||
priorityMultiplierReason: ColumnType<string | null, string | null, string | null>;
|
||||
|
||||
scopeConversationId: ColumnType<ConversationsId | null, ConversationsId | null, ConversationsId | null>;
|
||||
scopeConversationId: ColumnType<string, string, string>;
|
||||
|
||||
createdAt: ColumnType<string | null, string | null, string | null>;
|
||||
createdAt: ColumnType<string, string | undefined, string>;
|
||||
}
|
||||
|
||||
export type FactTriggers = Selectable<FactTriggersTable>;
|
||||
|
||||
@@ -6,19 +6,19 @@ import type { MessagesId } from './Messages';
|
||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||
|
||||
/** Identifier type for public.facts */
|
||||
export type FactsId = number & { __brand: 'public.facts' };
|
||||
export type FactsId = string;
|
||||
|
||||
/** Represents the table public.facts */
|
||||
export default interface FactsTable {
|
||||
id: ColumnType<FactsId, never, never>;
|
||||
id: ColumnType<FactsId, FactsId | undefined, FactsId>;
|
||||
|
||||
userId: ColumnType<UsersId | null, UsersId | null, UsersId | null>;
|
||||
userId: ColumnType<UsersId, UsersId, UsersId>;
|
||||
|
||||
sourceMessageId: ColumnType<MessagesId | null, MessagesId | null, MessagesId | null>;
|
||||
sourceMessageId: ColumnType<MessagesId, MessagesId, MessagesId>;
|
||||
|
||||
content: ColumnType<string | null, string | null, string | null>;
|
||||
content: ColumnType<string, string, string>;
|
||||
|
||||
createdAt: ColumnType<string | null, string | null, string | null>;
|
||||
createdAt: ColumnType<string, string | undefined, string>;
|
||||
}
|
||||
|
||||
export type Facts = Selectable<FactsTable>;
|
||||
|
||||
@@ -6,11 +6,11 @@ import type { default as Role } from './Role';
|
||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||
|
||||
/** Identifier type for public.messages */
|
||||
export type MessagesId = number & { __brand: 'public.messages' };
|
||||
export type MessagesId = string;
|
||||
|
||||
/** Represents the table public.messages */
|
||||
export default interface MessagesTable {
|
||||
id: ColumnType<MessagesId, never, never>;
|
||||
id: ColumnType<MessagesId, MessagesId | undefined, MessagesId>;
|
||||
|
||||
conversationId: ColumnType<ConversationsId | null, ConversationsId | null, ConversationsId | null>;
|
||||
|
||||
@@ -18,9 +18,9 @@ export default interface MessagesTable {
|
||||
|
||||
runningSummary: ColumnType<string | null, string | null, string | null>;
|
||||
|
||||
created_at: ColumnType<string | null, string | null, string | null>;
|
||||
createdAt: ColumnType<string | null, string | null, string | null>;
|
||||
|
||||
role: ColumnType<Role | null, Role | null, Role | null>;
|
||||
role: ColumnType<Role, Role, Role>;
|
||||
|
||||
parts: ColumnType<unknown | null, unknown | null, unknown | null>;
|
||||
}
|
||||
|
||||
@@ -6,11 +6,11 @@ import type { MessagesId } from './Messages';
|
||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||
|
||||
/** Identifier type for public.tools */
|
||||
export type ToolsId = number & { __brand: 'public.tools' };
|
||||
export type ToolsId = string;
|
||||
|
||||
/** Represents the table public.tools */
|
||||
export default interface ToolsTable {
|
||||
id: ColumnType<ToolsId, never, never>;
|
||||
id: ColumnType<ToolsId, ToolsId | undefined, ToolsId>;
|
||||
|
||||
userId: ColumnType<UsersId | null, UsersId | null, UsersId | null>;
|
||||
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
import type { ColumnType, Selectable, Insertable, Updateable } from 'kysely';
|
||||
|
||||
/** Identifier type for public.users */
|
||||
export type UsersId = number & { __brand: 'public.users' };
|
||||
export type UsersId = string;
|
||||
|
||||
/** Represents the table public.users */
|
||||
export default interface UsersTable {
|
||||
id: ColumnType<UsersId, never, never>;
|
||||
id: ColumnType<UsersId, UsersId | undefined, UsersId>;
|
||||
|
||||
username: ColumnType<string | null, string | null, string | null>;
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
// export { db } from "./lowdb";
|
||||
export { db } from "./postgres";
|
||||
+103
-117
@@ -1,33 +1,17 @@
|
||||
import { Low } from "lowdb";
|
||||
import { JSONFile } from "lowdb/node";
|
||||
import type { CommittedMessage } from "../types";
|
||||
import type { Entity } from "./common";
|
||||
import type {
|
||||
Conversation,
|
||||
ConversationEntity,
|
||||
Fact,
|
||||
FactEntity,
|
||||
FactTrigger,
|
||||
FactTriggerEntity,
|
||||
MessageEntity,
|
||||
} from "./common";
|
||||
import { nanoid } from "nanoid";
|
||||
|
||||
export type Conversation = {
|
||||
id: string;
|
||||
title: string;
|
||||
userId: string;
|
||||
};
|
||||
|
||||
export type Fact = {
|
||||
id: string;
|
||||
userId: string;
|
||||
sourceMessageId: string;
|
||||
content: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
export type FactTrigger = {
|
||||
id: string;
|
||||
sourceFactId: string;
|
||||
content: string;
|
||||
priorityMultiplier: number;
|
||||
priorityMultiplierReason: string;
|
||||
scopeConversationId: string;
|
||||
createdAt: string;
|
||||
};
|
||||
|
||||
type DB = {
|
||||
conversations: Array<Conversation>;
|
||||
messages: Array</*{
|
||||
@@ -43,217 +27,219 @@ type DB = {
|
||||
factTriggers: Array<FactTrigger>;
|
||||
};
|
||||
|
||||
export const db = new Low<DB>(new JSONFile("db.json"), {
|
||||
export const dbClient = new Low<DB>(new JSONFile("db.json"), {
|
||||
conversations: [],
|
||||
messages: [],
|
||||
facts: [],
|
||||
factTriggers: [],
|
||||
});
|
||||
/** Initialize the database. Sets `db.data` to the default state if the file doesn't exist. */
|
||||
await db.read();
|
||||
await dbClient.read();
|
||||
/** Write the database to the file, in case it didn't exist before. */
|
||||
await db.write();
|
||||
await dbClient.write();
|
||||
|
||||
const conversations: Entity<Conversation, string> & {
|
||||
fetchMessages: (conversationId: string) => Promise<Array<CommittedMessage>>;
|
||||
} = {
|
||||
const conversations: ConversationEntity = {
|
||||
construct: (conversation: Conversation) => conversation,
|
||||
create: async (conversation: Conversation) => {
|
||||
conversation.id = conversation.id ?? nanoid();
|
||||
await db.data.conversations.push(conversation);
|
||||
await db.write();
|
||||
create: async (_conversation) => {
|
||||
const conversation = { ..._conversation, id: nanoid() };
|
||||
await dbClient.data.conversations.push(conversation);
|
||||
await dbClient.write();
|
||||
return conversation;
|
||||
},
|
||||
createMany: async (conversations: Array<Conversation>) => {
|
||||
await db.data.conversations.push(...conversations);
|
||||
await db.write();
|
||||
createMany: async (_conversations) => {
|
||||
const conversations = _conversations.map((c) => ({ ...c, id: nanoid() }));
|
||||
await dbClient.data.conversations.push(...conversations);
|
||||
await dbClient.write();
|
||||
return conversations;
|
||||
},
|
||||
findAll: async () => {
|
||||
return db.data.conversations;
|
||||
return dbClient.data.conversations;
|
||||
},
|
||||
findById: async (id) => {
|
||||
return db.data.conversations.find((c) => c.id === id);
|
||||
return dbClient.data.conversations.find((c) => c.id === id);
|
||||
},
|
||||
update: async (id, data: Partial<Conversation>) => {
|
||||
const conversationIndex = db.data.conversations.findIndex(
|
||||
const conversationIndex = dbClient.data.conversations.findIndex(
|
||||
(c) => c.id === id
|
||||
);
|
||||
if (conversationIndex === -1) throw new Error("Conversation not found");
|
||||
db.data.conversations[conversationIndex] = {
|
||||
...db.data.conversations[conversationIndex],
|
||||
dbClient.data.conversations[conversationIndex] = {
|
||||
...dbClient.data.conversations[conversationIndex],
|
||||
...data,
|
||||
};
|
||||
await db.write();
|
||||
await dbClient.write();
|
||||
},
|
||||
delete: async (id) => {
|
||||
db.data.conversations.splice(
|
||||
db.data.conversations.findIndex((c) => c.id === id),
|
||||
dbClient.data.conversations.splice(
|
||||
dbClient.data.conversations.findIndex((c) => c.id === id),
|
||||
1
|
||||
);
|
||||
const deletedMessageIds = db.data.messages
|
||||
const deletedMessageIds = dbClient.data.messages
|
||||
.filter((m) => m.conversationId === id)
|
||||
.map((m) => m.id);
|
||||
db.data.messages = db.data.messages.filter((m) => m.conversationId !== id);
|
||||
const deletedFactIds = db.data.facts
|
||||
dbClient.data.messages = dbClient.data.messages.filter(
|
||||
(m) => m.conversationId !== id
|
||||
);
|
||||
const deletedFactIds = dbClient.data.facts
|
||||
.filter((fact) => deletedMessageIds.includes(fact.sourceMessageId))
|
||||
.map((fact) => fact.id);
|
||||
db.data.facts = db.data.facts.filter(
|
||||
dbClient.data.facts = dbClient.data.facts.filter(
|
||||
(fact) => !deletedFactIds.includes(fact.id)
|
||||
);
|
||||
db.data.factTriggers = db.data.factTriggers.filter(
|
||||
dbClient.data.factTriggers = dbClient.data.factTriggers.filter(
|
||||
(factTrigger) => !deletedFactIds.includes(factTrigger.sourceFactId)
|
||||
);
|
||||
await db.write();
|
||||
await dbClient.write();
|
||||
},
|
||||
fetchMessages: async (conversationId) => {
|
||||
const rows = await db.data.messages.filter(
|
||||
const rows = await dbClient.data.messages.filter(
|
||||
(m) => m.conversationId === conversationId
|
||||
);
|
||||
return rows as Array<CommittedMessage>;
|
||||
},
|
||||
};
|
||||
|
||||
const factTriggers: Entity<FactTrigger, string> & {
|
||||
findByFactId: (factId: string) => Promise<Array<FactTrigger>>;
|
||||
} = {
|
||||
const factTriggers: FactTriggerEntity = {
|
||||
construct: (factTrigger: FactTrigger) => factTrigger,
|
||||
create: async (factTrigger: FactTrigger) => {
|
||||
factTrigger.id = factTrigger.id ?? nanoid();
|
||||
await db.data.factTriggers.push(factTrigger);
|
||||
await db.write();
|
||||
create: async (_factTrigger) => {
|
||||
const factTrigger = { ..._factTrigger, id: nanoid() };
|
||||
await dbClient.data.factTriggers.push(factTrigger);
|
||||
await dbClient.write();
|
||||
return factTrigger;
|
||||
},
|
||||
createMany: async (factTriggers: Array<FactTrigger>) => {
|
||||
await db.data.factTriggers.push(...factTriggers);
|
||||
await db.write();
|
||||
createMany: async (_factTriggers) => {
|
||||
const factTriggers = _factTriggers.map((f) => ({ ...f, id: nanoid() }));
|
||||
await dbClient.data.factTriggers.push(...factTriggers);
|
||||
await dbClient.write();
|
||||
return factTriggers;
|
||||
},
|
||||
findAll: async () => {
|
||||
return db.data.factTriggers;
|
||||
return dbClient.data.factTriggers;
|
||||
},
|
||||
findById: async (id) => {
|
||||
return db.data.factTriggers.find((factTrigger) => factTrigger.id === id);
|
||||
return dbClient.data.factTriggers.find(
|
||||
(factTrigger) => factTrigger.id === id
|
||||
);
|
||||
},
|
||||
update: async (id, data: Partial<FactTrigger>) => {
|
||||
const factTriggerIndex = db.data.factTriggers.findIndex(
|
||||
const factTriggerIndex = dbClient.data.factTriggers.findIndex(
|
||||
(factTrigger) => factTrigger.id === id
|
||||
);
|
||||
if (factTriggerIndex === -1) throw new Error("Fact trigger not found");
|
||||
db.data.factTriggers[factTriggerIndex] = {
|
||||
...db.data.factTriggers[factTriggerIndex],
|
||||
dbClient.data.factTriggers[factTriggerIndex] = {
|
||||
...dbClient.data.factTriggers[factTriggerIndex],
|
||||
...data,
|
||||
};
|
||||
await db.write();
|
||||
await dbClient.write();
|
||||
},
|
||||
delete: async (id) => {
|
||||
const deletedFactTriggerIndex = db.data.factTriggers.findIndex(
|
||||
const deletedFactTriggerIndex = dbClient.data.factTriggers.findIndex(
|
||||
(factTrigger) => factTrigger.id === id
|
||||
);
|
||||
if (deletedFactTriggerIndex === -1)
|
||||
throw new Error("Fact trigger not found");
|
||||
db.data.factTriggers.splice(deletedFactTriggerIndex, 1);
|
||||
await db.write();
|
||||
dbClient.data.factTriggers.splice(deletedFactTriggerIndex, 1);
|
||||
await dbClient.write();
|
||||
},
|
||||
findByFactId: async (factId: string) => {
|
||||
return db.data.factTriggers.filter(
|
||||
return dbClient.data.factTriggers.filter(
|
||||
(factTrigger) => factTrigger.sourceFactId === factId
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
const facts: Entity<Fact, string> & {
|
||||
findByConversationId: (conversationId: string) => Promise<Array<Fact>>;
|
||||
} = {
|
||||
const facts: FactEntity = {
|
||||
construct: (fact: Fact) => fact,
|
||||
create: async (fact: Fact) => {
|
||||
fact.id = fact.id ?? nanoid();
|
||||
await db.data.facts.push(fact);
|
||||
await db.write();
|
||||
create: async (_fact) => {
|
||||
const fact = { ..._fact, id: nanoid() };
|
||||
await dbClient.data.facts.push(fact);
|
||||
await dbClient.write();
|
||||
return fact;
|
||||
},
|
||||
createMany: async (facts: Array<Fact>) => {
|
||||
await db.data.facts.push(...facts);
|
||||
await db.write();
|
||||
createMany: async (_facts) => {
|
||||
const facts = _facts.map((f) => ({ ...f, id: nanoid() }));
|
||||
await dbClient.data.facts.push(...facts);
|
||||
await dbClient.write();
|
||||
return facts;
|
||||
},
|
||||
findAll: async () => {
|
||||
return db.data.facts;
|
||||
return dbClient.data.facts;
|
||||
},
|
||||
findById: async (id) => {
|
||||
return db.data.facts.find((fact) => fact.id === id);
|
||||
return dbClient.data.facts.find((fact) => fact.id === id);
|
||||
},
|
||||
update: async (id, data: Partial<Fact>) => {
|
||||
const factIndex = db.data.facts.findIndex((fact) => fact.id === id);
|
||||
const factIndex = dbClient.data.facts.findIndex((fact) => fact.id === id);
|
||||
if (factIndex === -1) throw new Error("Fact not found");
|
||||
db.data.facts[factIndex] = {
|
||||
...db.data.facts[factIndex],
|
||||
dbClient.data.facts[factIndex] = {
|
||||
...dbClient.data.facts[factIndex],
|
||||
...data,
|
||||
};
|
||||
await db.write();
|
||||
await dbClient.write();
|
||||
},
|
||||
delete: async (id) => {
|
||||
const deletedFactId = db.data.facts.findIndex((fact) => fact.id === id);
|
||||
const deletedFactId = dbClient.data.facts.findIndex(
|
||||
(fact) => fact.id === id
|
||||
);
|
||||
if (deletedFactId === -1) throw new Error("Fact not found");
|
||||
db.data.facts.splice(deletedFactId, 1);
|
||||
await db.write();
|
||||
dbClient.data.facts.splice(deletedFactId, 1);
|
||||
await dbClient.write();
|
||||
},
|
||||
findByConversationId: async (conversationId) => {
|
||||
const conversationMessageIds = db.data.messages
|
||||
const conversationMessageIds = dbClient.data.messages
|
||||
.filter((m) => m.conversationId === conversationId)
|
||||
.map((m) => m.id);
|
||||
const rows = await db.data.facts.filter((f) =>
|
||||
const rows = await dbClient.data.facts.filter((f) =>
|
||||
conversationMessageIds.includes(f.sourceMessageId)
|
||||
);
|
||||
return rows as Array<Fact>;
|
||||
},
|
||||
};
|
||||
|
||||
const messages: Entity<CommittedMessage, string> & {
|
||||
findByConversationId: (
|
||||
conversationId: string
|
||||
) => Promise<Array<CommittedMessage>>;
|
||||
} = {
|
||||
const messages: MessageEntity = {
|
||||
construct: (message: CommittedMessage) => message,
|
||||
create: async (message: CommittedMessage) => {
|
||||
message.id = message.id ?? nanoid();
|
||||
await db.data.messages.push(message);
|
||||
await db.write();
|
||||
create: async (_message) => {
|
||||
const message = { ..._message, id: nanoid() };
|
||||
await dbClient.data.messages.push(message);
|
||||
await dbClient.write();
|
||||
return message;
|
||||
},
|
||||
createMany: async (messages: Array<CommittedMessage>) => {
|
||||
await db.data.messages.push(...messages);
|
||||
await db.write();
|
||||
createMany: async (_messages) => {
|
||||
const messages = _messages.map((m) => ({ ...m, id: nanoid() }));
|
||||
await dbClient.data.messages.push(...messages);
|
||||
await dbClient.write();
|
||||
return messages;
|
||||
},
|
||||
findAll: async () => {
|
||||
return db.data.messages;
|
||||
return dbClient.data.messages;
|
||||
},
|
||||
findById: async (id) => {
|
||||
return db.data.messages.find((m) => m.id === id);
|
||||
return dbClient.data.messages.find((m) => m.id === id);
|
||||
},
|
||||
update: async (id, data: Partial<CommittedMessage>) => {
|
||||
const messageIndex = db.data.messages.findIndex((m) => m.id === id);
|
||||
const messageIndex = dbClient.data.messages.findIndex((m) => m.id === id);
|
||||
if (messageIndex === -1) throw new Error("Message not found");
|
||||
db.data.messages[messageIndex] = {
|
||||
...db.data.messages[messageIndex],
|
||||
dbClient.data.messages[messageIndex] = {
|
||||
...dbClient.data.messages[messageIndex],
|
||||
...data,
|
||||
};
|
||||
await db.write();
|
||||
await dbClient.write();
|
||||
},
|
||||
delete: async (id) => {
|
||||
db.data.messages.splice(
|
||||
db.data.messages.findIndex((m) => m.id === id),
|
||||
dbClient.data.messages.splice(
|
||||
dbClient.data.messages.findIndex((m) => m.id === id),
|
||||
1
|
||||
);
|
||||
await db.write();
|
||||
await dbClient.write();
|
||||
},
|
||||
findByConversationId: async (conversationId) => {
|
||||
return db.data.messages.filter((m) => m.conversationId === conversationId);
|
||||
return dbClient.data.messages.filter(
|
||||
(m) => m.conversationId === conversationId
|
||||
);
|
||||
},
|
||||
};
|
||||
|
||||
export const _db = {
|
||||
export const db = {
|
||||
conversations,
|
||||
factTriggers,
|
||||
facts,
|
||||
|
||||
+229
-1
@@ -1,6 +1,14 @@
|
||||
import { Pool } from "pg";
|
||||
import { Kysely, PostgresDialect } from "kysely";
|
||||
import type Database from "./generated/Database";
|
||||
import type {
|
||||
ConversationEntity,
|
||||
FactEntity,
|
||||
FactTriggerEntity,
|
||||
MessageEntity,
|
||||
} from "./common.ts";
|
||||
import type { Messages } from "./generated/public/Messages";
|
||||
import type { CommittedMessage } from "../types";
|
||||
|
||||
export const pool = new Pool({
|
||||
connectionString:
|
||||
@@ -16,6 +24,226 @@ const dialect = new PostgresDialect({
|
||||
// knows your database structure.
|
||||
// Dialect is passed to Kysely's constructor, and from now on, Kysely knows how
|
||||
// to communicate with your database.
|
||||
export const db = new Kysely<Database>({
|
||||
export const dbClient = new Kysely<Database>({
|
||||
dialect,
|
||||
});
|
||||
|
||||
const conversations: ConversationEntity = {
|
||||
construct: (conversation) => conversation,
|
||||
create: async (conversation) => {
|
||||
const insertedRows = await dbClient
|
||||
.insertInto("conversations")
|
||||
.values(conversation)
|
||||
.returningAll()
|
||||
.execute();
|
||||
return insertedRows[0];
|
||||
},
|
||||
createMany: async (conversations) => {
|
||||
const insertedRows = await dbClient
|
||||
.insertInto("conversations")
|
||||
.values(conversations)
|
||||
.returningAll()
|
||||
.execute();
|
||||
return insertedRows;
|
||||
},
|
||||
findAll: async () => {
|
||||
const rows = await dbClient
|
||||
.selectFrom("conversations")
|
||||
.selectAll()
|
||||
.execute();
|
||||
return rows;
|
||||
},
|
||||
findById: async (id) => {
|
||||
const row = await dbClient
|
||||
.selectFrom("conversations")
|
||||
.selectAll()
|
||||
.where("id", "=", id)
|
||||
.execute();
|
||||
return row[0];
|
||||
},
|
||||
update: async (id, data) => {
|
||||
await dbClient
|
||||
.updateTable("conversations")
|
||||
.set(data)
|
||||
.where("id", "=", id)
|
||||
.execute();
|
||||
},
|
||||
delete: async (id) => {
|
||||
await dbClient.deleteFrom("conversations").where("id", "=", id).execute();
|
||||
},
|
||||
fetchMessages: async (conversationId) => {
|
||||
const rows = await dbClient
|
||||
.selectFrom("messages")
|
||||
.selectAll()
|
||||
.where("conversationId", "=", conversationId)
|
||||
.execute();
|
||||
return rows as Array<CommittedMessage>;
|
||||
},
|
||||
};
|
||||
|
||||
const facts: FactEntity = {
|
||||
construct: (fact) => fact,
|
||||
create: async (fact) => {
|
||||
const insertedRows = await dbClient
|
||||
.insertInto("facts")
|
||||
.values(fact)
|
||||
.returningAll()
|
||||
.execute();
|
||||
return insertedRows[0];
|
||||
},
|
||||
createMany: async (facts) => {
|
||||
const insertedRows = await dbClient
|
||||
.insertInto("facts")
|
||||
.values(facts)
|
||||
.returningAll()
|
||||
.execute();
|
||||
return insertedRows;
|
||||
},
|
||||
findAll: async () => {
|
||||
const rows = await dbClient.selectFrom("facts").selectAll().execute();
|
||||
return rows;
|
||||
},
|
||||
findById: async (id) => {
|
||||
const row = await dbClient
|
||||
.selectFrom("facts")
|
||||
.selectAll()
|
||||
.where("id", "=", id)
|
||||
.execute();
|
||||
return row[0];
|
||||
},
|
||||
update: async (id, data) => {
|
||||
await dbClient
|
||||
.updateTable("facts")
|
||||
.set(data)
|
||||
.where("id", "=", id)
|
||||
.execute();
|
||||
},
|
||||
delete: async (id) => {
|
||||
await dbClient.deleteFrom("facts").where("id", "=", id).execute();
|
||||
},
|
||||
findByConversationId: async (conversationId) => {
|
||||
const rows = await dbClient
|
||||
.selectFrom("facts")
|
||||
.innerJoin("messages", "messages.id", "facts.sourceMessageId")
|
||||
.selectAll("facts")
|
||||
.where("conversationId", "=", conversationId)
|
||||
.execute();
|
||||
return rows;
|
||||
},
|
||||
};
|
||||
|
||||
const factTriggers: FactTriggerEntity = {
|
||||
construct: (factTrigger) => factTrigger,
|
||||
create: async (factTrigger) => {
|
||||
const insertedRows = await dbClient
|
||||
.insertInto("fact_triggers")
|
||||
.values(factTrigger)
|
||||
.returningAll()
|
||||
.execute();
|
||||
return insertedRows[0];
|
||||
},
|
||||
createMany: async (factTriggers) => {
|
||||
const insertedRows = await dbClient
|
||||
.insertInto("fact_triggers")
|
||||
.values(factTriggers)
|
||||
.returningAll()
|
||||
.execute();
|
||||
return insertedRows;
|
||||
},
|
||||
findAll: async () => {
|
||||
const rows = await dbClient
|
||||
.selectFrom("fact_triggers")
|
||||
.selectAll()
|
||||
.execute();
|
||||
return rows;
|
||||
},
|
||||
findById: async (id) => {
|
||||
const row = await dbClient
|
||||
.selectFrom("fact_triggers")
|
||||
.selectAll()
|
||||
.where("id", "=", id)
|
||||
.execute();
|
||||
return row[0];
|
||||
},
|
||||
update: async (id, data) => {
|
||||
await dbClient
|
||||
.updateTable("fact_triggers")
|
||||
.set(data)
|
||||
.where("id", "=", id)
|
||||
.execute();
|
||||
},
|
||||
delete: async (id) => {
|
||||
await dbClient.deleteFrom("fact_triggers").where("id", "=", id).execute();
|
||||
},
|
||||
findByFactId: async (factId) => {
|
||||
const rows = await dbClient
|
||||
.selectFrom("fact_triggers")
|
||||
.innerJoin("facts", "facts.id", "fact_triggers.sourceFactId")
|
||||
.selectAll("fact_triggers")
|
||||
.where("sourceFactId", "=", factId)
|
||||
.execute();
|
||||
return rows;
|
||||
},
|
||||
};
|
||||
|
||||
const messages: MessageEntity = {
|
||||
construct: (message) => message,
|
||||
create: async (message) => {
|
||||
const insertedRows = await dbClient
|
||||
.insertInto("messages")
|
||||
.values({ ...message, parts: JSON.stringify(message.parts) })
|
||||
.returningAll()
|
||||
.execute();
|
||||
return insertedRows[0] as CommittedMessage;
|
||||
},
|
||||
createMany: async (messages) => {
|
||||
const insertedRows = await dbClient
|
||||
.insertInto("messages")
|
||||
.values(
|
||||
messages.map((message) => ({
|
||||
...message,
|
||||
parts: JSON.stringify(message.parts),
|
||||
}))
|
||||
)
|
||||
.returningAll()
|
||||
.execute();
|
||||
return insertedRows as Array<CommittedMessage>;
|
||||
},
|
||||
findAll: async () => {
|
||||
const rows = await dbClient.selectFrom("messages").selectAll().execute();
|
||||
return rows as Array<CommittedMessage>;
|
||||
},
|
||||
findById: async (id) => {
|
||||
const row = await dbClient
|
||||
.selectFrom("messages")
|
||||
.selectAll()
|
||||
.where("id", "=", id)
|
||||
.execute();
|
||||
return row[0] as CommittedMessage;
|
||||
},
|
||||
update: async (id, data) => {
|
||||
await dbClient
|
||||
.updateTable("messages")
|
||||
.set(data)
|
||||
.where("id", "=", id)
|
||||
.execute();
|
||||
},
|
||||
delete: async (id) => {
|
||||
await dbClient.deleteFrom("messages").where("id", "=", id).execute();
|
||||
},
|
||||
findByConversationId: async (conversationId) => {
|
||||
const rows = await dbClient
|
||||
.selectFrom("messages")
|
||||
.selectAll()
|
||||
.where("conversationId", "=", conversationId)
|
||||
.execute();
|
||||
return rows as Array<CommittedMessage>;
|
||||
},
|
||||
};
|
||||
|
||||
export const db = {
|
||||
conversations,
|
||||
facts,
|
||||
factTriggers,
|
||||
messages,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user