refactor: rename web/ to api/ to better reflect its purpose
Some checks failed
Deploy to Production / test (push) Failing after 30s
Some checks failed
Deploy to Production / test (push) Failing after 30s
The web/ folder contains the REST API, WebSocket server, and OAuth routes — not a web frontend. Renaming to api/ clarifies this distinction since the actual web frontend lives in panel/. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
91
api/src/routes/transactions.routes.ts
Normal file
91
api/src/routes/transactions.routes.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
* @fileoverview Transaction listing endpoints for Aurora API.
|
||||
* Provides read access to economy transaction history.
|
||||
*/
|
||||
|
||||
import type { RouteContext, RouteModule } from "./types";
|
||||
import { jsonResponse, withErrorHandling } from "./utils";
|
||||
|
||||
/**
|
||||
* Transactions routes handler.
|
||||
*
|
||||
* Endpoints:
|
||||
* - GET /api/transactions - List transactions with filters
|
||||
*/
|
||||
async function handler(ctx: RouteContext): Promise<Response | null> {
|
||||
const { pathname, method, url } = ctx;
|
||||
|
||||
/**
|
||||
* @route GET /api/transactions
|
||||
* @description Returns economy transactions with optional filtering.
|
||||
*
|
||||
* @query userId - Filter by user ID (Discord snowflake)
|
||||
* @query type - Filter by transaction type
|
||||
* @query limit - Max results (default: 50)
|
||||
* @query offset - Pagination offset (default: 0)
|
||||
*
|
||||
* @response 200 - `{ transactions: Transaction[] }`
|
||||
* @response 500 - Error fetching transactions
|
||||
*
|
||||
* Transaction Types:
|
||||
* - DAILY_REWARD - Daily claim reward
|
||||
* - TRANSFER_IN - Received from another user
|
||||
* - TRANSFER_OUT - Sent to another user
|
||||
* - LOOTDROP_CLAIM - Claimed lootdrop
|
||||
* - SHOP_BUY - Item purchase
|
||||
* - QUEST_REWARD - Quest completion reward
|
||||
*
|
||||
* @example
|
||||
* // Request
|
||||
* GET /api/transactions?userId=123456789&type=DAILY_REWARD&limit=10
|
||||
*
|
||||
* // Response
|
||||
* {
|
||||
* "transactions": [
|
||||
* {
|
||||
* "id": "1",
|
||||
* "userId": "123456789",
|
||||
* "amount": "100",
|
||||
* "type": "DAILY_REWARD",
|
||||
* "description": "Daily reward (Streak: 3)",
|
||||
* "createdAt": "2024-01-15T12:00:00Z"
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
if (pathname === "/api/transactions" && method === "GET") {
|
||||
return withErrorHandling(async () => {
|
||||
const { transactions } = await import("@shared/db/schema");
|
||||
const { DrizzleClient } = await import("@shared/db/DrizzleClient");
|
||||
const { eq, desc } = await import("drizzle-orm");
|
||||
|
||||
const userId = url.searchParams.get("userId");
|
||||
const type = url.searchParams.get("type");
|
||||
const limit = url.searchParams.get("limit") ? parseInt(url.searchParams.get("limit")!) : 50;
|
||||
const offset = url.searchParams.get("offset") ? parseInt(url.searchParams.get("offset")!) : 0;
|
||||
|
||||
let query = DrizzleClient.select().from(transactions);
|
||||
|
||||
if (userId) {
|
||||
query = query.where(eq(transactions.userId, BigInt(userId))) as typeof query;
|
||||
}
|
||||
if (type) {
|
||||
query = query.where(eq(transactions.type, type)) as typeof query;
|
||||
}
|
||||
|
||||
const result = await query
|
||||
.orderBy(desc(transactions.createdAt))
|
||||
.limit(limit)
|
||||
.offset(offset);
|
||||
|
||||
return jsonResponse({ transactions: result });
|
||||
}, "fetch transactions");
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export const transactionsRoutes: RouteModule = {
|
||||
name: "transactions",
|
||||
handler
|
||||
};
|
||||
Reference in New Issue
Block a user