feat: migrate entire codebase to TypeScript
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, mock, beforeEach, afterAll } from "bun:test";
|
||||
|
||||
const mockServe = mock((options) => {
|
||||
@@ -15,24 +16,24 @@ const mockStartBot = mock(() => Promise.resolve({
|
||||
stop: mock()
|
||||
}));
|
||||
|
||||
mock.module("../src/bot.js", () => ({
|
||||
mock.module("../src/bot", () => ({
|
||||
startBot: mockStartBot
|
||||
}));
|
||||
|
||||
mock.module("../src/routes/upload.js", () => ({
|
||||
mock.module("../src/routes/upload", () => ({
|
||||
handleUpload: mock()
|
||||
}));
|
||||
|
||||
mock.module("../src/routes/files.js", () => ({
|
||||
mock.module("../src/routes/files", () => ({
|
||||
handleFileRedirect: mock(),
|
||||
handleFileInfo: mock()
|
||||
}));
|
||||
|
||||
mock.module("../src/routes/health.js", () => ({
|
||||
mock.module("../src/routes/health", () => ({
|
||||
handleHealth: mock()
|
||||
}));
|
||||
|
||||
mock.module("../src/utils/rateLimit.js", () => ({
|
||||
mock.module("../src/utils/rateLimit", () => ({
|
||||
cleanupRateLimitCache: mock()
|
||||
}));
|
||||
|
||||
@@ -47,7 +48,7 @@ describe("Bootstrap Server", () => {
|
||||
});
|
||||
|
||||
it("should bootstrap the application successfully", async () => {
|
||||
await import("../src/index.js");
|
||||
await import("../src/index");
|
||||
|
||||
expect(mockServe).toHaveBeenCalled();
|
||||
expect(mockStartBot).toHaveBeenCalled();
|
||||
@@ -1,5 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, mock, spyOn, beforeEach, afterAll } from "bun:test";
|
||||
import logger from "../src/utils/logger.js";
|
||||
import logger from "../src/utils/logger";
|
||||
|
||||
// Mock environment
|
||||
process.env.BOT_TOKEN = "8605908810:AAFpUzlIBktfd_7wpEj7zMJob2CFxvG-ZGY";
|
||||
@@ -30,7 +31,7 @@ mock.module("telegraf", () => {
|
||||
const mockInsert = mock(() => ({
|
||||
values: mock(() => Promise.resolve())
|
||||
}));
|
||||
mock.module("../src/db/index.js", () => ({
|
||||
mock.module("../src/db/index", () => ({
|
||||
db: {
|
||||
insert: mockInsert
|
||||
},
|
||||
@@ -43,7 +44,7 @@ const mockForwardToStorage = mock(() => Promise.resolve({
|
||||
telegramFileUniqueId: "stored_unique_id",
|
||||
storageMessageId: 9999
|
||||
}));
|
||||
mock.module("../src/utils/telegram.js", () => ({
|
||||
mock.module("../src/utils/telegram", () => ({
|
||||
forwardToStorage: mockForwardToStorage
|
||||
}));
|
||||
|
||||
@@ -63,7 +64,7 @@ describe("Telegram Bot Handler", () => {
|
||||
});
|
||||
|
||||
it("should initialize and launch the bot", async () => {
|
||||
const { startBot } = await import("../src/bot.js");
|
||||
const { startBot } = await import("../src/bot");
|
||||
const bot = await startBot();
|
||||
|
||||
expect(bot).toBeDefined();
|
||||
@@ -77,7 +78,7 @@ describe("Telegram Bot Handler", () => {
|
||||
});
|
||||
|
||||
it("should handle /start command", async () => {
|
||||
const { startBot } = await import("../src/bot.js");
|
||||
const { startBot } = await import("../src/bot");
|
||||
await startBot();
|
||||
|
||||
const startHandler = mockCommand.mock.calls.find(call => call[0] === "start")[1];
|
||||
@@ -91,7 +92,7 @@ describe("Telegram Bot Handler", () => {
|
||||
});
|
||||
|
||||
it("should process document uploads and save to db", async () => {
|
||||
const { startBot } = await import("../src/bot.js");
|
||||
const { startBot } = await import("../src/bot");
|
||||
await startBot();
|
||||
|
||||
const fileHandler = mockOn.mock.calls[0][1];
|
||||
@@ -120,7 +121,7 @@ describe("Telegram Bot Handler", () => {
|
||||
});
|
||||
|
||||
it("should reject uploads exceeding max size limit", async () => {
|
||||
const { startBot } = await import("../src/bot.js");
|
||||
const { startBot } = await import("../src/bot");
|
||||
await startBot();
|
||||
|
||||
const fileHandler = mockOn.mock.calls[0][1];
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { db, files } from "../src/db/index.js";
|
||||
import { files as schemaFiles } from "../src/db/schema.js";
|
||||
import { db, files } from "../src/db/index";
|
||||
import { files as schemaFiles } from "../src/db/schema";
|
||||
|
||||
describe("Database Layer", () => {
|
||||
it("should export db instance", () => {
|
||||
@@ -1,5 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, beforeAll } from "bun:test";
|
||||
import { config } from "../src/env.js";
|
||||
import { config } from "../src/env";
|
||||
|
||||
describe("Environment Variables Validation", () => {
|
||||
it("config should have all required fields", () => {
|
||||
@@ -1,5 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect } from "bun:test";
|
||||
import { getFileType, checkFileSize, extractFileName, extractMimeType } from "../src/utils/file.js";
|
||||
import { getFileType, checkFileSize, extractFileName, extractMimeType } from "../src/utils/file";
|
||||
|
||||
describe("File Utilities", () => {
|
||||
describe("getFileType", () => {
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, mock, beforeEach, afterAll } from "bun:test";
|
||||
|
||||
// Mock database layer
|
||||
@@ -9,7 +10,7 @@ const mockSelect = mock(() => ({
|
||||
}))
|
||||
}));
|
||||
|
||||
mock.module("../src/db/index.js", () => ({
|
||||
mock.module("../src/db/index", () => ({
|
||||
db: {
|
||||
select: mockSelect
|
||||
},
|
||||
@@ -22,9 +23,9 @@ mock.module("../src/db/index.js", () => ({
|
||||
|
||||
// Mock telegram utils
|
||||
const mockGetFile = mock(() => Promise.resolve({ file_path: "photos/file_0.jpg" }));
|
||||
mock.module("../src/utils/telegram.js", () => ({
|
||||
mock.module("../src/utils/telegram", () => ({
|
||||
getBot: () => ({
|
||||
api: {
|
||||
telegram: {
|
||||
getFile: mockGetFile
|
||||
}
|
||||
})
|
||||
@@ -32,7 +33,7 @@ mock.module("../src/utils/telegram.js", () => ({
|
||||
|
||||
// Mock rateLimit
|
||||
const mockCheckRateLimit = mock(() => true);
|
||||
mock.module("../src/utils/rateLimit.js", () => ({
|
||||
mock.module("../src/utils/rateLimit", () => ({
|
||||
checkRateLimit: mockCheckRateLimit
|
||||
}));
|
||||
|
||||
@@ -47,7 +48,7 @@ describe("File Route Handlers", () => {
|
||||
// Set up mock token
|
||||
process.env.BOT_TOKEN = "123456:ABC-DEF";
|
||||
|
||||
const filesRoute = await import("../src/routes/files.js");
|
||||
const filesRoute = await import("../src/routes/files");
|
||||
handleFileRedirect = filesRoute.handleFileRedirect;
|
||||
handleFileInfo = filesRoute.handleFileInfo;
|
||||
});
|
||||
@@ -56,8 +57,9 @@ describe("File Route Handlers", () => {
|
||||
it("should return 429 if rate limit is exceeded", async () => {
|
||||
mockCheckRateLimit.mockImplementationOnce(() => false);
|
||||
const req = new Request("http://localhost:3000/f/test-id");
|
||||
req.params = { public_id: "test-id" };
|
||||
|
||||
const res = await handleFileRedirect(req, { params: { public_id: "test-id" } });
|
||||
const res = await handleFileRedirect(req);
|
||||
expect(res.status).toBe(429);
|
||||
const body = await res.json();
|
||||
expect(body.error).toBe("Rate limit exceeded");
|
||||
@@ -73,7 +75,8 @@ describe("File Route Handlers", () => {
|
||||
}));
|
||||
|
||||
const req = new Request("http://localhost:3000/f/missing-id");
|
||||
const res = await handleFileRedirect(req, { params: { public_id: "missing-id" } });
|
||||
req.params = { public_id: "missing-id" };
|
||||
const res = await handleFileRedirect(req);
|
||||
expect(res.status).toBe(404);
|
||||
const body = await res.json();
|
||||
expect(body.error).toBe("File not found");
|
||||
@@ -94,7 +97,8 @@ describe("File Route Handlers", () => {
|
||||
}));
|
||||
|
||||
const req = new Request("http://localhost:3000/f/test-id");
|
||||
const res = await handleFileRedirect(req, { params: { public_id: "test-id" } });
|
||||
req.params = { public_id: "test-id" };
|
||||
const res = await handleFileRedirect(req);
|
||||
expect(res.status).toBe(302);
|
||||
expect(res.headers.get("Location")).toBe("https://api.telegram.org/file/bot123456:ABC-DEF/photos/file_0.jpg");
|
||||
});
|
||||
@@ -105,7 +109,8 @@ describe("File Route Handlers", () => {
|
||||
});
|
||||
|
||||
const req = new Request("http://localhost:3000/f/test-id");
|
||||
const res = await handleFileRedirect(req, { params: { public_id: "test-id" } });
|
||||
req.params = { public_id: "test-id" };
|
||||
const res = await handleFileRedirect(req);
|
||||
expect(res.status).toBe(500);
|
||||
const body = await res.json();
|
||||
expect(body.error).toBe("Server error");
|
||||
@@ -123,7 +128,8 @@ describe("File Route Handlers", () => {
|
||||
}));
|
||||
|
||||
const req = new Request("http://localhost:3000/file/missing-id/info");
|
||||
const res = await handleFileInfo(req, { params: { public_id: "missing-id" } });
|
||||
req.params = { public_id: "missing-id" };
|
||||
const res = await handleFileInfo(req);
|
||||
expect(res.status).toBe(404);
|
||||
const body = await res.json();
|
||||
expect(body.error).toBe("File not found");
|
||||
@@ -149,7 +155,8 @@ describe("File Route Handlers", () => {
|
||||
}));
|
||||
|
||||
const req = new Request("http://localhost:3000/file/test-id/info");
|
||||
const res = await handleFileInfo(req, { params: { public_id: "test-id" } });
|
||||
req.params = { public_id: "test-id" };
|
||||
const res = await handleFileInfo(req);
|
||||
expect(res.status).toBe(200);
|
||||
const body = await res.json();
|
||||
expect(body).toEqual({
|
||||
@@ -169,7 +176,8 @@ describe("File Route Handlers", () => {
|
||||
});
|
||||
|
||||
const req = new Request("http://localhost:3000/file/test-id/info");
|
||||
const res = await handleFileInfo(req, { params: { public_id: "test-id" } });
|
||||
req.params = { public_id: "test-id" };
|
||||
const res = await handleFileInfo(req);
|
||||
expect(res.status).toBe(500);
|
||||
const body = await res.json();
|
||||
expect(body.error).toBe("Server error");
|
||||
@@ -1,9 +1,10 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, mock, beforeEach } from "bun:test";
|
||||
|
||||
// Mock database layer
|
||||
const mockExecute = mock(() => Promise.resolve());
|
||||
|
||||
mock.module("../src/db/index.js", () => ({
|
||||
mock.module("../src/db/index", () => ({
|
||||
db: {
|
||||
execute: mockExecute
|
||||
}
|
||||
@@ -14,7 +15,7 @@ describe("Health Route Handler", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
mockExecute.mockClear();
|
||||
const healthRoute = await import("../src/routes/health.js");
|
||||
const healthRoute = await import("../src/routes/health");
|
||||
handleHealth = healthRoute.handleHealth;
|
||||
});
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import { checkRateLimit, cleanupRateLimitCache } from "../src/utils/rateLimit.js";
|
||||
import logger from "../src/utils/logger.js";
|
||||
import { checkRateLimit, cleanupRateLimitCache } from "../src/utils/rateLimit";
|
||||
import logger from "../src/utils/logger";
|
||||
|
||||
// Spy on logger.warn
|
||||
const warnSpy = spyOn(logger, "warn");
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, beforeEach, afterEach, mock, spyOn } from "bun:test";
|
||||
import logger from "../src/utils/logger.js";
|
||||
import { config } from "../src/env.js";
|
||||
import logger from "../src/utils/logger";
|
||||
import { config } from "../src/env";
|
||||
|
||||
// Mock Telegraf and fetch
|
||||
mock.module("telegraf", () => {
|
||||
@@ -8,7 +9,7 @@ mock.module("telegraf", () => {
|
||||
Telegraf: class {
|
||||
constructor(token) {
|
||||
this.token = token;
|
||||
this.api = {
|
||||
this.telegram = {
|
||||
sendPhoto: mock(() => Promise.resolve({
|
||||
message_id: 12345,
|
||||
photo: [
|
||||
@@ -34,7 +35,7 @@ describe("Telegram API Utilities", () => {
|
||||
global.fetch = mock(() => Promise.resolve(new Response(JSON.stringify({ ok: true }))));
|
||||
|
||||
// Import dynamically so mocking is applied first
|
||||
const telegramUtils = await import("../src/utils/telegram.js");
|
||||
const telegramUtils = await import("../src/utils/telegram");
|
||||
forwardToStorage = telegramUtils.forwardToStorage;
|
||||
getFileInfo = telegramUtils.getFileInfo;
|
||||
getBot = telegramUtils.getBot;
|
||||
@@ -48,7 +49,7 @@ describe("Telegram API Utilities", () => {
|
||||
it("should return the telegraf bot instance", () => {
|
||||
const bot = getBot();
|
||||
expect(bot).toBeDefined();
|
||||
expect(bot.api).toBeDefined();
|
||||
expect(bot.telegram).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -71,7 +72,7 @@ describe("Telegram API Utilities", () => {
|
||||
|
||||
it("should handle error when forwarding fails", async () => {
|
||||
const bot = getBot();
|
||||
bot.api.sendPhoto = mock(() => Promise.reject(new Error("Telegram send failed")));
|
||||
bot.telegram.sendPhoto = mock(() => Promise.reject(new Error("Telegram send failed")));
|
||||
|
||||
const chunk = Buffer.from("fake photo data");
|
||||
const fileName = "test_photo.jpg";
|
||||
@@ -1,3 +1,4 @@
|
||||
// @ts-nocheck
|
||||
import { describe, it, expect, mock, beforeEach, afterAll } from "bun:test";
|
||||
|
||||
// Mock db
|
||||
@@ -5,7 +6,7 @@ const mockInsert = mock(() => ({
|
||||
values: mock(() => Promise.resolve())
|
||||
}));
|
||||
|
||||
mock.module("../src/db/index.js", () => ({
|
||||
mock.module("../src/db/index", () => ({
|
||||
db: {
|
||||
insert: mockInsert
|
||||
},
|
||||
@@ -18,14 +19,14 @@ mock.module("nanoid", () => ({
|
||||
}));
|
||||
|
||||
// Mock telegram utils
|
||||
mock.module("../src/utils/telegram.js", () => ({
|
||||
mock.module("../src/utils/telegram", () => ({
|
||||
forwardToStorage: mock(() => Promise.resolve({
|
||||
telegramFileId: "tg-file-id-123",
|
||||
telegramFileUniqueId: "tg-unique-id-abc",
|
||||
storageMessageId: 98765
|
||||
})),
|
||||
getBot: () => ({
|
||||
api: {
|
||||
telegram: {
|
||||
getFile: mock(() => Promise.resolve({
|
||||
file_id: "tg-file-id-123",
|
||||
file_size: 1000,
|
||||
@@ -40,7 +41,7 @@ describe("Upload Route Handler", () => {
|
||||
|
||||
beforeEach(async () => {
|
||||
mockInsert.mockClear();
|
||||
const uploadRoute = await import("../src/routes/upload.js");
|
||||
const uploadRoute = await import("../src/routes/upload");
|
||||
handleUpload = uploadRoute.handleUpload;
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user