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; types.setTypeParser(types.builtins.TIMESTAMPTZ, (val) => new Date(val).toISOString(), ); type GraphileJob = { taskIdentifier: string; payload: Record; 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; 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 | undefined; scope: string | undefined; id_token: string | undefined; session_state: string | undefined; }; Session: { id: GeneratedAlways; userId: string; sessionToken: string; expires: Date; }; VerificationToken: { identifier: string; token: string; expires: Date; }; WhatsappBot: { id: GeneratedAlways; name: string; description: string; phoneNumber: string; token: string; qrCode: string; verified: boolean; userId: string; createdBy: string; createdAt: Date; updatedAt: Date; }; FacebookBot: { id: GeneratedAlways; 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; createdAt: GeneratedAlways; updatedAt: GeneratedAlways; }; VoiceLine: { id: GeneratedAlways; name: string; description: string; createdBy: string; createdAt: Date; updatedAt: Date; }; SignalBot: { id: GeneratedAlways; name: string; description: string; phoneNumber: string; qrCode: string; token: string; verified: boolean; createdAt: Date; updatedAt: Date; }; Webhook: { id: GeneratedAlways; name: string; description: string; backendType: string; backendId: string; endpointUrl: string; httpMethod: "post" | "put"; headers: Record; createdBy: string; createdAt: Date; updatedAt: Date; }; } export type FacebookBot = Selectable; export type SignalBot = Selectable; export type WhatsappBot = Selectable; export type VoiceLine = Selectable; export type Webhook = Selectable; export type User = Selectable; // Lazy database initialization to avoid errors during build time let _db: KyselyAuth | undefined; function getDb(): KyselyAuth { 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({ 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, { 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; }, });