feat: PKCE auth + CI/CD deploy
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 1m2s
All checks were successful
CI/CD — Build & Deploy / Build & Deploy (push) Successful in 1m2s
- Frontend: PKCE flow (oauth.ts, AuthCallback code exchange, 401 interceptor) - Backend: token introspection via SuperOAuth (no more JWT secret) - User model: superOauthId (unified) replaces oauthId+provider - Cookies httpOnly session + refresh token - POST /auth/refresh endpoint - Gitea CI workflow (vps-runner pattern) - DB_SYNC env var for initial schema creation
This commit is contained in:
54
frontend/src/api/endpoints.ts
Normal file
54
frontend/src/api/endpoints.ts
Normal file
@@ -0,0 +1,54 @@
|
||||
import { api } from './client';
|
||||
import type {
|
||||
User, Character, Monster, CombatResult, CombatLog,
|
||||
CharacterItem, CharacterMaterial, Recipe, CraftJob, Item,
|
||||
} from './types';
|
||||
|
||||
// Auth
|
||||
export const authApi = {
|
||||
setSession: (token: string, refreshToken?: string) =>
|
||||
api.post<User>('/auth/session', { token, refreshToken }),
|
||||
me: () => api.get<User>('/auth/me'),
|
||||
logout: () => api.post<void>('/auth/logout'),
|
||||
};
|
||||
|
||||
// Character
|
||||
export const characterApi = {
|
||||
create: (name: string, stats: Record<string, number>) =>
|
||||
api.post<Character>('/characters', { name, ...stats }),
|
||||
me: () => api.get<Character>('/characters/me'),
|
||||
};
|
||||
|
||||
// Combat
|
||||
export const combatApi = {
|
||||
monsters: () => api.get<Monster[]>('/monsters'),
|
||||
start: (monsterId: string, attackType: string) => api.post<CombatResult>('/combat/start', { monsterId, attackType }),
|
||||
history: () => api.get<CombatLog[]>('/combat/history'),
|
||||
};
|
||||
|
||||
// Items
|
||||
export const itemApi = {
|
||||
catalogue: () => api.get<Item[]>('/items'),
|
||||
inventory: () => api.get<CharacterItem[]>('/items/inventory'),
|
||||
equip: (id: string) => api.post<void>(`/items/equip/${id}`),
|
||||
unequip: (slot: 'weapon' | 'armor') => api.post<void>(`/items/unequip/${slot}`),
|
||||
};
|
||||
|
||||
// Materials
|
||||
export const materialApi = {
|
||||
inventory: () => api.get<CharacterMaterial[]>('/materials/inventory'),
|
||||
};
|
||||
|
||||
// Craft
|
||||
export const craftApi = {
|
||||
recipes: () => api.get<Recipe[]>('/craft/recipes'),
|
||||
start: (recipeId: string) => api.post<CraftJob>('/craft/start', { recipeId }),
|
||||
active: () => api.get<CraftJob | { status: 'none' }>('/craft/active'),
|
||||
collect: (jobId: string) => api.post<CharacterItem>(`/craft/collect/${jobId}`),
|
||||
};
|
||||
|
||||
// Forge
|
||||
export const forgeApi = {
|
||||
upgrade: (characterItemId: string) =>
|
||||
api.post<{ success: boolean; newForgeLevel: number; item: CharacterItem }>('/forge/upgrade', { characterItemId }),
|
||||
};
|
||||
Reference in New Issue
Block a user