update flow and auth model
This commit is contained in:
79
src/services/admin.service.ts
Normal file
79
src/services/admin.service.ts
Normal file
@@ -0,0 +1,79 @@
|
||||
/**
|
||||
* Admin Service
|
||||
*
|
||||
* Handles admin-only API operations.
|
||||
*/
|
||||
|
||||
import {
|
||||
NO_BACKEND_MODE,
|
||||
API_ENDPOINTS,
|
||||
MOCK_CONFIG,
|
||||
buildApiUrl,
|
||||
getApiHeaders,
|
||||
logApiDebug,
|
||||
} from '../config';
|
||||
|
||||
// =============================================================================
|
||||
// Type Definitions
|
||||
// =============================================================================
|
||||
|
||||
export interface DeclareGualeRequest {
|
||||
username: string;
|
||||
}
|
||||
|
||||
export interface DeclareGualeResponse {
|
||||
message: string;
|
||||
username: string;
|
||||
guale: boolean;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Admin Service
|
||||
// =============================================================================
|
||||
|
||||
export const adminService = {
|
||||
/**
|
||||
* Declare a user as deceased (guale)
|
||||
* Admin only operation
|
||||
* @param request - Username to declare as deceased
|
||||
* @param token - JWT token for authentication (must be admin)
|
||||
* @returns Success response
|
||||
*/
|
||||
async declareGuale(request: DeclareGualeRequest, token: string): Promise<DeclareGualeResponse> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('Declare Guale', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
message: `User ${request.username} has been declared as deceased`,
|
||||
username: request.username,
|
||||
guale: true,
|
||||
});
|
||||
}, MOCK_CONFIG.RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
const url = buildApiUrl(API_ENDPOINTS.ADMIN.DECLARE_GUALE);
|
||||
logApiDebug('Declare Guale URL', url);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: getApiHeaders(token),
|
||||
body: JSON.stringify(request),
|
||||
});
|
||||
|
||||
logApiDebug('Declare Guale Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || 'Failed to declare user as deceased');
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Declare guale error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
243
src/services/ai.service.ts
Normal file
243
src/services/ai.service.ts
Normal file
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* AI Service
|
||||
*
|
||||
* Handles communication with the AI proxy endpoint for chat completions.
|
||||
*/
|
||||
|
||||
import {
|
||||
NO_BACKEND_MODE,
|
||||
API_ENDPOINTS,
|
||||
AI_CONFIG,
|
||||
buildApiUrl,
|
||||
getApiHeaders,
|
||||
logApiDebug,
|
||||
} from '../config';
|
||||
|
||||
// =============================================================================
|
||||
// Type Definitions
|
||||
// =============================================================================
|
||||
|
||||
export interface AIMessage {
|
||||
role: 'system' | 'user' | 'assistant';
|
||||
content: string;
|
||||
}
|
||||
|
||||
export interface AIRequest {
|
||||
messages: AIMessage[];
|
||||
model?: string;
|
||||
}
|
||||
|
||||
export interface AIResponse {
|
||||
id: string;
|
||||
object: string;
|
||||
created: number;
|
||||
model: string;
|
||||
choices: Array<{
|
||||
index: number;
|
||||
message: AIMessage;
|
||||
finish_reason: string;
|
||||
}>;
|
||||
usage: {
|
||||
prompt_tokens: number;
|
||||
completion_tokens: number;
|
||||
total_tokens: number;
|
||||
};
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Mock Response Generator
|
||||
// =============================================================================
|
||||
|
||||
const createMockResponse = (userMessage: string): AIResponse => {
|
||||
return {
|
||||
id: `mock-${Date.now()}`,
|
||||
object: 'chat.completion',
|
||||
created: Math.floor(Date.now() / 1000),
|
||||
model: 'mock-model',
|
||||
choices: [
|
||||
{
|
||||
index: 0,
|
||||
message: {
|
||||
role: 'assistant',
|
||||
content: `I received your message: "${userMessage}". This is a mock response since the backend is not connected.`,
|
||||
},
|
||||
finish_reason: 'stop',
|
||||
},
|
||||
],
|
||||
usage: {
|
||||
prompt_tokens: 10,
|
||||
completion_tokens: 20,
|
||||
total_tokens: 30,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
// =============================================================================
|
||||
// AI Service
|
||||
// =============================================================================
|
||||
|
||||
export const aiService = {
|
||||
/**
|
||||
* Send chat messages to the AI proxy
|
||||
* @param messages - Array of chat messages
|
||||
* @param token - JWT token for authentication
|
||||
* @returns AI response
|
||||
*/
|
||||
async chat(messages: AIMessage[], token?: string): Promise<AIResponse> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('AI Chat', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
const lastUserMessage = messages.filter((m) => m.role === 'user').pop();
|
||||
resolve(createMockResponse(lastUserMessage?.content || 'Hello'));
|
||||
}, AI_CONFIG.MOCK_RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
const url = buildApiUrl(API_ENDPOINTS.AI.PROXY);
|
||||
|
||||
logApiDebug('AI Request', {
|
||||
url,
|
||||
hasToken: !!token,
|
||||
messageCount: messages.length,
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: getApiHeaders(token),
|
||||
body: JSON.stringify({ messages } as AIRequest),
|
||||
});
|
||||
|
||||
logApiDebug('AI Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
logApiDebug('AI Error Response', errorText);
|
||||
|
||||
let errorDetail = 'AI request failed';
|
||||
try {
|
||||
const errorData = JSON.parse(errorText);
|
||||
errorDetail = errorData.detail || errorDetail;
|
||||
} catch {
|
||||
errorDetail = errorText || errorDetail;
|
||||
}
|
||||
throw new Error(`${response.status}: ${errorDetail}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
logApiDebug('AI Success', {
|
||||
id: data.id,
|
||||
model: data.model,
|
||||
choicesCount: data.choices?.length,
|
||||
});
|
||||
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('AI proxy error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Simple helper for single message chat
|
||||
* @param content - User message content
|
||||
* @param token - JWT token for authentication
|
||||
* @returns AI response text
|
||||
*/
|
||||
async sendMessage(content: string, token?: string): Promise<string> {
|
||||
const messages: AIMessage[] = [
|
||||
{
|
||||
role: 'system',
|
||||
content: AI_CONFIG.DEFAULT_SYSTEM_PROMPT,
|
||||
},
|
||||
{
|
||||
role: 'user',
|
||||
content,
|
||||
},
|
||||
];
|
||||
|
||||
const response = await this.chat(messages, token);
|
||||
return response.choices[0]?.message?.content || 'No response';
|
||||
},
|
||||
|
||||
/**
|
||||
* Send a message with an image to AI for analysis
|
||||
* @param content - User message content
|
||||
* @param imageBase64 - Base64 encoded image data
|
||||
* @param token - JWT token for authentication
|
||||
* @returns AI response text
|
||||
*/
|
||||
async sendMessageWithImage(content: string, imageBase64: string, token?: string): Promise<string> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('AI Image Analysis', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve('This is a mock image analysis response. The image appears to show an interesting scene. In production, this would be analyzed by Gemini AI.');
|
||||
}, AI_CONFIG.MOCK_RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
const url = buildApiUrl(API_ENDPOINTS.AI.PROXY);
|
||||
|
||||
logApiDebug('AI Image Request', {
|
||||
url,
|
||||
hasToken: !!token,
|
||||
hasImage: !!imageBase64,
|
||||
});
|
||||
|
||||
// Gemini vision format - using multimodal content
|
||||
const messages = [
|
||||
{
|
||||
role: 'user',
|
||||
content: [
|
||||
{
|
||||
type: 'text',
|
||||
text: content,
|
||||
},
|
||||
{
|
||||
type: 'image_url',
|
||||
image_url: {
|
||||
url: `data:image/jpeg;base64,${imageBase64}`,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: getApiHeaders(token),
|
||||
body: JSON.stringify({ messages }),
|
||||
});
|
||||
|
||||
logApiDebug('AI Image Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
logApiDebug('AI Image Error Response', errorText);
|
||||
|
||||
let errorDetail = 'AI image request failed';
|
||||
try {
|
||||
const errorData = JSON.parse(errorText);
|
||||
errorDetail = errorData.detail || errorDetail;
|
||||
} catch {
|
||||
errorDetail = errorText || errorDetail;
|
||||
}
|
||||
throw new Error(`${response.status}: ${errorDetail}`);
|
||||
}
|
||||
|
||||
const data = await response.json();
|
||||
logApiDebug('AI Image Success', {
|
||||
id: data.id,
|
||||
model: data.model,
|
||||
});
|
||||
|
||||
return data.choices[0]?.message?.content || 'No response';
|
||||
} catch (error) {
|
||||
console.error('AI image proxy error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
243
src/services/assets.service.ts
Normal file
243
src/services/assets.service.ts
Normal file
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
* Assets Service
|
||||
*
|
||||
* Handles all asset-related API operations including CRUD and inheritance.
|
||||
*/
|
||||
|
||||
import {
|
||||
NO_BACKEND_MODE,
|
||||
API_ENDPOINTS,
|
||||
MOCK_CONFIG,
|
||||
buildApiUrl,
|
||||
getApiHeaders,
|
||||
logApiDebug,
|
||||
} from '../config';
|
||||
|
||||
// =============================================================================
|
||||
// Type Definitions
|
||||
// =============================================================================
|
||||
|
||||
export interface Asset {
|
||||
id: number;
|
||||
title: string;
|
||||
author_id: number;
|
||||
private_key_shard: string;
|
||||
content_outer_encrypted: string;
|
||||
}
|
||||
|
||||
export interface AssetCreate {
|
||||
title: string;
|
||||
private_key_shard: string;
|
||||
content_inner_encrypted: string;
|
||||
}
|
||||
|
||||
export interface AssetClaim {
|
||||
asset_id: number;
|
||||
private_key_shard: string;
|
||||
}
|
||||
|
||||
export interface AssetClaimResponse {
|
||||
asset_id: number;
|
||||
title: string;
|
||||
decrypted_content: string;
|
||||
server_shard_key: string;
|
||||
}
|
||||
|
||||
export interface AssetAssign {
|
||||
asset_id: number;
|
||||
heir_name: string;
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// Mock Data
|
||||
// =============================================================================
|
||||
|
||||
const MOCK_ASSETS: Asset[] = [
|
||||
{
|
||||
id: 1,
|
||||
title: 'Mock Asset 1',
|
||||
author_id: MOCK_CONFIG.USER.id,
|
||||
private_key_shard: 'mock_shard_1',
|
||||
content_outer_encrypted: 'mock_encrypted_content_1',
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: 'Mock Asset 2',
|
||||
author_id: MOCK_CONFIG.USER.id,
|
||||
private_key_shard: 'mock_shard_2',
|
||||
content_outer_encrypted: 'mock_encrypted_content_2',
|
||||
},
|
||||
];
|
||||
|
||||
// =============================================================================
|
||||
// Assets Service
|
||||
// =============================================================================
|
||||
|
||||
export const assetsService = {
|
||||
/**
|
||||
* Get all assets for the current user
|
||||
* @param token - JWT token for authentication
|
||||
* @returns Array of user's assets
|
||||
*/
|
||||
async getMyAssets(token: string): Promise<Asset[]> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('Get Assets', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => resolve(MOCK_ASSETS), MOCK_CONFIG.RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
const url = buildApiUrl(API_ENDPOINTS.ASSETS.GET);
|
||||
logApiDebug('Get Assets URL', url);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'GET',
|
||||
headers: getApiHeaders(token),
|
||||
});
|
||||
|
||||
logApiDebug('Get Assets Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || 'Failed to fetch assets');
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Get assets error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a new asset
|
||||
* @param asset - Asset creation data
|
||||
* @param token - JWT token for authentication
|
||||
* @returns Created asset
|
||||
*/
|
||||
async createAsset(asset: AssetCreate, token: string): Promise<Asset> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('Create Asset', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
id: Date.now(),
|
||||
title: asset.title,
|
||||
author_id: MOCK_CONFIG.USER.id,
|
||||
private_key_shard: asset.private_key_shard,
|
||||
content_outer_encrypted: asset.content_inner_encrypted,
|
||||
});
|
||||
}, MOCK_CONFIG.RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
const url = buildApiUrl(API_ENDPOINTS.ASSETS.CREATE);
|
||||
logApiDebug('Create Asset URL', url);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: getApiHeaders(token),
|
||||
body: JSON.stringify(asset),
|
||||
});
|
||||
|
||||
logApiDebug('Create Asset Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || 'Failed to create asset');
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Create asset error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Claim an inherited asset
|
||||
* @param claim - Asset claim data
|
||||
* @param token - JWT token for authentication
|
||||
* @returns Claimed asset with decrypted content
|
||||
*/
|
||||
async claimAsset(claim: AssetClaim, token: string): Promise<AssetClaimResponse> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('Claim Asset', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
asset_id: claim.asset_id,
|
||||
title: 'Mock Claimed Asset',
|
||||
decrypted_content: 'This is the decrypted content of the claimed asset.',
|
||||
server_shard_key: 'mock_server_shard',
|
||||
});
|
||||
}, MOCK_CONFIG.RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
const url = buildApiUrl(API_ENDPOINTS.ASSETS.CLAIM);
|
||||
logApiDebug('Claim Asset URL', url);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: getApiHeaders(token),
|
||||
body: JSON.stringify(claim),
|
||||
});
|
||||
|
||||
logApiDebug('Claim Asset Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || 'Failed to claim asset');
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Claim asset error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Assign an asset to an heir
|
||||
* @param assignment - Asset assignment data
|
||||
* @param token - JWT token for authentication
|
||||
* @returns Success message
|
||||
*/
|
||||
async assignAsset(assignment: AssetAssign, token: string): Promise<{ message: string }> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('Assign Asset', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({ message: `Asset assigned to ${assignment.heir_name}` });
|
||||
}, MOCK_CONFIG.RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
const url = buildApiUrl(API_ENDPOINTS.ASSETS.ASSIGN);
|
||||
logApiDebug('Assign Asset URL', url);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: getApiHeaders(token),
|
||||
body: JSON.stringify(assignment),
|
||||
});
|
||||
|
||||
logApiDebug('Assign Asset Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || 'Failed to assign asset');
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Assign asset error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -1,80 +1,87 @@
|
||||
import { LoginRequest, LoginResponse, RegisterRequest, User } from '../types';
|
||||
|
||||
const PLATFORM_URL = 'http://192.168.56.103:8000';
|
||||
const no_backend_mode = true;
|
||||
|
||||
const MOCK_USER: User = {
|
||||
id: 999,
|
||||
username: 'MockCaptain',
|
||||
public_key: 'mock_public_key',
|
||||
is_admin: true,
|
||||
guale: false,
|
||||
tier: 'premium',
|
||||
tier_expires_at: '2026-12-31T23:59:59Z',
|
||||
last_active_at: new Date().toISOString(),
|
||||
};
|
||||
import {
|
||||
NO_BACKEND_MODE,
|
||||
API_ENDPOINTS,
|
||||
MOCK_CONFIG,
|
||||
buildApiUrl,
|
||||
getApiHeaders,
|
||||
logApiDebug,
|
||||
} from '../config';
|
||||
|
||||
export const authService = {
|
||||
async login(credentials: LoginRequest): Promise<LoginResponse> {
|
||||
if (no_backend_mode) {
|
||||
console.log('No-Backend Mode: Simulating login...');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
access_token: 'mock_access_token',
|
||||
token_type: 'bearer',
|
||||
user: { ...MOCK_USER, username: credentials.username },
|
||||
});
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`${PLATFORM_URL}/login`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(credentials),
|
||||
});
|
||||
async login(credentials: LoginRequest): Promise<LoginResponse> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('Login', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({
|
||||
access_token: MOCK_CONFIG.ACCESS_TOKEN,
|
||||
token_type: 'bearer',
|
||||
user: { ...MOCK_CONFIG.USER, username: credentials.username } as User,
|
||||
});
|
||||
}, MOCK_CONFIG.RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error('Login failed');
|
||||
}
|
||||
const url = buildApiUrl(API_ENDPOINTS.AUTH.LOGIN);
|
||||
logApiDebug('Login URL', url);
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: getApiHeaders(),
|
||||
body: JSON.stringify(credentials),
|
||||
});
|
||||
|
||||
async register(data: RegisterRequest): Promise<User> {
|
||||
if (no_backend_mode) {
|
||||
console.log('No-Backend Mode: Simulating registration...');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({ ...MOCK_USER, username: data.username });
|
||||
}, 200);
|
||||
});
|
||||
}
|
||||
try {
|
||||
const response = await fetch(`${PLATFORM_URL}/register`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
logApiDebug('Login Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail?.[0]?.msg || 'Registration failed');
|
||||
}
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail || 'Login failed');
|
||||
}
|
||||
|
||||
return await response.json();
|
||||
} catch (error) {
|
||||
console.error('Registration error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
const data = await response.json();
|
||||
logApiDebug('Login Success', { username: data.user?.username });
|
||||
return data;
|
||||
} catch (error) {
|
||||
console.error('Login error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
|
||||
async register(data: RegisterRequest): Promise<User> {
|
||||
if (NO_BACKEND_MODE) {
|
||||
logApiDebug('Register', 'Using mock mode');
|
||||
return new Promise((resolve) => {
|
||||
setTimeout(() => {
|
||||
resolve({ ...MOCK_CONFIG.USER, username: data.username } as User);
|
||||
}, MOCK_CONFIG.RESPONSE_DELAY);
|
||||
});
|
||||
}
|
||||
|
||||
const url = buildApiUrl(API_ENDPOINTS.AUTH.REGISTER);
|
||||
logApiDebug('Register URL', url);
|
||||
|
||||
try {
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: getApiHeaders(),
|
||||
body: JSON.stringify(data),
|
||||
});
|
||||
|
||||
logApiDebug('Register Response Status', response.status);
|
||||
|
||||
if (!response.ok) {
|
||||
const errorData = await response.json().catch(() => ({}));
|
||||
throw new Error(errorData.detail?.[0]?.msg || errorData.detail || 'Registration failed');
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
logApiDebug('Register Success', { username: result.username });
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Registration error:', error);
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
25
src/services/index.ts
Normal file
25
src/services/index.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
/**
|
||||
* Services Index
|
||||
*
|
||||
* Central export for all API services.
|
||||
* Import services from here for cleaner imports.
|
||||
*
|
||||
* Usage:
|
||||
* import { authService, aiService, assetsService, adminService } from '../services';
|
||||
*/
|
||||
|
||||
export { authService } from './auth.service';
|
||||
export { aiService, type AIMessage, type AIRequest, type AIResponse } from './ai.service';
|
||||
export {
|
||||
assetsService,
|
||||
type Asset,
|
||||
type AssetCreate,
|
||||
type AssetClaim,
|
||||
type AssetClaimResponse,
|
||||
type AssetAssign
|
||||
} from './assets.service';
|
||||
export {
|
||||
adminService,
|
||||
type DeclareGualeRequest,
|
||||
type DeclareGualeResponse
|
||||
} from './admin.service';
|
||||
Reference in New Issue
Block a user