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:
274
api/src/routes/schemas.ts
Normal file
274
api/src/routes/schemas.ts
Normal file
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* @fileoverview Centralized Zod validation schemas for all Aurora API endpoints.
|
||||
* Provides type-safe request/response validation for every entity in the system.
|
||||
*/
|
||||
|
||||
import { z } from "zod";
|
||||
|
||||
// ============================================================================
|
||||
// Common Schemas
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Standard pagination query parameters.
|
||||
*/
|
||||
export const PaginationSchema = z.object({
|
||||
limit: z.coerce.number().min(1).max(100).optional().default(50),
|
||||
offset: z.coerce.number().min(0).optional().default(0),
|
||||
});
|
||||
|
||||
/**
|
||||
* Numeric ID parameter validation.
|
||||
*/
|
||||
export const NumericIdSchema = z.coerce.number().int().positive();
|
||||
|
||||
/**
|
||||
* Discord snowflake ID validation (string of digits).
|
||||
*/
|
||||
export const SnowflakeIdSchema = z.string().regex(/^\d{17,20}$/, "Invalid Discord ID format");
|
||||
|
||||
// ============================================================================
|
||||
// Items Schemas
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Valid item types in the system.
|
||||
*/
|
||||
export const ItemTypeEnum = z.enum([
|
||||
"CONSUMABLE",
|
||||
"EQUIPMENT",
|
||||
"MATERIAL",
|
||||
"LOOTBOX",
|
||||
"COLLECTIBLE",
|
||||
"KEY",
|
||||
"TOOL"
|
||||
]);
|
||||
|
||||
/**
|
||||
* Valid item rarities.
|
||||
*/
|
||||
export const ItemRarityEnum = z.enum(["C", "R", "SR", "SSR"]);
|
||||
|
||||
/**
|
||||
* Query parameters for listing items.
|
||||
*/
|
||||
export const ItemQuerySchema = PaginationSchema.extend({
|
||||
search: z.string().optional(),
|
||||
type: z.string().optional(),
|
||||
rarity: z.string().optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for creating a new item.
|
||||
*/
|
||||
export const CreateItemSchema = z.object({
|
||||
name: z.string().min(1, "Name is required").max(100),
|
||||
description: z.string().max(500).nullable().optional(),
|
||||
rarity: ItemRarityEnum.optional().default("C"),
|
||||
type: ItemTypeEnum,
|
||||
price: z.union([z.string(), z.number()]).nullable().optional(),
|
||||
iconUrl: z.string().optional(),
|
||||
imageUrl: z.string().optional(),
|
||||
usageData: z.any().nullable().optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for updating an existing item.
|
||||
*/
|
||||
export const UpdateItemSchema = z.object({
|
||||
name: z.string().min(1).max(100).optional(),
|
||||
description: z.string().max(500).nullable().optional(),
|
||||
rarity: ItemRarityEnum.optional(),
|
||||
type: ItemTypeEnum.optional(),
|
||||
price: z.union([z.string(), z.number()]).nullable().optional(),
|
||||
iconUrl: z.string().optional(),
|
||||
imageUrl: z.string().optional(),
|
||||
usageData: z.any().nullable().optional(),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Users Schemas
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Query parameters for listing users.
|
||||
*/
|
||||
export const UserQuerySchema = PaginationSchema.extend({
|
||||
search: z.string().optional(),
|
||||
sortBy: z.enum(["balance", "level", "xp", "username"]).optional().default("balance"),
|
||||
sortOrder: z.enum(["asc", "desc"]).optional().default("desc"),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for updating a user.
|
||||
*/
|
||||
export const UpdateUserSchema = z.object({
|
||||
username: z.string().min(1).max(32).optional(),
|
||||
balance: z.union([z.string(), z.number()]).optional(),
|
||||
xp: z.union([z.string(), z.number()]).optional(),
|
||||
level: z.coerce.number().int().min(0).optional(),
|
||||
dailyStreak: z.coerce.number().int().min(0).optional(),
|
||||
isActive: z.boolean().optional(),
|
||||
settings: z.record(z.string(), z.any()).optional(),
|
||||
classId: z.union([z.string(), z.number()]).optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for adding an item to user inventory.
|
||||
*/
|
||||
export const InventoryAddSchema = z.object({
|
||||
itemId: z.coerce.number().int().positive("Item ID is required"),
|
||||
quantity: z.union([z.string(), z.number()]).refine(
|
||||
(val) => BigInt(val) > 0n,
|
||||
"Quantity must be positive"
|
||||
),
|
||||
});
|
||||
|
||||
/**
|
||||
* Query params for removing inventory items.
|
||||
*/
|
||||
export const InventoryRemoveQuerySchema = z.object({
|
||||
amount: z.coerce.number().int().min(1).optional().default(1),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Classes Schemas
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Schema for creating a new class.
|
||||
*/
|
||||
export const CreateClassSchema = z.object({
|
||||
id: z.union([z.string(), z.number()]),
|
||||
name: z.string().min(1, "Name is required").max(50),
|
||||
balance: z.union([z.string(), z.number()]).optional().default("0"),
|
||||
roleId: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for updating a class.
|
||||
*/
|
||||
export const UpdateClassSchema = z.object({
|
||||
name: z.string().min(1).max(50).optional(),
|
||||
balance: z.union([z.string(), z.number()]).optional(),
|
||||
roleId: z.string().nullable().optional(),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Moderation Schemas
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Valid moderation case types.
|
||||
*/
|
||||
export const ModerationTypeEnum = z.enum([
|
||||
"warn",
|
||||
"timeout",
|
||||
"kick",
|
||||
"ban",
|
||||
"note",
|
||||
"prune"
|
||||
]);
|
||||
|
||||
/**
|
||||
* Query parameters for searching moderation cases.
|
||||
*/
|
||||
export const CaseQuerySchema = PaginationSchema.extend({
|
||||
userId: z.string().optional(),
|
||||
moderatorId: z.string().optional(),
|
||||
type: ModerationTypeEnum.optional(),
|
||||
active: z.preprocess(
|
||||
(val) => val === "true" ? true : val === "false" ? false : undefined,
|
||||
z.boolean().optional()
|
||||
),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for creating a moderation case.
|
||||
*/
|
||||
export const CreateCaseSchema = z.object({
|
||||
type: ModerationTypeEnum,
|
||||
userId: z.string().min(1, "User ID is required"),
|
||||
username: z.string().min(1, "Username is required"),
|
||||
moderatorId: z.string().min(1, "Moderator ID is required"),
|
||||
moderatorName: z.string().min(1, "Moderator name is required"),
|
||||
reason: z.string().min(1, "Reason is required").max(1000),
|
||||
metadata: z.record(z.string(), z.any()).optional().default({}),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for clearing/resolving a moderation case.
|
||||
*/
|
||||
export const ClearCaseSchema = z.object({
|
||||
clearedBy: z.string().min(1, "Cleared by ID is required"),
|
||||
clearedByName: z.string().min(1, "Cleared by name is required"),
|
||||
reason: z.string().max(500).optional().default("Cleared via API"),
|
||||
});
|
||||
|
||||
/**
|
||||
* Case ID pattern validation (CASE-XXXX format).
|
||||
*/
|
||||
export const CaseIdPattern = /^CASE-\d+$/i;
|
||||
|
||||
// ============================================================================
|
||||
// Transactions Schemas
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Query parameters for listing transactions.
|
||||
*/
|
||||
export const TransactionQuerySchema = PaginationSchema.extend({
|
||||
userId: z.string().optional(),
|
||||
type: z.string().optional(),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Lootdrops Schemas
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Query parameters for listing lootdrops.
|
||||
*/
|
||||
export const LootdropQuerySchema = z.object({
|
||||
limit: z.coerce.number().min(1).max(100).optional().default(50),
|
||||
});
|
||||
|
||||
/**
|
||||
* Schema for spawning a lootdrop.
|
||||
*/
|
||||
export const CreateLootdropSchema = z.object({
|
||||
channelId: z.string().min(1, "Channel ID is required"),
|
||||
amount: z.coerce.number().int().positive().optional(),
|
||||
currency: z.string().optional(),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Admin Actions Schemas
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Schema for toggling maintenance mode.
|
||||
*/
|
||||
export const MaintenanceModeSchema = z.object({
|
||||
enabled: z.boolean(),
|
||||
reason: z.string().max(200).optional(),
|
||||
});
|
||||
|
||||
// ============================================================================
|
||||
// Type Exports
|
||||
// ============================================================================
|
||||
|
||||
export type ItemQuery = z.infer<typeof ItemQuerySchema>;
|
||||
export type CreateItem = z.infer<typeof CreateItemSchema>;
|
||||
export type UpdateItem = z.infer<typeof UpdateItemSchema>;
|
||||
export type UserQuery = z.infer<typeof UserQuerySchema>;
|
||||
export type UpdateUser = z.infer<typeof UpdateUserSchema>;
|
||||
export type InventoryAdd = z.infer<typeof InventoryAddSchema>;
|
||||
export type CreateClass = z.infer<typeof CreateClassSchema>;
|
||||
export type UpdateClass = z.infer<typeof UpdateClassSchema>;
|
||||
export type CaseQuery = z.infer<typeof CaseQuerySchema>;
|
||||
export type CreateCase = z.infer<typeof CreateCaseSchema>;
|
||||
export type ClearCase = z.infer<typeof ClearCaseSchema>;
|
||||
export type TransactionQuery = z.infer<typeof TransactionQuerySchema>;
|
||||
export type CreateLootdrop = z.infer<typeof CreateLootdropSchema>;
|
||||
export type MaintenanceMode = z.infer<typeof MaintenanceModeSchema>;
|
||||
Reference in New Issue
Block a user