197 lines
4.9 KiB
TypeScript
197 lines
4.9 KiB
TypeScript
import { PostgresDialect, CamelCasePlugin } from "kysely";
|
|
import type { GeneratedAlways, Generated, ColumnType, Selectable } from "kysely";
|
|
import pg from "pg";
|
|
import { KyselyAuth } from "@auth/kysely-adapter";
|
|
const { Pool, types } = pg;
|
|
|
|
type Timestamp = ColumnType<Date, Date | string>;
|
|
|
|
types.setTypeParser(types.builtins.TIMESTAMPTZ, (val) => new Date(val).toISOString());
|
|
|
|
type GraphileJob = {
|
|
taskIdentifier: string;
|
|
payload: Record<string, any>;
|
|
priority: number;
|
|
maxAttempts: number;
|
|
key: string;
|
|
queueName: string;
|
|
};
|
|
|
|
export const addGraphileJob = async (jobInfo: GraphileJob) => {
|
|
// await db.insertInto("graphile_worker.jobs").values(jobInfo).execute();
|
|
};
|
|
|
|
export interface Database {
|
|
User: {
|
|
id: string;
|
|
name: string | null;
|
|
email: string;
|
|
emailVerified: Date | null;
|
|
image: string | null;
|
|
};
|
|
|
|
Account: {
|
|
id: GeneratedAlways<string>;
|
|
userId: string;
|
|
type: "oidc" | "oauth" | "email" | "webauthn";
|
|
provider: string;
|
|
providerAccountId: string;
|
|
refresh_token: string | undefined;
|
|
access_token: string | undefined;
|
|
expires_at: number | undefined;
|
|
token_type: Lowercase<string> | undefined;
|
|
scope: string | undefined;
|
|
id_token: string | undefined;
|
|
session_state: string | undefined;
|
|
};
|
|
|
|
Session: {
|
|
id: GeneratedAlways<string>;
|
|
userId: string;
|
|
sessionToken: string;
|
|
expires: Date;
|
|
};
|
|
|
|
VerificationToken: {
|
|
identifier: string;
|
|
token: string;
|
|
expires: Date;
|
|
};
|
|
|
|
WhatsappBot: {
|
|
id: GeneratedAlways<string>;
|
|
name: string;
|
|
description: string;
|
|
phoneNumber: string;
|
|
token: string;
|
|
qrCode: string;
|
|
verified: boolean;
|
|
userId: string;
|
|
createdBy: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
|
|
FacebookBot: {
|
|
id: GeneratedAlways<string>;
|
|
name: string | null;
|
|
description: string | null;
|
|
token: string | null;
|
|
pageAccessToken: string | null;
|
|
appSecret: string | null;
|
|
verifyToken: string | null;
|
|
pageId: string | null;
|
|
appId: string | null;
|
|
userId: string | null;
|
|
verified: Generated<boolean>;
|
|
createdAt: GeneratedAlways<Timestamp>;
|
|
updatedAt: GeneratedAlways<Timestamp>;
|
|
};
|
|
|
|
VoiceLine: {
|
|
id: GeneratedAlways<string>;
|
|
name: string;
|
|
description: string;
|
|
createdBy: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
|
|
SignalBot: {
|
|
id: GeneratedAlways<string>;
|
|
name: string;
|
|
description: string;
|
|
phoneNumber: string;
|
|
qrCode: string;
|
|
token: string;
|
|
verified: boolean;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
|
|
Webhook: {
|
|
id: GeneratedAlways<string>;
|
|
name: string;
|
|
description: string;
|
|
backendType: string;
|
|
backendId: string;
|
|
endpointUrl: string;
|
|
httpMethod: "post" | "put";
|
|
headers: Record<string, any>;
|
|
createdBy: string;
|
|
createdAt: Date;
|
|
updatedAt: Date;
|
|
};
|
|
}
|
|
|
|
export type FacebookBot = Selectable<Database["FacebookBot"]>;
|
|
export type SignalBot = Selectable<Database["SignalBot"]>;
|
|
export type WhatsappBot = Selectable<Database["WhatsappBot"]>;
|
|
export type VoiceLine = Selectable<Database["VoiceLine"]>;
|
|
export type Webhook = Selectable<Database["Webhook"]>;
|
|
export type User = Selectable<Database["User"]>;
|
|
|
|
// Lazy database initialization to avoid errors during build time
|
|
let _db: KyselyAuth<Database> | undefined;
|
|
|
|
function getDb(): KyselyAuth<Database> {
|
|
if (_db) {
|
|
return _db;
|
|
}
|
|
|
|
// Validate environment variables
|
|
const DATABASE_HOST = process.env.DATABASE_HOST;
|
|
const DATABASE_NAME = process.env.DATABASE_NAME;
|
|
const DATABASE_PORT = process.env.DATABASE_PORT;
|
|
const DATABASE_USER = process.env.DATABASE_USER;
|
|
const DATABASE_PASSWORD = process.env.DATABASE_PASSWORD;
|
|
|
|
if (
|
|
!DATABASE_HOST ||
|
|
!DATABASE_NAME ||
|
|
!DATABASE_PORT ||
|
|
!DATABASE_USER ||
|
|
!DATABASE_PASSWORD
|
|
) {
|
|
throw new Error(
|
|
"Missing required database environment variables: DATABASE_HOST, DATABASE_NAME, DATABASE_PORT, DATABASE_USER, DATABASE_PASSWORD",
|
|
);
|
|
}
|
|
|
|
const port = parseInt(DATABASE_PORT, 10);
|
|
if (isNaN(port) || port < 1 || port > 65535) {
|
|
throw new Error(
|
|
`Invalid DATABASE_PORT: ${DATABASE_PORT}. Must be a number between 1 and 65535.`,
|
|
);
|
|
}
|
|
|
|
_db = new KyselyAuth<Database>({
|
|
dialect: new PostgresDialect({
|
|
pool: new Pool({
|
|
host: DATABASE_HOST,
|
|
database: DATABASE_NAME,
|
|
port,
|
|
user: DATABASE_USER,
|
|
password: DATABASE_PASSWORD,
|
|
}),
|
|
}) as any,
|
|
plugins: [new CamelCasePlugin() as any],
|
|
});
|
|
|
|
return _db;
|
|
}
|
|
|
|
// Export db as a getter that lazily initializes the database
|
|
export const db = new Proxy({} as KyselyAuth<Database>, {
|
|
get(_target, prop) {
|
|
const instance = getDb();
|
|
const value = (instance as any)[prop];
|
|
|
|
// If it's a function, bind it to the actual instance to preserve 'this' context
|
|
if (typeof value === "function") {
|
|
return value.bind(instance);
|
|
}
|
|
|
|
return value;
|
|
},
|
|
});
|