aethex-forge/client/lib/mock-auth.ts
Builder.io 491f6eaf06 Update signOut to notify auth state changes
cgen-7b6080a47fe74da1a173a231cd272f7b
2025-08-17 00:16:03 +00:00

184 lines
4.3 KiB
TypeScript

// Mock authentication service for development when Supabase is not available
interface MockUser {
id: string;
email: string;
created_at: string;
}
interface MockSession {
user: MockUser;
access_token: string;
}
interface MockProfile {
id: string;
username: string;
email: string;
role: string;
onboarded: boolean;
full_name?: string;
bio?: string;
level: number;
total_xp: number;
avatar_url?: string;
created_at: string;
updated_at: string;
}
class MockAuthService {
private currentUser: MockUser | null = null;
private currentSession: MockSession | null = null;
private profiles: Map<string, MockProfile> = new Map();
constructor() {
// Load from localStorage if available
const savedUser = localStorage.getItem('mock_user');
const savedProfile = localStorage.getItem('mock_profile');
if (savedUser) {
this.currentUser = JSON.parse(savedUser);
if (this.currentUser) {
this.currentSession = {
user: this.currentUser,
access_token: 'mock_token_' + Date.now()
};
}
}
if (savedProfile) {
const profile = JSON.parse(savedProfile);
this.profiles.set(profile.id, profile);
}
}
async signInWithPassword(email: string, password: string) {
// Mock validation - accept any email/password for demo
if (!email || !password) {
throw new Error('Email and password are required');
}
const user: MockUser = {
id: 'mock_user_' + email.replace(/[^a-z0-9]/gi, '_'),
email,
created_at: new Date().toISOString()
};
this.currentUser = user;
this.currentSession = {
user,
access_token: 'mock_token_' + Date.now()
};
// Save to localStorage
localStorage.setItem('mock_user', JSON.stringify(user));
// Notify auth state change
setTimeout(() => this.notifyAuthChange('SIGNED_IN'), 50);
return {
data: {
user,
session: this.currentSession
},
error: null
};
}
async signOut() {
this.currentUser = null;
this.currentSession = null;
localStorage.removeItem('mock_user');
localStorage.removeItem('mock_profile');
// Notify auth state change
setTimeout(() => this.notifyAuthChange('SIGNED_OUT'), 50);
return { error: null };
}
async getUser() {
return {
data: { user: this.currentUser },
error: null
};
}
async getSession() {
return {
data: { session: this.currentSession },
error: null
};
}
// Mock database operations
async getUserProfile(userId: string): Promise<MockProfile | null> {
return this.profiles.get(userId) || null;
}
async updateProfile(userId: string, updates: Partial<MockProfile>): Promise<MockProfile> {
let profile = this.profiles.get(userId);
if (!profile) {
// Create new profile
profile = {
id: userId,
username: updates.username || this.currentUser?.email?.split('@')[0] || 'user',
email: this.currentUser?.email || '',
role: 'member',
onboarded: true,
level: 1,
total_xp: 0,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
...updates
};
} else {
// Update existing
profile = {
...profile,
...updates,
updated_at: new Date().toISOString()
};
}
this.profiles.set(userId, profile);
localStorage.setItem('mock_profile', JSON.stringify(profile));
return profile;
}
onAuthStateChange(callback: (event: string, session: MockSession | null) => void) {
// Store callback for later use
this.authCallback = callback;
// Immediately call with current state
setTimeout(() => {
if (this.currentSession) {
callback('SIGNED_IN', this.currentSession);
} else {
callback('SIGNED_OUT', null);
}
}, 100);
// Return unsubscribe function
return {
data: {
subscription: {
unsubscribe: () => {
this.authCallback = null;
}
}
}
};
}
private authCallback: ((event: string, session: MockSession | null) => void) | null = null;
private notifyAuthChange(event: string) {
if (this.authCallback) {
this.authCallback(event, this.currentSession);
}
}
}
export const mockAuth = new MockAuthService();