mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 20:21:09 +02:00
🚚 feat(context): integrate context app into monorepo
Restructure the context app (formerly basetext) to follow the monorepo pattern with proper workspace configuration. Changes: - Move app files to apps/context/apps/mobile/ - Rename package to @context/mobile - Update bundle ID to com.manacore.context - Create pnpm-workspace.yaml for project workspace - Add dev scripts to root package.json - Update CLAUDE.md with project documentation The app structure is prepared for future web/backend additions. Note: Existing TypeScript errors in the original codebase are preserved. These should be fixed in a follow-up PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
34c879929b
commit
bb0e0cf5cb
303 changed files with 31904 additions and 475 deletions
|
|
@ -1 +0,0 @@
|
|||
engine-strict=true
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
# Package Managers
|
||||
package-lock.json
|
||||
pnpm-lock.yaml
|
||||
yarn.lock
|
||||
bun.lock
|
||||
bun.lockb
|
||||
|
||||
# Miscellaneous
|
||||
/static/
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
{
|
||||
"useTabs": true,
|
||||
"singleQuote": true,
|
||||
"trailingComma": "none",
|
||||
"printWidth": 100,
|
||||
"plugins": ["prettier-plugin-svelte", "prettier-plugin-tailwindcss"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": "*.svelte",
|
||||
"options": {
|
||||
"parser": "svelte"
|
||||
}
|
||||
}
|
||||
],
|
||||
"tailwindStylesheet": "./src/app.css"
|
||||
}
|
||||
44
games/worldream/apps/web/package.json
Normal file
44
games/worldream/apps/web/package.json
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
{
|
||||
"name": "@worldream/web",
|
||||
"private": true,
|
||||
"version": "0.0.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite dev",
|
||||
"build": "vite build",
|
||||
"preview": "vite preview",
|
||||
"prepare": "svelte-kit sync || echo ''",
|
||||
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
|
||||
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
||||
"type-check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sveltejs/adapter-node": "^5.2.12",
|
||||
"@sveltejs/kit": "^2.22.0",
|
||||
"@sveltejs/vite-plugin-svelte": "^6.0.0",
|
||||
"@tailwindcss/forms": "^0.5.9",
|
||||
"@tailwindcss/typography": "^0.5.15",
|
||||
"@tailwindcss/vite": "^4.0.0",
|
||||
"svelte": "^5.0.0",
|
||||
"svelte-check": "^4.0.0",
|
||||
"tailwindcss": "^4.0.0",
|
||||
"typescript": "^5.0.0",
|
||||
"vite": "^7.0.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@google/generative-ai": "^0.24.1",
|
||||
"@manacore/shared-auth": "workspace:*",
|
||||
"@manacore/shared-auth-ui": "workspace:*",
|
||||
"@manacore/shared-branding": "workspace:*",
|
||||
"@manacore/shared-i18n": "workspace:*",
|
||||
"@manacore/shared-theme": "workspace:*",
|
||||
"@manacore/shared-utils": "workspace:*",
|
||||
"@paralleldrive/cuid2": "^3.0.4",
|
||||
"@supabase/ssr": "^0.7.0",
|
||||
"@supabase/supabase-js": "^2.56.1",
|
||||
"@worldream/types": "workspace:*",
|
||||
"marked": "^16.2.1",
|
||||
"openai": "^5.16.0",
|
||||
"replicate": "^1.1.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -6,12 +6,11 @@ declare global {
|
|||
namespace App {
|
||||
interface Locals {
|
||||
supabase: SupabaseClient;
|
||||
// Session helpers - returns mock session while transitioning to Mana Core Auth
|
||||
safeGetSession: () => Promise<{ session: Session | null; user: User | null }>;
|
||||
getSession: () => Promise<Session | null>;
|
||||
}
|
||||
interface PageData {
|
||||
session: Session | null;
|
||||
user: User | null;
|
||||
}
|
||||
// interface PageData {}
|
||||
// interface Error {}
|
||||
// interface PageState {}
|
||||
// interface Platform {}
|
||||
41
games/worldream/apps/web/src/hooks.server.ts
Normal file
41
games/worldream/apps/web/src/hooks.server.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
/**
|
||||
* Server Hooks for SvelteKit
|
||||
* Auth is handled client-side via Mana Core Auth
|
||||
* Supabase is still used for database operations
|
||||
*
|
||||
* TODO: Migrate API routes to use Mana Core Auth headers instead of session-based auth
|
||||
*/
|
||||
|
||||
import { createClient } from '$lib/supabase/server';
|
||||
import type { Handle } from '@sveltejs/kit';
|
||||
|
||||
export const handle: Handle = async ({ event, resolve }) => {
|
||||
// Create Supabase client for database operations
|
||||
event.locals.supabase = createClient(event);
|
||||
|
||||
// Provide session helpers for backwards compatibility
|
||||
// These are stubs while transitioning to Mana Core Auth
|
||||
event.locals.safeGetSession = async () => {
|
||||
// In the future, this should validate the Mana Core Auth token
|
||||
// For now, return a mock session for development
|
||||
const {
|
||||
data: { session },
|
||||
error,
|
||||
} = await event.locals.supabase.auth.getSession();
|
||||
if (error || !session) {
|
||||
return { session: null, user: null };
|
||||
}
|
||||
return { session, user: session.user };
|
||||
};
|
||||
|
||||
event.locals.getSession = async () => {
|
||||
const { session } = await event.locals.safeGetSession();
|
||||
return session;
|
||||
};
|
||||
|
||||
return resolve(event, {
|
||||
filterSerializedResponseHeaders(name) {
|
||||
return name === 'content-range' || name === 'x-supabase-api-version';
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -233,7 +233,9 @@ function validateAndCleanUpdates(updates: any, originalNode: ContentNode): Parti
|
|||
}
|
||||
|
||||
if (updates.tags && Array.isArray(updates.tags)) {
|
||||
cleaned.tags = updates.tags.filter((tag) => typeof tag === 'string').map((tag) => tag.trim());
|
||||
cleaned.tags = updates.tags
|
||||
.filter((tag: unknown): tag is string => typeof tag === 'string')
|
||||
.map((tag: string) => tag.trim());
|
||||
}
|
||||
|
||||
// Validate content updates
|
||||
|
|
@ -55,12 +55,13 @@ export async function generateImageWithFlux(options: ImageGenerationOptions): Pr
|
|||
console.log('Flux Raw Output Type:', typeof output);
|
||||
console.log('Flux Raw Output:', output);
|
||||
|
||||
// Verarbeite das Output
|
||||
// Verarbeite das Output - Type als unknown, da Replicate verschiedene Formate zurückgibt
|
||||
let imageUrl: string = '';
|
||||
const result = output as unknown;
|
||||
|
||||
// Wenn es ein Array mit ReadableStreams ist
|
||||
if (Array.isArray(output) && output.length > 0) {
|
||||
const firstItem = output[0];
|
||||
if (Array.isArray(result) && result.length > 0) {
|
||||
const firstItem = result[0];
|
||||
|
||||
// Wenn es ein ReadableStream ist, konvertiere zu Base64
|
||||
if (
|
||||
|
|
@ -124,8 +125,8 @@ export async function generateImageWithFlux(options: ImageGenerationOptions): Pr
|
|||
}
|
||||
}
|
||||
// Wenn es direkt ein String ist
|
||||
else if (typeof output === 'string' && output.startsWith('http')) {
|
||||
imageUrl = output;
|
||||
else if (typeof result === 'string' && result.startsWith('http')) {
|
||||
imageUrl = result;
|
||||
}
|
||||
|
||||
if (!imageUrl) {
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
|
|
@ -3,20 +3,32 @@
|
|||
import { fade, fly, scale } from 'svelte/transition';
|
||||
import { cubicOut, elasticOut } from 'svelte/easing';
|
||||
|
||||
// Props - optional message for simple loading states
|
||||
interface Props {
|
||||
message?: string;
|
||||
}
|
||||
let { message }: Props = $props();
|
||||
|
||||
// Reactive state from store
|
||||
let loading = $derived($loadingStore);
|
||||
let minimized = $state(false);
|
||||
let toastMode = $state(false);
|
||||
|
||||
// Use store title or fallback to message prop
|
||||
let displayTitle = $derived(loading.title || message || 'Laden...');
|
||||
|
||||
// Calculate overall progress
|
||||
let progress = $derived(() => {
|
||||
if (!loading.steps.length) return 0;
|
||||
const completed = loading.steps.filter((s) => s.status === 'completed').length;
|
||||
return (completed / loading.steps.length) * 100;
|
||||
});
|
||||
|
||||
// Show overlay if store is loading OR if message prop is provided
|
||||
let showOverlay = $derived(loading.isLoading || !!message);
|
||||
</script>
|
||||
|
||||
{#if loading.isLoading}
|
||||
{#if showOverlay}
|
||||
<!-- Overlay -->
|
||||
<div
|
||||
class="fixed inset-0 z-50 flex items-center justify-center bg-theme-overlay backdrop-blur-sm"
|
||||
|
|
@ -45,7 +57,7 @@
|
|||
|
||||
<div class="relative flex items-center justify-between">
|
||||
<h2 class="text-xl font-semibold text-theme-text-primary">
|
||||
{loading.title}
|
||||
{displayTitle}
|
||||
</h2>
|
||||
|
||||
<!-- Minimize button -->
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import type { ContentNode } from '$lib/types/content';
|
||||
|
||||
interface ReferenceData {
|
||||
export interface ReferenceData {
|
||||
slug: string;
|
||||
title: string;
|
||||
kind: 'character' | 'place' | 'object';
|
||||
186
games/worldream/apps/web/src/lib/stores/authStore.svelte.ts
Normal file
186
games/worldream/apps/web/src/lib/stores/authStore.svelte.ts
Normal file
|
|
@ -0,0 +1,186 @@
|
|||
/**
|
||||
* Auth Store - Manages authentication state using Svelte 5 runes
|
||||
* Using Mana Core Auth
|
||||
*/
|
||||
|
||||
import { browser } from '$app/environment';
|
||||
import { initializeWebAuth, type UserData } from '@manacore/shared-auth';
|
||||
import { PUBLIC_MANA_CORE_AUTH_URL } from '$env/static/public';
|
||||
|
||||
// Initialize Mana Core Auth only on the client side
|
||||
const MANA_AUTH_URL = PUBLIC_MANA_CORE_AUTH_URL || 'http://localhost:3001';
|
||||
|
||||
// Lazy initialization to avoid SSR issues with localStorage
|
||||
let _authService: ReturnType<typeof initializeWebAuth>['authService'] | null = null;
|
||||
let _tokenManager: ReturnType<typeof initializeWebAuth>['tokenManager'] | null = null;
|
||||
|
||||
function getAuthService() {
|
||||
if (!browser) return null;
|
||||
if (!_authService) {
|
||||
const auth = initializeWebAuth({ baseUrl: MANA_AUTH_URL });
|
||||
_authService = auth.authService;
|
||||
_tokenManager = auth.tokenManager;
|
||||
}
|
||||
return _authService;
|
||||
}
|
||||
|
||||
// State
|
||||
let user = $state<UserData | null>(null);
|
||||
let loading = $state(true);
|
||||
let initialized = $state(false);
|
||||
|
||||
export const authStore = {
|
||||
// Getters
|
||||
get user() {
|
||||
return user;
|
||||
},
|
||||
get loading() {
|
||||
return loading;
|
||||
},
|
||||
get isAuthenticated() {
|
||||
return !!user;
|
||||
},
|
||||
get initialized() {
|
||||
return initialized;
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize auth state from stored tokens
|
||||
*/
|
||||
async initialize() {
|
||||
if (initialized) return;
|
||||
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
initialized = true;
|
||||
loading = false;
|
||||
return;
|
||||
}
|
||||
|
||||
loading = true;
|
||||
try {
|
||||
const authenticated = await authService.isAuthenticated();
|
||||
if (authenticated) {
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
}
|
||||
initialized = true;
|
||||
} catch (error) {
|
||||
console.error('Failed to initialize auth:', error);
|
||||
user = null;
|
||||
} finally {
|
||||
loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sign in with email and password
|
||||
*/
|
||||
async signIn(email: string, password: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth not available on server' };
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await authService.signIn(email, password);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Login failed' };
|
||||
}
|
||||
|
||||
// Get user data from token
|
||||
const userData = await authService.getUserFromToken();
|
||||
user = userData;
|
||||
|
||||
return { success: true, error: null };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sign up with email and password
|
||||
*/
|
||||
async signUp(email: string, password: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth not available on server', needsVerification: false };
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await authService.signUp(email, password);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Signup failed', needsVerification: false };
|
||||
}
|
||||
|
||||
// Mana Core Auth requires separate login after signup
|
||||
if (result.needsVerification) {
|
||||
return { success: true, error: null, needsVerification: true };
|
||||
}
|
||||
|
||||
// Auto sign in after successful signup
|
||||
const signInResult = await this.signIn(email, password);
|
||||
return { ...signInResult, needsVerification: false };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage, needsVerification: false };
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Sign out
|
||||
*/
|
||||
async signOut() {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
user = null;
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await authService.signOut();
|
||||
user = null;
|
||||
} catch (error) {
|
||||
console.error('Sign out error:', error);
|
||||
// Clear user even if sign out fails
|
||||
user = null;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Send password reset email
|
||||
*/
|
||||
async resetPassword(email: string) {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return { success: false, error: 'Auth not available on server' };
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await authService.forgotPassword(email);
|
||||
|
||||
if (!result.success) {
|
||||
return { success: false, error: result.error || 'Password reset failed' };
|
||||
}
|
||||
|
||||
return { success: true, error: null };
|
||||
} catch (error) {
|
||||
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
||||
return { success: false, error: errorMessage };
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Get access token for API calls
|
||||
*/
|
||||
async getAccessToken() {
|
||||
const authService = getAuthService();
|
||||
if (!authService) {
|
||||
return null;
|
||||
}
|
||||
return await authService.getAppToken();
|
||||
},
|
||||
};
|
||||
|
|
@ -51,7 +51,7 @@ function createLoadingStore() {
|
|||
currentStep: -1,
|
||||
});
|
||||
|
||||
let funFactInterval: NodeJS.Timeout | null = null;
|
||||
let funFactInterval: ReturnType<typeof setInterval> | null = null;
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
|
|
@ -95,14 +95,14 @@ function createLoadingStore() {
|
|||
|
||||
// Complete current step
|
||||
if (state.currentStep >= 0 && state.currentStep < state.steps.length) {
|
||||
state.steps[state.currentStep].status = 'completed';
|
||||
const currentStep = state.steps[state.currentStep];
|
||||
currentStep.status = 'completed';
|
||||
if (message) {
|
||||
state.steps[state.currentStep].message = message;
|
||||
currentStep.message = message;
|
||||
}
|
||||
// Calculate duration for completed step
|
||||
if (state.steps[state.currentStep].startTime) {
|
||||
state.steps[state.currentStep].duration =
|
||||
now - state.steps[state.currentStep].startTime;
|
||||
if (currentStep.startTime !== undefined) {
|
||||
currentStep.duration = now - currentStep.startTime;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,8 +85,8 @@ function createThemeStore() {
|
|||
},
|
||||
toggleMode: () => {
|
||||
update((current) => {
|
||||
const newMode = current.mode === 'light' ? 'dark' : 'light';
|
||||
const newState = { ...current, mode: newMode };
|
||||
const newMode: ThemeMode = current.mode === 'light' ? 'dark' : 'light';
|
||||
const newState: ThemeState = { ...current, mode: newMode };
|
||||
applyTheme(newState);
|
||||
return newState;
|
||||
});
|
||||
|
|
@ -351,11 +351,11 @@ export function generateCssVariables(
|
|||
|
||||
// Flatten the theme colors into CSS variables
|
||||
Object.entries(colors).forEach(([category, values]) => {
|
||||
if (typeof values === 'object') {
|
||||
Object.entries(values).forEach(([key, value]) => {
|
||||
if (typeof values === 'object' && values !== null) {
|
||||
Object.entries(values as Record<string, string>).forEach(([key, value]) => {
|
||||
variables[getCssVariableName(`${category}.${key}`)] = value;
|
||||
});
|
||||
} else {
|
||||
} else if (typeof values === 'string') {
|
||||
variables[getCssVariableName(category)] = values;
|
||||
}
|
||||
});
|
||||
|
|
@ -64,6 +64,8 @@ export interface ContentData {
|
|||
_links?: Record<string, string[]>;
|
||||
_aliases?: string[];
|
||||
_i18n?: Record<string, any>;
|
||||
// Index signature für dynamische Content-Felder
|
||||
[key: string]: string | Record<string, string[]> | string[] | Record<string, any> | undefined;
|
||||
}
|
||||
|
||||
export interface StoryEntry {
|
||||
|
|
@ -11,7 +11,6 @@ marked.setOptions({
|
|||
breaks: true, // Convert \n to <br>
|
||||
gfm: true, // GitHub Flavored Markdown
|
||||
pedantic: false,
|
||||
sanitize: false, // We'll trust our own content
|
||||
});
|
||||
|
||||
/**
|
||||
|
|
@ -76,7 +75,7 @@ export async function renderMarkdownSmart(
|
|||
});
|
||||
|
||||
// 4. Render markdown
|
||||
let html = marked(protectedText);
|
||||
let html = String(marked.parse(protectedText));
|
||||
|
||||
// 5. Restore references with smart display
|
||||
placeholders.forEach((ref, index) => {
|
||||
|
|
@ -121,7 +120,7 @@ export function renderMarkdown(text: string): string {
|
|||
});
|
||||
|
||||
// Render markdown
|
||||
let html = marked(protectedText);
|
||||
let html = String(marked.parse(protectedText));
|
||||
|
||||
// Restore @references as links with formatted names
|
||||
references.forEach((ref, index) => {
|
||||
|
|
@ -1,6 +1,5 @@
|
|||
import { json, error } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
import { supabase } from '$lib/supabaseClient';
|
||||
import type { CustomFieldData, CustomFieldSchema } from '$lib/types/customFields';
|
||||
|
||||
// GET /api/nodes/[slug]/custom-data - Get custom field data for a node
|
||||
|
|
@ -14,7 +13,7 @@ export const GET: RequestHandler = async ({ params, locals }) => {
|
|||
|
||||
try {
|
||||
// Get the node with its custom data
|
||||
const { data: node, error: fetchError } = await supabase
|
||||
const { data: node, error: fetchError } = await locals.supabase
|
||||
.from('content_nodes')
|
||||
.select('id, slug, custom_data, custom_schema, owner_id, visibility')
|
||||
.eq('slug', slug)
|
||||
|
|
@ -64,7 +63,7 @@ export const PUT: RequestHandler = async ({ params, request, locals }) => {
|
|||
const customData = body.data as CustomFieldData;
|
||||
|
||||
// Get the node to check ownership and schema
|
||||
const { data: node, error: fetchError } = await supabase
|
||||
const { data: node, error: fetchError } = await locals.supabase
|
||||
.from('content_nodes')
|
||||
.select('id, owner_id, custom_schema')
|
||||
.eq('slug', slug)
|
||||
|
|
@ -88,7 +87,7 @@ export const PUT: RequestHandler = async ({ params, request, locals }) => {
|
|||
}
|
||||
|
||||
// Update the custom data
|
||||
const { error: updateError } = await supabase
|
||||
const { error: updateError } = await locals.supabase
|
||||
.from('content_nodes')
|
||||
.update({
|
||||
custom_data: customData,
|
||||
|
|
@ -132,7 +131,7 @@ export const PATCH: RequestHandler = async ({ params, request, locals }) => {
|
|||
const updates = body.data as Partial<CustomFieldData>;
|
||||
|
||||
// Get the current node data
|
||||
const { data: node, error: fetchError } = await supabase
|
||||
const { data: node, error: fetchError } = await locals.supabase
|
||||
.from('content_nodes')
|
||||
.select('id, owner_id, custom_schema, custom_data')
|
||||
.eq('slug', slug)
|
||||
|
|
@ -162,7 +161,7 @@ export const PATCH: RequestHandler = async ({ params, request, locals }) => {
|
|||
}
|
||||
|
||||
// Update the custom data
|
||||
const { error: updateError } = await supabase
|
||||
const { error: updateError } = await locals.supabase
|
||||
.from('content_nodes')
|
||||
.update({
|
||||
custom_data: mergedData,
|
||||
|
|
@ -1,8 +1,6 @@
|
|||
<script lang="ts">
|
||||
import { createClient } from '$lib/supabase/client';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
const supabase = createClient();
|
||||
import { authStore } from '$lib/stores/authStore.svelte';
|
||||
|
||||
let email = $state('');
|
||||
let password = $state('');
|
||||
|
|
@ -16,17 +14,21 @@
|
|||
|
||||
try {
|
||||
if (mode === 'login') {
|
||||
const { error: authError } = await supabase.auth.signInWithPassword({
|
||||
email,
|
||||
password,
|
||||
});
|
||||
if (authError) throw authError;
|
||||
const result = await authStore.signIn(email, password);
|
||||
if (!result.success) {
|
||||
error = result.error || 'Anmeldung fehlgeschlagen';
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
const { error: authError } = await supabase.auth.signUp({
|
||||
email,
|
||||
password,
|
||||
});
|
||||
if (authError) throw authError;
|
||||
const result = await authStore.signUp(email, password);
|
||||
if (!result.success) {
|
||||
error = result.error || 'Registrierung fehlgeschlagen';
|
||||
return;
|
||||
}
|
||||
if (result.needsVerification) {
|
||||
error = 'Bitte bestätige deine E-Mail-Adresse';
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
goto('/');
|
||||
10
games/worldream/apps/web/src/routes/auth/logout/+server.ts
Normal file
10
games/worldream/apps/web/src/routes/auth/logout/+server.ts
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
import { redirect } from '@sveltejs/kit';
|
||||
import type { RequestHandler } from './$types';
|
||||
|
||||
/**
|
||||
* Logout endpoint - redirects to login page
|
||||
* Actual logout is handled client-side by authStore.signOut()
|
||||
*/
|
||||
export const POST: RequestHandler = async () => {
|
||||
redirect(303, '/auth/login');
|
||||
};
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue