// Database types for Supabase tables
export interface Book {
id: string;
title: string;
description: string | null;
status: 'Planning' | 'Draft' | 'In Progress' | 'Completed' | 'Published';
word_count: number;
created_at: string;
updated_at: string;
user_id: string;
// Metadata
author: string | null;
cover_image_url: string | null;
genre: string | null;
target_word_count: number | null;
template_id: string | null;
// Settings (stored as JSONB)
settings: Record<string, any>;
}
export interface GeneratedImage {
id: string;
user_id: string;
book_id: string | null;
prompt: string;
revised_prompt: string | null;
image_url: string;
model: string;
size: string;
quality: string;
style: string;
cost_usd: number;
metadata: Record<string, any>;
created_at: string;
updated_at: string;
}
export interface BookTemplate {
id: string;
name: string;
description: string | null;
is_default: boolean;
is_system: boolean;
structure: TemplateStructure;
created_by: string | null;
created_at: string;
updated_at: string;
metadata: Record<string, any>;
}
export interface TemplateStructure {
files: TemplateFile[];
folders: TemplateFolder[];
}
export interface TemplateFile {
name: string;
type: 'file';
content: string;
file_extension: string;
mime_type: string;
sort_order: number;
}
export interface TemplateFolder {
name: string;
type: 'folder';
expanded: boolean;
sort_order: number;
children?: (TemplateFile | TemplateFolder)[];
}
export interface FileSystemItem {
id: string;
book_id: string;
parent_id: string | null;
// Basic properties
name: string;
type: 'file' | 'folder';
// File-specific properties
content: string | null;
file_extension: string | null;
mime_type: string | null;
file_size: number | null;
file_url: string | null;
// Folder-specific properties
expanded: boolean;
// Ordering and organization
sort_order: number;
// Timestamps
created_at: string;
updated_at: string;
// Metadata (stored as JSONB)
metadata: Record<string, any>;
}
// Extended interface for UI purposes (matches current FileItem interface)
export interface FileItem {
// Convert database IDs to numbers for compatibility with existing UI
id: number;
parent_id?: number | null;
// Basic properties
name: string;
type: 'file' | 'folder';
// File-specific properties
content?: string;
file_extension?: string | null;
mime_type?: string | null;
file_size?: number | null;
file_url?: string | null;
// Folder-specific properties
expanded?: boolean;
// Ordering and organization
sort_order?: number;
// For nested structure in UI
children?: FileItem[];
}
// For API requests
export interface CreateBookRequest {
title: string;
description?: string;
author?: string;
genre?: string;
genres?: string[];
target_word_count?: number;
template_id?: string;
}
export interface UpdateBookRequest {
title?: string;
description?: string;
author?: string;
status?: Book['status'];
genre?: string;
target_word_count?: number;
cover_image_url?: string;
settings?: Record<string, any>;
}
export interface CreateFileSystemItemRequest {
book_id: string;
parent_id?: string | null;
name: string;
type: 'file' | 'folder';
content?: string;
file_extension?: string;
mime_type?: string;
sort_order?: number;
}
export interface UpdateFileSystemItemRequest {
name?: string;
content?: string;
expanded?: boolean;
sort_order?: number;
parent_id?: string | null;
}
// Response types
export interface BookWithStats extends Book {
file_count?: number;
folder_count?: number;
last_modified_file?: string;
}
// For the file tree view
export interface FileTreeItem extends FileSystemItem {
depth: number;
path: number[];
children?: FileTreeItem[];
}
// Utility types for common operations
export type BookStatus = Book['status'];
export type FileType = FileSystemItem['type'];
// Common mime types for validation
export const SUPPORTED_MIME_TYPES = {
// Text files
'text/plain': ['.txt'],
'text/markdown': ['.md', '.markdown'],
'text/html': ['.html', '.htm'],
'application/json': ['.json'],
// Documents
'application/pdf': ['.pdf'],
'application/msword': ['.doc'],
'application/vnd.openxmlformats-officedocument.wordprocessingml.document': ['.docx'],
// Images
'image/jpeg': ['.jpg', '.jpeg'],
'image/png': ['.png'],
'image/gif': ['.gif'],
'image/svg+xml': ['.svg'],
'image/webp': ['.webp'],
// Audio
'audio/mpeg': ['.mp3'],
'audio/wav': ['.wav'],
'audio/ogg': ['.ogg'],
// Video
'video/mp4': ['.mp4'],
'video/webm': ['.webm'],
'video/ogg': ['.ogv'],
} as const;
// Helper function to get mime type from file extension
export function getMimeTypeFromExtension(extension: string): string | null {
const ext = extension.toLowerCase().startsWith('.') ? extension : `.${extension}`;
for (const [mimeType, extensions] of Object.entries(SUPPORTED_MIME_TYPES)) {
if ((extensions as readonly string[]).includes(ext)) {
return mimeType;
}
}
return null;
}
// Helper function to check if a file type is supported
export function isSupportedFileType(extension: string): boolean {
return getMimeTypeFromExtension(extension) !== null;
}
// Default file extensions for new files
export const DEFAULT_FILE_EXTENSIONS = {
markdown: 'md',
text: 'txt',
html: 'html',
json: 'json',
} as const;
// Chat-related interfaces
export interface Chat {
id: string;
book_id: string;
user_id: string;
title: string;
created_at: string;
updated_at: string;
// Chat metadata
model: string;
total_messages: number;
last_message_at: string;
}
export interface Message {
id: string;
chat_id: string;
type: 'user' | 'ai';
content: string;
created_at: string;
// Message ordering
sequence_number: number;
// Optional metadata for AI messages
model?: string | null;
tool_results?: Record<string, any> | null;
context_info?: Record<string, any> | null;
}
// UI-compatible message interface (for compatibility with existing code)
export interface MessageUI {
id: number | string;
type: 'user' | 'ai';
content: string;
timestamp?: Date;
// Optional metadata
model?: string;
tool_results?: Record<string, any>;
context_info?: Record<string, any>;
}