LOG_LEVEL |
diff --git a/prisma/migrations/20230809070833_initial/migration.sql b/prisma/migrations/20230809070833_initial/migration.sql
new file mode 100644
index 00000000..0948999a
--- /dev/null
+++ b/prisma/migrations/20230809070833_initial/migration.sql
@@ -0,0 +1,10 @@
+-- CreateTable
+CREATE TABLE "users" (
+ "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
+ "telegram_id" BIGINT NOT NULL,
+ "updated_at" DATETIME NOT NULL,
+ "created_at" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
+);
+
+-- CreateIndex
+CREATE UNIQUE INDEX "users_telegram_id_key" ON "users"("telegram_id");
diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml
new file mode 100644
index 00000000..e5e5c470
--- /dev/null
+++ b/prisma/migrations/migration_lock.toml
@@ -0,0 +1,3 @@
+# Please do not edit this file manually
+# It should be added in your version-control system (i.e. Git)
+provider = "sqlite"
\ No newline at end of file
diff --git a/prisma/schema.prisma b/prisma/schema.prisma
new file mode 100644
index 00000000..4376a914
--- /dev/null
+++ b/prisma/schema.prisma
@@ -0,0 +1,17 @@
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "sqlite"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id Int @id @default(autoincrement())
+ telegramId BigInt @unique @map("telegram_id")
+ updatedAt DateTime @updatedAt @map("updated_at")
+ createdAt DateTime @default(now()) @map("created_at")
+
+ @@map(name: "users")
+}
\ No newline at end of file
diff --git a/src/bot/context.ts b/src/bot/context.ts
index bd97ed17..6342848b 100644
--- a/src/bot/context.ts
+++ b/src/bot/context.ts
@@ -6,6 +6,7 @@ import type { I18nFlavor } from '@grammyjs/i18n'
import type { ParseModeFlavor } from '@grammyjs/parse-mode'
import type { Logger } from '#root/logger.js'
import type { Config } from '#root/config.js'
+import type { PrismaClientX } from '#root/prisma/index.js'
export interface SessionData {
// field?: string;
@@ -14,6 +15,7 @@ export interface SessionData {
interface ExtendedContextFlavor {
logger: Logger
config: Config
+ prisma: PrismaClientX
}
export type Context = ParseModeFlavor<
@@ -29,15 +31,18 @@ export type Context = ParseModeFlavor<
interface Dependencies {
logger: Logger
config: Config
+ prisma: PrismaClientX
}
export function createContextConstructor(
{
logger,
config,
+ prisma,
}: Dependencies,
) {
return class extends DefaultContext implements ExtendedContextFlavor {
+ prisma: PrismaClientX
logger: Logger
config: Config
@@ -48,6 +53,7 @@ export function createContextConstructor(
update_id: this.update.update_id,
})
this.config = config
+ this.prisma = prisma
}
} as unknown as new (update: Update, api: Api, me: UserFromGetMe) => Context
}
diff --git a/src/bot/index.ts b/src/bot/index.ts
index facc7f2b..897d6867 100644
--- a/src/bot/index.ts
+++ b/src/bot/index.ts
@@ -16,10 +16,12 @@ import { createContextConstructor } from '#root/bot/context.js'
import { i18n, isMultipleLocales } from '#root/bot/i18n.js'
import type { Logger } from '#root/logger.js'
import type { Config } from '#root/config.js'
+import type { PrismaClientX } from '#root/prisma/index.js'
interface Dependencies {
config: Config
logger: Logger
+ prisma: PrismaClientX
}
interface Options {
@@ -35,6 +37,7 @@ export function createBot(token: string, dependencies: Dependencies, options: Op
const {
config,
logger,
+ prisma,
} = dependencies
const bot = new TelegramBot(token, {
@@ -42,6 +45,7 @@ export function createBot(token: string, dependencies: Dependencies, options: Op
ContextConstructor: createContextConstructor({
logger,
config,
+ prisma,
}),
})
const protectedBot = bot.errorBoundary(errorHandler)
diff --git a/src/main.ts b/src/main.ts
index 69bb959a..f0aaad7f 100644
--- a/src/main.ts
+++ b/src/main.ts
@@ -3,6 +3,7 @@
import process from 'node:process'
import { type RunnerHandle, run } from '@grammyjs/runner'
import { logger } from '#root/logger.js'
+import { prisma } from '#root/prisma/index.js'
import { createBot } from '#root/bot/index.js'
import type { PollingConfig, WebhookConfig } from '#root/config.js'
import { config } from '#root/config.js'
@@ -12,6 +13,7 @@ async function startPolling(config: PollingConfig) {
const bot = createBot(config.botToken, {
config,
logger,
+ prisma,
})
let runner: undefined | RunnerHandle
@@ -26,6 +28,9 @@ async function startPolling(config: PollingConfig) {
bot.api.deleteWebhook(),
])
+ // connect to database
+ await prisma.$connect()
+
// start bot
runner = run(bot, {
runner: {
@@ -45,6 +50,7 @@ async function startWebhook(config: WebhookConfig) {
const bot = createBot(config.botToken, {
config,
logger,
+ prisma,
})
const server = createServer({
bot,
@@ -62,6 +68,9 @@ async function startWebhook(config: WebhookConfig) {
await serverManager.stop()
})
+ // connect to database
+ await prisma.$connect()
+
// to prevent receiving updates before the bot is ready
await bot.init()
diff --git a/src/prisma/index.ts b/src/prisma/index.ts
new file mode 100644
index 00000000..c7d11219
--- /dev/null
+++ b/src/prisma/index.ts
@@ -0,0 +1,59 @@
+import type { Prisma } from '@prisma/client'
+import { PrismaClient } from '@prisma/client'
+import { logger } from '#root/logger.js'
+
+export const prisma = new PrismaClient({
+ log: [
+ {
+ emit: 'event',
+ level: 'query',
+ },
+ {
+ emit: 'event',
+ level: 'error',
+ },
+ {
+ emit: 'event',
+ level: 'info',
+ },
+ {
+ emit: 'event',
+ level: 'warn',
+ },
+ ],
+})
+
+export type PrismaClientX = typeof prisma
+
+prisma.$on('query', (event: Prisma.QueryEvent) => {
+ logger.debug({
+ msg: 'database query',
+ query: event.query,
+ params: event.params,
+ duration: event.duration,
+ })
+})
+
+prisma.$on('error', (event: Prisma.LogEvent) => {
+ logger.error({
+ msg: 'database error',
+ target: event.target,
+ message: event.message,
+ })
+})
+
+prisma.$on('info', (event: Prisma.LogEvent) => {
+ logger.info({
+ msg: 'database info',
+ target: event.target,
+ message: event.message,
+ })
+})
+
+prisma.$on('warn', (event: Prisma.LogEvent) => {
+ logger.warn({
+ msg: 'database warning',
+ target: event.target,
+ message: event.message,
+ })
+})
|