feat: add bot and api services with config, logger and database packages

- Add bot service with telegram integration and webhook/polling modes
- Add api service with hono, swagger and zod-openapi
- Create config package for environment variable management
- Create logger package for colored console logging
- Create database package with prisma integration
- Remove next.js web and docs apps
- Update turbo.json for new services
- Add dockerfiles and gitea workflows for deployment
This commit is contained in:
Yuu Ottosoka
2025-07-08 19:46:08 +03:00
parent 393c175460
commit 71365836d3
85 changed files with 5635 additions and 4333 deletions

4
apps/bot/.env.example Normal file
View File

@@ -0,0 +1,4 @@
BOT_TOKEN="your-bot-token"
WEBHOOK_URL="your-webhook-url"
PORT=3000
MODE=polling or webhook

58
apps/bot/Dockerfile Normal file
View File

@@ -0,0 +1,58 @@
FROM node:lts-alpine AS base
# Install system dependencies needed for canvas and other native modules
RUN apk add --no-cache \
python3 \
make \
g++ \
cairo-dev \
jpeg-dev \
pango-dev \
musl-dev \
giflib-dev \
pixman-dev \
pangomm-dev \
libjpeg-turbo-dev \
freetype-dev
# Install turbo globally
RUN npm install -g turbo
FROM base AS pruner
WORKDIR /app
COPY . .
RUN turbo prune bot --docker
# Add lockfile and package.json's of isolated subworkspace
FROM base AS installer
WORKDIR /app
# First install the dependencies (this is done before copying the source code to better leverage Docker layer caching)
COPY .gitignore .gitignore
COPY --from=pruner /app/out/json/ .
COPY --from=pruner /app/out/package-lock.json ./package-lock.json
RUN npm ci
# Build the project
COPY --from=pruner /app/out/full/ .
RUN turbo run build --filter=bot...
FROM base AS runner
WORKDIR /app
# Don't run production as root
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 bot
USER bot
COPY --from=installer --chown=bot:nodejs /app/apps/bot/dist ./dist
COPY --from=installer --chown=bot:nodejs /app/apps/bot/package.json ./package.json
# Copy node_modules from installer stage
COPY --from=installer --chown=bot:nodejs /app/node_modules ./node_modules
COPY --from=installer --chown=bot:nodejs /app/apps/bot/node_modules ./apps/bot/node_modules
# Expose port
EXPOSE 3000
CMD ["npm", "start"]

1
apps/bot/README.md Normal file
View File

@@ -0,0 +1 @@
# `bot`

25
apps/bot/package.json Normal file
View File

@@ -0,0 +1,25 @@
{
"name": "bot",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "NODE_PATH=./src tsnd --respawn --transpile-only --exit-child src/index.ts",
"start": "NODE_PATH=./dist node ./dist/index.js",
"build": "tsc"
},
"dependencies": {
"@hono/node-server": "^1.15.0",
"@repo/config": "*",
"@repo/db": "*",
"@repo/typescript-config": "*",
"@repo/logger": "*",
"dotenv": "^17.1.0",
"grammy": "^1.37.0",
"hono": "^4.8.4",
"zod": "^3.25.76"
},
"devDependencies": {
"ts-node-dev": "^2.0.0",
"typescript": "^5.8.3"
}
}

12
apps/bot/src/config.ts Normal file
View File

@@ -0,0 +1,12 @@
import { createConfig } from '@repo/config';
import z from 'zod';
import 'dotenv/config';
export const config = createConfig({
schema: {
BOT_TOKEN: z.string(),
WEBHOOK_URI: z.string(),
PORT: z.string().default('3000'),
MODE: z.enum(['polling', 'webhook']).default('polling'),
},
});

33
apps/bot/src/index.ts Normal file
View File

@@ -0,0 +1,33 @@
import { serve } from '@hono/node-server';
import { config } from './config';
import { Bot, webhookCallback } from 'grammy';
import { Hono } from 'hono';
import { logger } from '@repo/logger';
const bot = new Bot(config.BOT_TOKEN);
bot.command('start', (ctx) => ctx.reply('Привет, мир'));
if (config.MODE === 'webhook') {
logger.info('Starting in webhook mode...');
const app = new Hono();
app.post(`/${config.WEBHOOK_URI}`, webhookCallback(bot, 'hono'));
serve(
{
fetch: app.fetch,
port: Number(config.PORT),
},
(info) => {
logger.info(`Server is running on localhost:${info.port}`);
}
);
} else {
logger.info('Starting in polling mode...');
bot.start({
onStart: () => {
logger.info('Bot started polling...');
},
});
}

9
apps/bot/tsconfig.json Normal file
View File

@@ -0,0 +1,9 @@
{
"extends": "@repo/typescript-config/base.json",
"compilerOptions": {
"outDir": "dist",
"rootDir": "src"
},
"include": ["src"],
"exclude": ["node_modules", "dist"]
}