Skip to content

Conversation

@Jax0312
Copy link
Contributor

@Jax0312 Jax0312 commented Jan 15, 2026

Implemented all backend API per previously discussed specifications.

Copy link

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR implements a complete backend prototype for a QueueBot application using Fastify, Prisma, and TypeScript. It includes JWT-based authentication, admin management, and queue operations with Telegram Mini App integration.

Changes:

  • Migrated from CommonJS to ES modules with updated TypeScript configuration
  • Implemented JWT authentication with Telegram Mini App validation
  • Created database schema with Prisma (Admin, Queue, QueueConfig, AdminRequester models)
  • Built REST API with public and private routes for queue and admin management

Reviewed changes

Copilot reviewed 22 out of 23 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
backend/tsconfig.json Updated to ESNext/NodeNext with stricter type checking
backend/package.json Added dependencies (jose, fastify plugins, pg adapter) and switched to ESM
backend/src/server.ts Main server setup with CORS, JWT auth, and route autoloading
backend/src/types.ts Type definitions for Fastify extensions and Telegram data
backend/src/shared.ts Admin authorization middleware
backend/src/prismaPlugin.ts Prisma client plugin with PostgreSQL adapter
backend/src/queueConfigPlugin.ts Queue configuration caching plugin
backend/src/routes/public/auth/index.ts Telegram Mini App authentication endpoint
backend/src/routes/private/queue/*.ts Queue management endpoints (status, config, next, entries)
backend/src/routes/private/admins/*.ts Admin and admin request management endpoints
backend/prisma/schema.prisma Database schema with 4 models
backend/README.md Comprehensive API documentation
Files not reviewed (1)
  • backend/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +27 to +34
let config = await fastify.prisma.queueConfig.findFirst().then((queueConfig) => queueConfig);

if (config === null) {
reply.code(500);
throw new Error("No queue configured");
}

config.isOpen = request.query.open;
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing input validation: The 'open' query parameter is parsed from stringbool but there's no validation that the config exists before trying to update it. The check happens after attempting to set the property on a potentially null object.

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no issue here

// hit Telegram API to send user message
fetch(`https://api.telegram.org/bot${BOT_TOKEN}/test/sendMessage?${queryString}`, {
method: 'POST',
})
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing error handling for the Telegram API fetch request. If the request fails, there's no catch block or error handling, which could lead to unhandled promise rejections.

Suggested change
})
}).catch((error) => {
fastify.log.error({ err: error }, 'Failed to send Telegram notification');
});

Copilot uses AI. Check for mistakes.
import type {FastifyPluginAsyncZod} from "fastify-type-provider-zod";
import {isAdmin} from "../../../shared.js";

const BOT_TOKEN = process.env.BOT_TOKEN;
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The BOT_TOKEN is accessed without the non-null assertion operator, unlike other files, and could be undefined. Add validation or use the non-null assertion consistently.

Suggested change
const BOT_TOKEN = process.env.BOT_TOKEN;
const BOT_TOKEN = process.env.BOT_TOKEN!;

Copilot uses AI. Check for mistakes.
Comment on lines 8 to 9
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL })

Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The database URL environment variable is accessed without validation. If DATABASE_URL is undefined, the PrismaClient will fail to initialize. Add validation at startup.

Suggested change
const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL })
const databaseUrl = process.env.DATABASE_URL
if (!databaseUrl) {
throw new Error('DATABASE_URL environment variable is not set. Please configure it before starting the server.')
}
const adapter = new PrismaPg({ connectionString: databaseUrl })

Copilot uses AI. Check for mistakes.
Comment on lines +9 to +12
fastify.prisma.admin.count().then((count) => console.log(count));

});

Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The public index route logs admin count to console but doesn't return any response. This will cause Fastify to timeout or send an empty response. Either remove this TODO endpoint or add a proper reply.

Suggested change
fastify.prisma.admin.count().then((count) => console.log(count));
});
const count = await fastify.prisma.admin.count();
console.log(count);
return reply.send({ adminCount: count });
});

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

will remove this example endpoint

Comment on lines +16 to +17
reply.code(500);
throw new Error(e.message);
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error from catch block is being re-thrown, but the reply code has already been set. This will cause Fastify to log a warning about attempting to send headers after they've been sent. The catch block should return or handle the error properly without throwing.

Suggested change
reply.code(500);
throw new Error(e.message);
// Handle internal errors without re-throwing after setting the reply code
if (request.log && typeof request.log.error === "function") {
request.log.error(e, "Error while checking admin privileges");
}
if (!reply.sent) {
reply.code(500).send({ error: e.message });
}

Copilot uses AI. Check for mistakes.
const queryString = new URLSearchParams(
{'chat_id': allEntries[i]!.telegram_id, 'text': message, 'parse_mode': 'Markdown'}).toString();
// hit Telegram API to send user message
fetch(`https://api.telegram.org/bot${BOT_TOKEN}/test/sendMessage?${queryString}`, {
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Incorrect Telegram API endpoint: The URL includes "/test/" which is not a valid part of the Telegram Bot API path. The correct endpoint should be "https://api.telegram.org/bot{BOT_TOKEN}/sendMessage" without the "test" segment.

Suggested change
fetch(`https://api.telegram.org/bot${BOT_TOKEN}/test/sendMessage?${queryString}`, {
fetch(`https://api.telegram.org/bot${BOT_TOKEN}/sendMessage?${queryString}`, {

Copilot uses AI. Check for mistakes.
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

URL is correct, "/test/" points to Telegram API for staging environment. Should add check to switch between staging and production based on Node Env

@@ -0,0 +1,67 @@
import {z} from 'zod';
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import z.

Suggested change
import {z} from 'zod';

Copilot uses AI. Check for mistakes.
@@ -0,0 +1,67 @@
import {z} from 'zod';
import type { FastifyPluginAsyncZod } from "fastify-type-provider-zod";
import { isAdmin } from "../../../../../shared.js";
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unused import isAdmin.

Suggested change
import { isAdmin } from "../../../../../shared.js";

Copilot uses AI. Check for mistakes.
fastify.log.error(err)
process.exit(1)
}
}
Copy link

Copilot AI Jan 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid automated semicolon insertion (91% of all statements in the enclosing script have an explicit semicolon).

Copilot uses AI. Check for mistakes.
@Jax0312 Jax0312 merged commit a8ee651 into main Jan 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants