mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-17 10:39:40 +02:00
- Add uload project with apps/web structure
- Reorganize from flat to monorepo structure
- Remove PocketBase binary and local data
- Update to pnpm and @uload/web namespace
- Add picture project to monorepo
- Remove embedded git repository
- Unify all package names to @{project}/{app} schema:
- @maerchenzauber/* (was @storyteller/*)
- @manacore/* (was manacore-*, manacore)
- @manadeck/* (was web, backend, manadeck)
- @memoro/* (was memoro-web, landing, memoro)
- @picture/* (already unified)
- @uload/web
- Add convenient dev scripts for all apps:
- pnpm dev:{project}:web
- pnpm dev:{project}:landing
- pnpm dev:{project}:mobile
- pnpm dev:{project}:backend
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
146 lines
No EOL
4 KiB
TypeScript
146 lines
No EOL
4 KiB
TypeScript
import { supabase } from '~/utils/supabase';
|
|
import { getModelById } from './models';
|
|
import { logger, networkLogger } from '~/utils/logger';
|
|
|
|
export interface GenerationParams {
|
|
prompt: string;
|
|
model_id: string;
|
|
width?: number;
|
|
height?: number;
|
|
steps?: number;
|
|
guidance_scale?: number;
|
|
style?: string;
|
|
}
|
|
|
|
export async function generateImage(params: GenerationParams) {
|
|
try {
|
|
logger.info('=== Starting Image Generation ===');
|
|
logger.debug('Parameters:', params);
|
|
|
|
// Get current user
|
|
const { data: { user }, error: userError } = await supabase.auth.getUser();
|
|
|
|
if (userError || !user) {
|
|
logger.error('User authentication failed:', userError);
|
|
throw new Error('User not authenticated');
|
|
}
|
|
|
|
logger.debug('User authenticated:', user.id);
|
|
|
|
// Get model configuration
|
|
const model = await getModelById(params.model_id);
|
|
if (!model) {
|
|
throw new Error('Invalid model selected');
|
|
}
|
|
|
|
logger.debug('Using model:', model.name, model.replicate_id);
|
|
|
|
// Create generation record
|
|
logger.debug('Creating generation record...');
|
|
const { data: generation, error: generationError } = await supabase
|
|
.from('image_generations')
|
|
.insert({
|
|
user_id: user.id,
|
|
prompt: params.prompt,
|
|
negative_prompt: null,
|
|
model: model.name,
|
|
style: params.style || null,
|
|
width: params.width || model.default_width,
|
|
height: params.height || model.default_height,
|
|
steps: params.steps || model.default_steps,
|
|
guidance_scale: params.guidance_scale || model.default_guidance_scale,
|
|
status: 'pending'
|
|
})
|
|
.select()
|
|
.single();
|
|
|
|
if (generationError) {
|
|
logger.error('Failed to create generation record:', generationError);
|
|
throw generationError;
|
|
}
|
|
|
|
logger.info('Generation record created:', generation.id);
|
|
|
|
// No need to manually get session - supabase.functions.invoke() handles it
|
|
logger.debug('Calling edge function...');
|
|
|
|
networkLogger.request('generate-image', 'POST', {
|
|
generation_id: generation.id,
|
|
model: model.replicate_id,
|
|
});
|
|
|
|
// Call Edge Function to generate image
|
|
// Explicitly pass the authorization header
|
|
const requestBody = {
|
|
prompt: params.prompt,
|
|
negative_prompt: undefined,
|
|
model_id: model.replicate_id,
|
|
model_version: model.version,
|
|
width: params.width || model.default_width,
|
|
height: params.height || model.default_height,
|
|
num_inference_steps: params.steps || model.default_steps,
|
|
guidance_scale: params.guidance_scale || model.default_guidance_scale,
|
|
generation_id: generation.id
|
|
};
|
|
|
|
logger.debug('Request body:', requestBody);
|
|
|
|
// Use supabase.functions.invoke which handles auth properly
|
|
// It automatically includes both the apikey and Authorization headers
|
|
const { data, error } = await supabase.functions.invoke('generate-image', {
|
|
body: requestBody,
|
|
});
|
|
|
|
if (error) {
|
|
logger.error('Edge function error:', error);
|
|
networkLogger.error('generate-image', error);
|
|
|
|
// Update generation status to failed
|
|
await supabase
|
|
.from('image_generations')
|
|
.update({
|
|
status: 'failed',
|
|
error_message: error.message
|
|
})
|
|
.eq('id', generation.id);
|
|
|
|
throw error;
|
|
}
|
|
|
|
networkLogger.response('generate-image', 200, data);
|
|
logger.success('Image generation successful');
|
|
return data;
|
|
} catch (error: any) {
|
|
logger.error('Generation error:', error);
|
|
logger.debug('Error stack:', error.stack);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
export async function getGenerationStatus(generationId: string) {
|
|
const { data, error } = await supabase
|
|
.from('image_generations')
|
|
.select('*')
|
|
.eq('id', generationId)
|
|
.single();
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
export async function getUserImages(userId: string) {
|
|
const { data, error } = await supabase
|
|
.from('images')
|
|
.select('*')
|
|
.eq('user_id', userId)
|
|
.order('created_at', { ascending: false });
|
|
|
|
if (error) {
|
|
throw error;
|
|
}
|
|
|
|
return data;
|
|
} |