mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-21 23:46:41 +02:00
refactor: restructure
monorepo with apps/ and services/ directories
This commit is contained in:
parent
25824ed0ac
commit
ff80aeec1f
4062 changed files with 2592 additions and 1278 deletions
1
apps/picture/packages/shared/src/api/index.ts
Normal file
1
apps/picture/packages/shared/src/api/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './supabase'
|
||||
8
apps/picture/packages/shared/src/api/supabase.ts
Normal file
8
apps/picture/packages/shared/src/api/supabase.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
import { createClient } from '@supabase/supabase-js'
|
||||
import type { Database } from '../types/database.types'
|
||||
|
||||
export function createSupabaseClient(supabaseUrl: string, supabaseAnonKey: string) {
|
||||
return createClient<Database>(supabaseUrl, supabaseAnonKey)
|
||||
}
|
||||
|
||||
export type SupabaseClient = ReturnType<typeof createSupabaseClient>
|
||||
4
apps/picture/packages/shared/src/index.ts
Normal file
4
apps/picture/packages/shared/src/index.ts
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
export * from './types'
|
||||
export * from './api'
|
||||
export * from './utils'
|
||||
export * from './queue'
|
||||
534
apps/picture/packages/shared/src/queue.ts
Normal file
534
apps/picture/packages/shared/src/queue.ts
Normal file
|
|
@ -0,0 +1,534 @@
|
|||
/**
|
||||
* Job Queue Helper Functions
|
||||
*
|
||||
* Provides client-side utilities for interacting with the async job queue system.
|
||||
* Uses Supabase database functions to enqueue jobs and monitor status.
|
||||
*/
|
||||
|
||||
import type { SupabaseClient } from '@supabase/supabase-js';
|
||||
import type { Database } from './types';
|
||||
|
||||
// ============================================================================
|
||||
// TYPES
|
||||
// ============================================================================
|
||||
|
||||
export type JobType = 'generate-image' | 'download-image' | 'process-webhook' | 'cleanup-storage';
|
||||
|
||||
export type JobStatus = 'pending' | 'processing' | 'completed' | 'failed' | 'cancelled';
|
||||
|
||||
export interface JobQueueRow {
|
||||
id: string;
|
||||
job_type: JobType;
|
||||
payload: Record<string, any>;
|
||||
status: JobStatus;
|
||||
attempts: number;
|
||||
max_attempts: number;
|
||||
scheduled_at: string;
|
||||
started_at: string | null;
|
||||
completed_at: string | null;
|
||||
error_message: string | null;
|
||||
error_details: Record<string, any> | null;
|
||||
created_by: string | null;
|
||||
priority: number;
|
||||
created_at: string;
|
||||
updated_at: string;
|
||||
}
|
||||
|
||||
export interface EnqueueJobParams {
|
||||
jobType: JobType;
|
||||
payload: Record<string, any>;
|
||||
priority?: number;
|
||||
scheduledAt?: Date;
|
||||
maxAttempts?: number;
|
||||
}
|
||||
|
||||
export interface JobStats {
|
||||
total: number;
|
||||
pending: number;
|
||||
processing: number;
|
||||
completed: number;
|
||||
failed: number;
|
||||
avgDurationSeconds: number;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// QUEUE FUNCTIONS
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Enqueue a new job for background processing
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const jobId = await enqueueJob(supabase, {
|
||||
* jobType: 'generate-image',
|
||||
* payload: { prompt: 'A beautiful sunset', model_id: 'flux-dev' },
|
||||
* priority: 10
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export async function enqueueJob(
|
||||
supabase: SupabaseClient<Database>,
|
||||
params: EnqueueJobParams
|
||||
): Promise<string> {
|
||||
const {
|
||||
jobType,
|
||||
payload,
|
||||
priority = 0,
|
||||
scheduledAt = new Date(),
|
||||
maxAttempts = 3
|
||||
} = params;
|
||||
|
||||
const { data, error } = await supabase.rpc('enqueue_job', {
|
||||
p_job_type: jobType,
|
||||
p_payload: payload as any,
|
||||
p_priority: priority,
|
||||
p_scheduled_at: scheduledAt.toISOString(),
|
||||
p_max_attempts: maxAttempts
|
||||
});
|
||||
|
||||
if (error) {
|
||||
console.error('Failed to enqueue job:', error);
|
||||
throw new Error(`Failed to enqueue job: ${error.message}`);
|
||||
}
|
||||
|
||||
return data as string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get job by ID
|
||||
*/
|
||||
export async function getJob(
|
||||
supabase: SupabaseClient<Database>,
|
||||
jobId: string
|
||||
): Promise<JobQueueRow | null> {
|
||||
const { data, error } = await supabase
|
||||
.from('job_queue')
|
||||
.select('*')
|
||||
.eq('id', jobId)
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
if (error.code === 'PGRST116') {
|
||||
return null; // Not found
|
||||
}
|
||||
throw error;
|
||||
}
|
||||
|
||||
return data as JobQueueRow;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all jobs for current user
|
||||
*/
|
||||
export async function getUserJobs(
|
||||
supabase: SupabaseClient<Database>,
|
||||
options?: {
|
||||
status?: JobStatus;
|
||||
limit?: number;
|
||||
offset?: number;
|
||||
}
|
||||
): Promise<JobQueueRow[]> {
|
||||
let query = supabase
|
||||
.from('job_queue')
|
||||
.select('*')
|
||||
.order('created_at', { ascending: false });
|
||||
|
||||
if (options?.status) {
|
||||
query = query.eq('status', options.status);
|
||||
}
|
||||
|
||||
if (options?.limit) {
|
||||
query = query.limit(options.limit);
|
||||
}
|
||||
|
||||
if (options?.offset) {
|
||||
query = query.range(options.offset, options.offset + (options.limit || 10) - 1);
|
||||
}
|
||||
|
||||
const { data, error } = await query;
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return (data || []) as JobQueueRow[];
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel a pending job
|
||||
*/
|
||||
export async function cancelJob(
|
||||
supabase: SupabaseClient<Database>,
|
||||
jobId: string
|
||||
): Promise<void> {
|
||||
const { error } = await supabase
|
||||
.from('job_queue')
|
||||
.update({ status: 'cancelled', updated_at: new Date().toISOString() })
|
||||
.eq('id', jobId)
|
||||
.eq('status', 'pending'); // Only cancel pending jobs
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to cancel job: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get queue health statistics
|
||||
*/
|
||||
export async function getQueueStats(
|
||||
supabase: SupabaseClient<Database>,
|
||||
jobType?: JobType
|
||||
): Promise<JobStats> {
|
||||
const { data, error } = await supabase
|
||||
.from('queue_health')
|
||||
.select('*');
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
// Aggregate stats
|
||||
let stats: JobStats = {
|
||||
total: 0,
|
||||
pending: 0,
|
||||
processing: 0,
|
||||
completed: 0,
|
||||
failed: 0,
|
||||
avgDurationSeconds: 0
|
||||
};
|
||||
|
||||
const filtered = jobType
|
||||
? data?.filter(row => row.job_type === jobType)
|
||||
: data;
|
||||
|
||||
filtered?.forEach(row => {
|
||||
const count = row.count || 0;
|
||||
stats.total += count;
|
||||
|
||||
switch (row.status) {
|
||||
case 'pending':
|
||||
stats.pending += count;
|
||||
break;
|
||||
case 'processing':
|
||||
stats.processing += count;
|
||||
break;
|
||||
case 'completed':
|
||||
stats.completed += count;
|
||||
break;
|
||||
case 'failed':
|
||||
stats.failed += count;
|
||||
break;
|
||||
}
|
||||
|
||||
if (row.avg_duration_seconds) {
|
||||
stats.avgDurationSeconds = row.avg_duration_seconds;
|
||||
}
|
||||
});
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get failed jobs (last 24 hours)
|
||||
*/
|
||||
export async function getRecentFailedJobs(
|
||||
supabase: SupabaseClient<Database>
|
||||
): Promise<JobQueueRow[]> {
|
||||
const { data, error } = await supabase
|
||||
.from('failed_jobs_recent')
|
||||
.select('*');
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return (data || []) as JobQueueRow[];
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// REALTIME SUBSCRIPTION HELPERS
|
||||
// ============================================================================
|
||||
|
||||
export type JobUpdateCallback = (job: JobQueueRow) => void;
|
||||
|
||||
/**
|
||||
* Subscribe to job updates via Realtime
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const unsubscribe = subscribeToJob(supabase, jobId, (job) => {
|
||||
* console.log('Job updated:', job.status);
|
||||
* if (job.status === 'completed') {
|
||||
* unsubscribe();
|
||||
* }
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export function subscribeToJob(
|
||||
supabase: SupabaseClient<Database>,
|
||||
jobId: string,
|
||||
callback: JobUpdateCallback
|
||||
): () => void {
|
||||
const channel = supabase
|
||||
.channel(`job:${jobId}`)
|
||||
.on(
|
||||
'postgres_changes',
|
||||
{
|
||||
event: 'UPDATE',
|
||||
schema: 'public',
|
||||
table: 'job_queue',
|
||||
filter: `id=eq.${jobId}`
|
||||
},
|
||||
(payload) => {
|
||||
callback(payload.new as JobQueueRow);
|
||||
}
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
return () => {
|
||||
channel.unsubscribe();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to all job updates for current user
|
||||
*/
|
||||
export function subscribeToUserJobs(
|
||||
supabase: SupabaseClient<Database>,
|
||||
userId: string,
|
||||
callback: JobUpdateCallback
|
||||
): () => void {
|
||||
const channel = supabase
|
||||
.channel(`user-jobs:${userId}`)
|
||||
.on(
|
||||
'postgres_changes',
|
||||
{
|
||||
event: '*',
|
||||
schema: 'public',
|
||||
table: 'job_queue',
|
||||
filter: `created_by=eq.${userId}`
|
||||
},
|
||||
(payload) => {
|
||||
if (payload.new) {
|
||||
callback(payload.new as JobQueueRow);
|
||||
}
|
||||
}
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
return () => {
|
||||
channel.unsubscribe();
|
||||
};
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// IMAGE GENERATION HELPERS (Convenience wrappers)
|
||||
// ============================================================================
|
||||
|
||||
export interface GenerateImageJobParams {
|
||||
prompt: string;
|
||||
model_id: string;
|
||||
model_version?: string;
|
||||
width?: number;
|
||||
height?: number;
|
||||
num_inference_steps?: number;
|
||||
guidance_scale?: number;
|
||||
seed?: number;
|
||||
negative_prompt?: string;
|
||||
source_image_url?: string;
|
||||
strength?: number;
|
||||
style?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start an image generation job (high-level wrapper)
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const { generationId, jobId } = await startImageGeneration(supabase, {
|
||||
* prompt: 'A beautiful sunset over mountains',
|
||||
* model_id: 'black-forest-labs/flux-dev'
|
||||
* });
|
||||
*
|
||||
* // Subscribe to updates
|
||||
* subscribeToGeneration(supabase, generationId, (generation) => {
|
||||
* console.log('Status:', generation.status);
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
export async function startImageGeneration(
|
||||
supabase: SupabaseClient<Database>,
|
||||
params: GenerateImageJobParams
|
||||
): Promise<{ generationId: string; jobId: string }> {
|
||||
// Call start-generation Edge Function
|
||||
const { data, error } = await supabase.functions.invoke('start-generation', {
|
||||
body: params
|
||||
});
|
||||
|
||||
if (error) {
|
||||
throw new Error(`Failed to start generation: ${error.message}`);
|
||||
}
|
||||
|
||||
if (!data.success) {
|
||||
throw new Error(data.error || 'Failed to start generation');
|
||||
}
|
||||
|
||||
return {
|
||||
generationId: data.generation_id,
|
||||
jobId: data.job_id
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Subscribe to generation updates via Realtime
|
||||
*/
|
||||
export function subscribeToGeneration(
|
||||
supabase: SupabaseClient<Database>,
|
||||
generationId: string,
|
||||
callback: (generation: any) => void
|
||||
): () => void {
|
||||
const channel = supabase
|
||||
.channel(`generation:${generationId}`)
|
||||
.on(
|
||||
'postgres_changes',
|
||||
{
|
||||
event: 'UPDATE',
|
||||
schema: 'public',
|
||||
table: 'image_generations',
|
||||
filter: `id=eq.${generationId}`
|
||||
},
|
||||
(payload) => {
|
||||
callback(payload.new);
|
||||
}
|
||||
)
|
||||
.subscribe();
|
||||
|
||||
return () => {
|
||||
channel.unsubscribe();
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Combined helper: Start generation and subscribe to updates
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
* const { generationId, unsubscribe } = await generateImageWithUpdates(
|
||||
* supabase,
|
||||
* { prompt: 'A sunset', model_id: 'flux-dev' },
|
||||
* (generation) => {
|
||||
* console.log('Status:', generation.status);
|
||||
* if (generation.status === 'completed') {
|
||||
* console.log('Image ready!', generation.id);
|
||||
* unsubscribe();
|
||||
* }
|
||||
* }
|
||||
* );
|
||||
* ```
|
||||
*/
|
||||
export async function generateImageWithUpdates(
|
||||
supabase: SupabaseClient<Database>,
|
||||
params: GenerateImageJobParams,
|
||||
onUpdate: (generation: any) => void
|
||||
): Promise<{ generationId: string; jobId: string; unsubscribe: () => void }> {
|
||||
// Start generation
|
||||
const { generationId, jobId } = await startImageGeneration(supabase, params);
|
||||
|
||||
// Subscribe to updates
|
||||
const unsubscribe = subscribeToGeneration(supabase, generationId, onUpdate);
|
||||
|
||||
return { generationId, jobId, unsubscribe };
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// POLLING HELPERS (fallback if Realtime not available)
|
||||
// ============================================================================
|
||||
|
||||
/**
|
||||
* Poll for job status (fallback for environments without Realtime)
|
||||
*/
|
||||
export async function pollJobUntilComplete(
|
||||
supabase: SupabaseClient<Database>,
|
||||
jobId: string,
|
||||
options: {
|
||||
maxAttempts?: number;
|
||||
intervalMs?: number;
|
||||
onUpdate?: JobUpdateCallback;
|
||||
} = {}
|
||||
): Promise<JobQueueRow> {
|
||||
const {
|
||||
maxAttempts = 60,
|
||||
intervalMs = 2000,
|
||||
onUpdate
|
||||
} = options;
|
||||
|
||||
let attempts = 0;
|
||||
|
||||
while (attempts < maxAttempts) {
|
||||
const job = await getJob(supabase, jobId);
|
||||
|
||||
if (!job) {
|
||||
throw new Error('Job not found');
|
||||
}
|
||||
|
||||
if (onUpdate) {
|
||||
onUpdate(job);
|
||||
}
|
||||
|
||||
if (job.status === 'completed' || job.status === 'failed' || job.status === 'cancelled') {
|
||||
return job;
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Error('Job polling timeout');
|
||||
}
|
||||
|
||||
/**
|
||||
* Poll for generation completion
|
||||
*/
|
||||
export async function pollGenerationUntilComplete(
|
||||
supabase: SupabaseClient<Database>,
|
||||
generationId: string,
|
||||
options: {
|
||||
maxAttempts?: number;
|
||||
intervalMs?: number;
|
||||
onUpdate?: (generation: any) => void;
|
||||
} = {}
|
||||
): Promise<any> {
|
||||
const {
|
||||
maxAttempts = 120,
|
||||
intervalMs = 2000,
|
||||
onUpdate
|
||||
} = options;
|
||||
|
||||
let attempts = 0;
|
||||
|
||||
while (attempts < maxAttempts) {
|
||||
const { data: generation, error } = await supabase
|
||||
.from('image_generations')
|
||||
.select('*')
|
||||
.eq('id', generationId)
|
||||
.single();
|
||||
|
||||
if (error) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
if (onUpdate) {
|
||||
onUpdate(generation);
|
||||
}
|
||||
|
||||
if (generation.status === 'completed' || generation.status === 'failed') {
|
||||
return generation;
|
||||
}
|
||||
|
||||
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
||||
attempts++;
|
||||
}
|
||||
|
||||
throw new Error('Generation polling timeout');
|
||||
}
|
||||
969
apps/picture/packages/shared/src/types/database.types.ts
Normal file
969
apps/picture/packages/shared/src/types/database.types.ts
Normal file
|
|
@ -0,0 +1,969 @@
|
|||
export type Json =
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null
|
||||
| { [key: string]: Json | undefined }
|
||||
| Json[]
|
||||
|
||||
export type Database = {
|
||||
// Allows to automatically instantiate createClient with right options
|
||||
// instead of createClient<Database, { PostgrestVersion: 'XX' }>(URL, KEY)
|
||||
__InternalSupabase: {
|
||||
PostgrestVersion: "13.0.4"
|
||||
}
|
||||
public: {
|
||||
Tables: {
|
||||
batch_generations: {
|
||||
Row: {
|
||||
completed_at: string | null
|
||||
completed_count: number | null
|
||||
created_at: string | null
|
||||
failed_count: number | null
|
||||
guidance_scale: number | null
|
||||
height: number | null
|
||||
id: string
|
||||
is_multi_generation: boolean | null
|
||||
model_id: string | null
|
||||
model_version: string | null
|
||||
multi_count: number | null
|
||||
name: string | null
|
||||
status: string | null
|
||||
steps: number | null
|
||||
total_count: number
|
||||
user_id: string | null
|
||||
width: number | null
|
||||
}
|
||||
Insert: {
|
||||
completed_at?: string | null
|
||||
completed_count?: number | null
|
||||
created_at?: string | null
|
||||
failed_count?: number | null
|
||||
guidance_scale?: number | null
|
||||
height?: number | null
|
||||
id?: string
|
||||
is_multi_generation?: boolean | null
|
||||
model_id?: string | null
|
||||
model_version?: string | null
|
||||
multi_count?: number | null
|
||||
name?: string | null
|
||||
status?: string | null
|
||||
steps?: number | null
|
||||
total_count: number
|
||||
user_id?: string | null
|
||||
width?: number | null
|
||||
}
|
||||
Update: {
|
||||
completed_at?: string | null
|
||||
completed_count?: number | null
|
||||
created_at?: string | null
|
||||
failed_count?: number | null
|
||||
guidance_scale?: number | null
|
||||
height?: number | null
|
||||
id?: string
|
||||
is_multi_generation?: boolean | null
|
||||
model_id?: string | null
|
||||
model_version?: string | null
|
||||
multi_count?: number | null
|
||||
name?: string | null
|
||||
status?: string | null
|
||||
steps?: number | null
|
||||
total_count?: number
|
||||
user_id?: string | null
|
||||
width?: number | null
|
||||
}
|
||||
Relationships: []
|
||||
}
|
||||
generation_errors: {
|
||||
Row: {
|
||||
batch_id: string | null
|
||||
created_at: string | null
|
||||
error_details: Json | null
|
||||
error_message: string | null
|
||||
error_type: string | null
|
||||
generation_id: string | null
|
||||
id: string
|
||||
max_retries: number | null
|
||||
recovered_at: string | null
|
||||
recovery_action: string | null
|
||||
retry_after: string | null
|
||||
retry_count: number | null
|
||||
user_id: string | null
|
||||
}
|
||||
Insert: {
|
||||
batch_id?: string | null
|
||||
created_at?: string | null
|
||||
error_details?: Json | null
|
||||
error_message?: string | null
|
||||
error_type?: string | null
|
||||
generation_id?: string | null
|
||||
id?: string
|
||||
max_retries?: number | null
|
||||
recovered_at?: string | null
|
||||
recovery_action?: string | null
|
||||
retry_after?: string | null
|
||||
retry_count?: number | null
|
||||
user_id?: string | null
|
||||
}
|
||||
Update: {
|
||||
batch_id?: string | null
|
||||
created_at?: string | null
|
||||
error_details?: Json | null
|
||||
error_message?: string | null
|
||||
error_type?: string | null
|
||||
generation_id?: string | null
|
||||
id?: string
|
||||
max_retries?: number | null
|
||||
recovered_at?: string | null
|
||||
recovery_action?: string | null
|
||||
retry_after?: string | null
|
||||
retry_count?: number | null
|
||||
user_id?: string | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "generation_errors_batch_id_fkey"
|
||||
columns: ["batch_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "batch_generations"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "generation_errors_batch_id_fkey"
|
||||
columns: ["batch_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "batch_progress"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "generation_errors_generation_id_fkey"
|
||||
columns: ["generation_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "image_generations"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
generation_performance: {
|
||||
Row: {
|
||||
batch_id: string | null
|
||||
completed_at: string | null
|
||||
created_at: string | null
|
||||
error_message: string | null
|
||||
generation_id: string | null
|
||||
height: number | null
|
||||
id: string
|
||||
model_id: string | null
|
||||
model_version: string | null
|
||||
processing_time_ms: number | null
|
||||
queue_time_ms: number | null
|
||||
retry_count: number | null
|
||||
started_at: string | null
|
||||
status: string | null
|
||||
steps: number | null
|
||||
total_time_ms: number | null
|
||||
user_id: string | null
|
||||
width: number | null
|
||||
}
|
||||
Insert: {
|
||||
batch_id?: string | null
|
||||
completed_at?: string | null
|
||||
created_at?: string | null
|
||||
error_message?: string | null
|
||||
generation_id?: string | null
|
||||
height?: number | null
|
||||
id?: string
|
||||
model_id?: string | null
|
||||
model_version?: string | null
|
||||
processing_time_ms?: number | null
|
||||
queue_time_ms?: number | null
|
||||
retry_count?: number | null
|
||||
started_at?: string | null
|
||||
status?: string | null
|
||||
steps?: number | null
|
||||
total_time_ms?: number | null
|
||||
user_id?: string | null
|
||||
width?: number | null
|
||||
}
|
||||
Update: {
|
||||
batch_id?: string | null
|
||||
completed_at?: string | null
|
||||
created_at?: string | null
|
||||
error_message?: string | null
|
||||
generation_id?: string | null
|
||||
height?: number | null
|
||||
id?: string
|
||||
model_id?: string | null
|
||||
model_version?: string | null
|
||||
processing_time_ms?: number | null
|
||||
queue_time_ms?: number | null
|
||||
retry_count?: number | null
|
||||
started_at?: string | null
|
||||
status?: string | null
|
||||
steps?: number | null
|
||||
total_time_ms?: number | null
|
||||
user_id?: string | null
|
||||
width?: number | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "generation_performance_batch_id_fkey"
|
||||
columns: ["batch_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "batch_generations"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "generation_performance_batch_id_fkey"
|
||||
columns: ["batch_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "batch_progress"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "generation_performance_generation_id_fkey"
|
||||
columns: ["generation_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "image_generations"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
image_generations: {
|
||||
Row: {
|
||||
batch_id: string | null
|
||||
batch_index: number | null
|
||||
completed_at: string | null
|
||||
created_at: string | null
|
||||
error_message: string | null
|
||||
generation_strength: number | null
|
||||
generation_time_seconds: number | null
|
||||
guidance_scale: number | null
|
||||
height: number | null
|
||||
id: string
|
||||
model: string | null
|
||||
model_id: string | null
|
||||
multi_group_id: string | null
|
||||
multi_index: number | null
|
||||
negative_prompt: string | null
|
||||
priority: number | null
|
||||
prompt: string
|
||||
replicate_prediction_id: string | null
|
||||
retry_count: number | null
|
||||
seed: number | null
|
||||
source_image_url: string | null
|
||||
status: string | null
|
||||
steps: number | null
|
||||
style: string | null
|
||||
user_id: string | null
|
||||
width: number | null
|
||||
}
|
||||
Insert: {
|
||||
batch_id?: string | null
|
||||
batch_index?: number | null
|
||||
completed_at?: string | null
|
||||
created_at?: string | null
|
||||
error_message?: string | null
|
||||
generation_strength?: number | null
|
||||
generation_time_seconds?: number | null
|
||||
guidance_scale?: number | null
|
||||
height?: number | null
|
||||
id?: string
|
||||
model?: string | null
|
||||
model_id?: string | null
|
||||
multi_group_id?: string | null
|
||||
multi_index?: number | null
|
||||
negative_prompt?: string | null
|
||||
priority?: number | null
|
||||
prompt: string
|
||||
replicate_prediction_id?: string | null
|
||||
retry_count?: number | null
|
||||
seed?: number | null
|
||||
source_image_url?: string | null
|
||||
status?: string | null
|
||||
steps?: number | null
|
||||
style?: string | null
|
||||
user_id?: string | null
|
||||
width?: number | null
|
||||
}
|
||||
Update: {
|
||||
batch_id?: string | null
|
||||
batch_index?: number | null
|
||||
completed_at?: string | null
|
||||
created_at?: string | null
|
||||
error_message?: string | null
|
||||
generation_strength?: number | null
|
||||
generation_time_seconds?: number | null
|
||||
guidance_scale?: number | null
|
||||
height?: number | null
|
||||
id?: string
|
||||
model?: string | null
|
||||
model_id?: string | null
|
||||
multi_group_id?: string | null
|
||||
multi_index?: number | null
|
||||
negative_prompt?: string | null
|
||||
priority?: number | null
|
||||
prompt?: string
|
||||
replicate_prediction_id?: string | null
|
||||
retry_count?: number | null
|
||||
seed?: number | null
|
||||
source_image_url?: string | null
|
||||
status?: string | null
|
||||
steps?: number | null
|
||||
style?: string | null
|
||||
user_id?: string | null
|
||||
width?: number | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "image_generations_batch_id_fkey"
|
||||
columns: ["batch_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "batch_generations"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "image_generations_batch_id_fkey"
|
||||
columns: ["batch_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "batch_progress"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "image_generations_model_id_fkey"
|
||||
columns: ["model_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "models"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "image_generations_user_id_fkey"
|
||||
columns: ["user_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "profiles"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
image_likes: {
|
||||
Row: {
|
||||
created_at: string | null
|
||||
id: string
|
||||
image_id: string | null
|
||||
user_id: string | null
|
||||
}
|
||||
Insert: {
|
||||
created_at?: string | null
|
||||
id?: string
|
||||
image_id?: string | null
|
||||
user_id?: string | null
|
||||
}
|
||||
Update: {
|
||||
created_at?: string | null
|
||||
id?: string
|
||||
image_id?: string | null
|
||||
user_id?: string | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "image_likes_image_id_fkey"
|
||||
columns: ["image_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "images"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "image_likes_user_id_fkey"
|
||||
columns: ["user_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "profiles"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
image_tags: {
|
||||
Row: {
|
||||
added_at: string | null
|
||||
id: string
|
||||
image_id: string | null
|
||||
tag_id: string | null
|
||||
}
|
||||
Insert: {
|
||||
added_at?: string | null
|
||||
id?: string
|
||||
image_id?: string | null
|
||||
tag_id?: string | null
|
||||
}
|
||||
Update: {
|
||||
added_at?: string | null
|
||||
id?: string
|
||||
image_id?: string | null
|
||||
tag_id?: string | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "image_tags_image_id_fkey"
|
||||
columns: ["image_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "images"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "image_tags_tag_id_fkey"
|
||||
columns: ["tag_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "tags"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
images: {
|
||||
Row: {
|
||||
archived_at: string | null
|
||||
blurhash: string | null
|
||||
created_at: string | null
|
||||
download_count: number | null
|
||||
file_size: number | null
|
||||
filename: string
|
||||
format: string | null
|
||||
generation_id: string | null
|
||||
generation_strength: number | null
|
||||
height: number | null
|
||||
id: string
|
||||
is_favorite: boolean | null
|
||||
is_public: boolean | null
|
||||
model: string | null
|
||||
negative_prompt: string | null
|
||||
prompt: string
|
||||
public_url: string | null
|
||||
rating: number | null
|
||||
source_image_id: string | null
|
||||
storage_path: string
|
||||
style: string | null
|
||||
user_id: string | null
|
||||
width: number | null
|
||||
}
|
||||
Insert: {
|
||||
archived_at?: string | null
|
||||
blurhash?: string | null
|
||||
created_at?: string | null
|
||||
download_count?: number | null
|
||||
file_size?: number | null
|
||||
filename: string
|
||||
format?: string | null
|
||||
generation_id?: string | null
|
||||
generation_strength?: number | null
|
||||
height?: number | null
|
||||
id?: string
|
||||
is_favorite?: boolean | null
|
||||
is_public?: boolean | null
|
||||
model?: string | null
|
||||
negative_prompt?: string | null
|
||||
prompt: string
|
||||
public_url?: string | null
|
||||
rating?: number | null
|
||||
source_image_id?: string | null
|
||||
storage_path: string
|
||||
style?: string | null
|
||||
user_id?: string | null
|
||||
width?: number | null
|
||||
}
|
||||
Update: {
|
||||
archived_at?: string | null
|
||||
blurhash?: string | null
|
||||
created_at?: string | null
|
||||
download_count?: number | null
|
||||
file_size?: number | null
|
||||
filename?: string
|
||||
format?: string | null
|
||||
generation_id?: string | null
|
||||
generation_strength?: number | null
|
||||
height?: number | null
|
||||
id?: string
|
||||
is_favorite?: boolean | null
|
||||
is_public?: boolean | null
|
||||
model?: string | null
|
||||
negative_prompt?: string | null
|
||||
prompt?: string
|
||||
public_url?: string | null
|
||||
rating?: number | null
|
||||
source_image_id?: string | null
|
||||
storage_path?: string
|
||||
style?: string | null
|
||||
user_id?: string | null
|
||||
width?: number | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "images_generation_id_fkey"
|
||||
columns: ["generation_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "image_generations"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "images_source_image_id_fkey"
|
||||
columns: ["source_image_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "images"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
{
|
||||
foreignKeyName: "images_user_id_fkey"
|
||||
columns: ["user_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "profiles"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
models: {
|
||||
Row: {
|
||||
cost_per_generation: number | null
|
||||
created_at: string | null
|
||||
default_guidance_scale: number | null
|
||||
default_height: number | null
|
||||
default_steps: number | null
|
||||
default_strength: number | null
|
||||
default_width: number | null
|
||||
description: string | null
|
||||
display_name: string
|
||||
estimated_time_seconds: number | null
|
||||
id: string
|
||||
is_active: boolean | null
|
||||
is_default: boolean | null
|
||||
max_height: number | null
|
||||
max_steps: number | null
|
||||
max_width: number | null
|
||||
min_height: number | null
|
||||
min_width: number | null
|
||||
name: string
|
||||
replicate_id: string
|
||||
sort_order: number | null
|
||||
strength_max: number | null
|
||||
strength_min: number | null
|
||||
supported_aspect_ratios: Json | null
|
||||
supports_image_to_image: boolean | null
|
||||
supports_img2img: boolean | null
|
||||
supports_negative_prompt: boolean | null
|
||||
supports_seed: boolean | null
|
||||
updated_at: string | null
|
||||
version: string | null
|
||||
}
|
||||
Insert: {
|
||||
cost_per_generation?: number | null
|
||||
created_at?: string | null
|
||||
default_guidance_scale?: number | null
|
||||
default_height?: number | null
|
||||
default_steps?: number | null
|
||||
default_strength?: number | null
|
||||
default_width?: number | null
|
||||
description?: string | null
|
||||
display_name: string
|
||||
estimated_time_seconds?: number | null
|
||||
id?: string
|
||||
is_active?: boolean | null
|
||||
is_default?: boolean | null
|
||||
max_height?: number | null
|
||||
max_steps?: number | null
|
||||
max_width?: number | null
|
||||
min_height?: number | null
|
||||
min_width?: number | null
|
||||
name: string
|
||||
replicate_id: string
|
||||
sort_order?: number | null
|
||||
strength_max?: number | null
|
||||
strength_min?: number | null
|
||||
supported_aspect_ratios?: Json | null
|
||||
supports_image_to_image?: boolean | null
|
||||
supports_img2img?: boolean | null
|
||||
supports_negative_prompt?: boolean | null
|
||||
supports_seed?: boolean | null
|
||||
updated_at?: string | null
|
||||
version?: string | null
|
||||
}
|
||||
Update: {
|
||||
cost_per_generation?: number | null
|
||||
created_at?: string | null
|
||||
default_guidance_scale?: number | null
|
||||
default_height?: number | null
|
||||
default_steps?: number | null
|
||||
default_strength?: number | null
|
||||
default_width?: number | null
|
||||
description?: string | null
|
||||
display_name?: string
|
||||
estimated_time_seconds?: number | null
|
||||
id?: string
|
||||
is_active?: boolean | null
|
||||
is_default?: boolean | null
|
||||
max_height?: number | null
|
||||
max_steps?: number | null
|
||||
max_width?: number | null
|
||||
min_height?: number | null
|
||||
min_width?: number | null
|
||||
name?: string
|
||||
replicate_id?: string
|
||||
sort_order?: number | null
|
||||
strength_max?: number | null
|
||||
strength_min?: number | null
|
||||
supported_aspect_ratios?: Json | null
|
||||
supports_image_to_image?: boolean | null
|
||||
supports_img2img?: boolean | null
|
||||
supports_negative_prompt?: boolean | null
|
||||
supports_seed?: boolean | null
|
||||
updated_at?: string | null
|
||||
version?: string | null
|
||||
}
|
||||
Relationships: []
|
||||
}
|
||||
profiles: {
|
||||
Row: {
|
||||
avatar_url: string | null
|
||||
created_at: string | null
|
||||
email: string | null
|
||||
id: string
|
||||
updated_at: string | null
|
||||
username: string | null
|
||||
}
|
||||
Insert: {
|
||||
avatar_url?: string | null
|
||||
created_at?: string | null
|
||||
email?: string | null
|
||||
id: string
|
||||
updated_at?: string | null
|
||||
username?: string | null
|
||||
}
|
||||
Update: {
|
||||
avatar_url?: string | null
|
||||
created_at?: string | null
|
||||
email?: string | null
|
||||
id?: string
|
||||
updated_at?: string | null
|
||||
username?: string | null
|
||||
}
|
||||
Relationships: []
|
||||
}
|
||||
prompt_templates: {
|
||||
Row: {
|
||||
category: string | null
|
||||
created_at: string | null
|
||||
id: string
|
||||
is_public: boolean | null
|
||||
name: string
|
||||
negative_prompt: string | null
|
||||
prompt: string
|
||||
use_count: number | null
|
||||
user_id: string | null
|
||||
}
|
||||
Insert: {
|
||||
category?: string | null
|
||||
created_at?: string | null
|
||||
id?: string
|
||||
is_public?: boolean | null
|
||||
name: string
|
||||
negative_prompt?: string | null
|
||||
prompt: string
|
||||
use_count?: number | null
|
||||
user_id?: string | null
|
||||
}
|
||||
Update: {
|
||||
category?: string | null
|
||||
created_at?: string | null
|
||||
id?: string
|
||||
is_public?: boolean | null
|
||||
name?: string
|
||||
negative_prompt?: string | null
|
||||
prompt?: string
|
||||
use_count?: number | null
|
||||
user_id?: string | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "prompt_templates_user_id_fkey"
|
||||
columns: ["user_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "profiles"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
tags: {
|
||||
Row: {
|
||||
color: string | null
|
||||
created_at: string | null
|
||||
id: string
|
||||
name: string
|
||||
}
|
||||
Insert: {
|
||||
color?: string | null
|
||||
created_at?: string | null
|
||||
id?: string
|
||||
name: string
|
||||
}
|
||||
Update: {
|
||||
color?: string | null
|
||||
created_at?: string | null
|
||||
id?: string
|
||||
name?: string
|
||||
}
|
||||
Relationships: []
|
||||
}
|
||||
user_rate_limits: {
|
||||
Row: {
|
||||
daily_generations_count: number | null
|
||||
daily_generations_limit: number | null
|
||||
daily_reset_at: string | null
|
||||
hourly_generations_count: number | null
|
||||
hourly_generations_limit: number | null
|
||||
hourly_reset_at: string | null
|
||||
last_generation_at: string | null
|
||||
max_batch_size: number | null
|
||||
max_concurrent_generations: number | null
|
||||
total_generations_all_time: number | null
|
||||
updated_at: string | null
|
||||
user_id: string
|
||||
}
|
||||
Insert: {
|
||||
daily_generations_count?: number | null
|
||||
daily_generations_limit?: number | null
|
||||
daily_reset_at?: string | null
|
||||
hourly_generations_count?: number | null
|
||||
hourly_generations_limit?: number | null
|
||||
hourly_reset_at?: string | null
|
||||
last_generation_at?: string | null
|
||||
max_batch_size?: number | null
|
||||
max_concurrent_generations?: number | null
|
||||
total_generations_all_time?: number | null
|
||||
updated_at?: string | null
|
||||
user_id: string
|
||||
}
|
||||
Update: {
|
||||
daily_generations_count?: number | null
|
||||
daily_generations_limit?: number | null
|
||||
daily_reset_at?: string | null
|
||||
hourly_generations_count?: number | null
|
||||
hourly_generations_limit?: number | null
|
||||
hourly_reset_at?: string | null
|
||||
last_generation_at?: string | null
|
||||
max_batch_size?: number | null
|
||||
max_concurrent_generations?: number | null
|
||||
total_generations_all_time?: number | null
|
||||
updated_at?: string | null
|
||||
user_id?: string
|
||||
}
|
||||
Relationships: []
|
||||
}
|
||||
}
|
||||
Views: {
|
||||
batch_progress: {
|
||||
Row: {
|
||||
completed_count: number | null
|
||||
created_at: string | null
|
||||
failed_count: number | null
|
||||
id: string | null
|
||||
items: Json | null
|
||||
name: string | null
|
||||
pending_count: number | null
|
||||
processing_count: number | null
|
||||
status: string | null
|
||||
total_count: number | null
|
||||
user_id: string | null
|
||||
}
|
||||
Relationships: []
|
||||
}
|
||||
multi_generation_groups: {
|
||||
Row: {
|
||||
completed_at: string | null
|
||||
completed_count: number | null
|
||||
created_at: string | null
|
||||
failed_count: number | null
|
||||
images: Json[] | null
|
||||
model: string | null
|
||||
multi_group_id: string | null
|
||||
processing_count: number | null
|
||||
prompt: string | null
|
||||
total_count: number | null
|
||||
user_id: string | null
|
||||
}
|
||||
Relationships: [
|
||||
{
|
||||
foreignKeyName: "image_generations_user_id_fkey"
|
||||
columns: ["user_id"]
|
||||
isOneToOne: false
|
||||
referencedRelation: "profiles"
|
||||
referencedColumns: ["id"]
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
Functions: {
|
||||
check_rate_limit: {
|
||||
Args: { p_count?: number; p_user_id: string }
|
||||
Returns: Json
|
||||
}
|
||||
create_multi_generation: {
|
||||
Args: {
|
||||
p_count: number
|
||||
p_model: string
|
||||
p_prompt: string
|
||||
p_settings: Json
|
||||
p_user_id: string
|
||||
}
|
||||
Returns: string
|
||||
}
|
||||
get_error_statistics: {
|
||||
Args: { p_days?: number; p_user_id?: string }
|
||||
Returns: Json
|
||||
}
|
||||
get_user_limits: {
|
||||
Args: { p_user_id: string }
|
||||
Returns: Json
|
||||
}
|
||||
process_error_recovery: {
|
||||
Args: Record<PropertyKey, never>
|
||||
Returns: Json
|
||||
}
|
||||
recover_stale_generations: {
|
||||
Args: Record<PropertyKey, never>
|
||||
Returns: number
|
||||
}
|
||||
schedule_retry: {
|
||||
Args: {
|
||||
p_error_message: string
|
||||
p_error_type: string
|
||||
p_generation_id: string
|
||||
}
|
||||
Returns: Json
|
||||
}
|
||||
}
|
||||
Enums: {
|
||||
[_ in never]: never
|
||||
}
|
||||
CompositeTypes: {
|
||||
[_ in never]: never
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type DatabaseWithoutInternals = Omit<Database, "__InternalSupabase">
|
||||
|
||||
type DefaultSchema = DatabaseWithoutInternals[Extract<keyof Database, "public">]
|
||||
|
||||
export type Tables<
|
||||
DefaultSchemaTableNameOrOptions extends
|
||||
| keyof (DefaultSchema["Tables"] & DefaultSchema["Views"])
|
||||
| { schema: keyof DatabaseWithoutInternals },
|
||||
TableName extends DefaultSchemaTableNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? keyof (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] &
|
||||
DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])
|
||||
: never = never,
|
||||
> = DefaultSchemaTableNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? (DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"] &
|
||||
DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Views"])[TableName] extends {
|
||||
Row: infer R
|
||||
}
|
||||
? R
|
||||
: never
|
||||
: DefaultSchemaTableNameOrOptions extends keyof (DefaultSchema["Tables"] &
|
||||
DefaultSchema["Views"])
|
||||
? (DefaultSchema["Tables"] &
|
||||
DefaultSchema["Views"])[DefaultSchemaTableNameOrOptions] extends {
|
||||
Row: infer R
|
||||
}
|
||||
? R
|
||||
: never
|
||||
: never
|
||||
|
||||
export type TablesInsert<
|
||||
DefaultSchemaTableNameOrOptions extends
|
||||
| keyof DefaultSchema["Tables"]
|
||||
| { schema: keyof DatabaseWithoutInternals },
|
||||
TableName extends DefaultSchemaTableNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"]
|
||||
: never = never,
|
||||
> = DefaultSchemaTableNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends {
|
||||
Insert: infer I
|
||||
}
|
||||
? I
|
||||
: never
|
||||
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"]
|
||||
? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends {
|
||||
Insert: infer I
|
||||
}
|
||||
? I
|
||||
: never
|
||||
: never
|
||||
|
||||
export type TablesUpdate<
|
||||
DefaultSchemaTableNameOrOptions extends
|
||||
| keyof DefaultSchema["Tables"]
|
||||
| { schema: keyof DatabaseWithoutInternals },
|
||||
TableName extends DefaultSchemaTableNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? keyof DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"]
|
||||
: never = never,
|
||||
> = DefaultSchemaTableNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? DatabaseWithoutInternals[DefaultSchemaTableNameOrOptions["schema"]]["Tables"][TableName] extends {
|
||||
Update: infer U
|
||||
}
|
||||
? U
|
||||
: never
|
||||
: DefaultSchemaTableNameOrOptions extends keyof DefaultSchema["Tables"]
|
||||
? DefaultSchema["Tables"][DefaultSchemaTableNameOrOptions] extends {
|
||||
Update: infer U
|
||||
}
|
||||
? U
|
||||
: never
|
||||
: never
|
||||
|
||||
export type Enums<
|
||||
DefaultSchemaEnumNameOrOptions extends
|
||||
| keyof DefaultSchema["Enums"]
|
||||
| { schema: keyof DatabaseWithoutInternals },
|
||||
EnumName extends DefaultSchemaEnumNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? keyof DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"]
|
||||
: never = never,
|
||||
> = DefaultSchemaEnumNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? DatabaseWithoutInternals[DefaultSchemaEnumNameOrOptions["schema"]]["Enums"][EnumName]
|
||||
: DefaultSchemaEnumNameOrOptions extends keyof DefaultSchema["Enums"]
|
||||
? DefaultSchema["Enums"][DefaultSchemaEnumNameOrOptions]
|
||||
: never
|
||||
|
||||
export type CompositeTypes<
|
||||
PublicCompositeTypeNameOrOptions extends
|
||||
| keyof DefaultSchema["CompositeTypes"]
|
||||
| { schema: keyof DatabaseWithoutInternals },
|
||||
CompositeTypeName extends PublicCompositeTypeNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? keyof DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"]
|
||||
: never = never,
|
||||
> = PublicCompositeTypeNameOrOptions extends {
|
||||
schema: keyof DatabaseWithoutInternals
|
||||
}
|
||||
? DatabaseWithoutInternals[PublicCompositeTypeNameOrOptions["schema"]]["CompositeTypes"][CompositeTypeName]
|
||||
: PublicCompositeTypeNameOrOptions extends keyof DefaultSchema["CompositeTypes"]
|
||||
? DefaultSchema["CompositeTypes"][PublicCompositeTypeNameOrOptions]
|
||||
: never
|
||||
|
||||
export const Constants = {
|
||||
public: {
|
||||
Enums: {},
|
||||
},
|
||||
} as const
|
||||
1
apps/picture/packages/shared/src/types/index.ts
Normal file
1
apps/picture/packages/shared/src/types/index.ts
Normal file
|
|
@ -0,0 +1 @@
|
|||
export * from './database.types'
|
||||
2
apps/picture/packages/shared/src/utils/index.ts
Normal file
2
apps/picture/packages/shared/src/utils/index.ts
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
// Utility functions will be added here
|
||||
export {}
|
||||
Loading…
Add table
Add a link
Reference in a new issue