import type { CsoundProject, CreateProjectData, UpdateProjectData, Result } from './types'; import { projectDb } from './db'; import { compressProject, decompressProject, projectToShareUrl, projectFromShareUrl } from './compression'; const CSOUND_VERSION = '7.0.0'; // This should be detected from @csound/browser /** * Generate a unique ID for a project */ function generateId(): string { return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`; } /** * Get the current ISO timestamp */ function getCurrentTimestamp(): string { return new Date().toISOString(); } /** * Project Manager - Main API for managing Csound projects */ export class ProjectManager { /** * Initialize the project manager (initializes database) */ async init(): Promise { await projectDb.init(); } /** * Create a new project */ async createProject(data: CreateProjectData): Promise> { try { const now = getCurrentTimestamp(); const project: CsoundProject = { id: generateId(), title: data.title, author: data.author, dateCreated: now, dateModified: now, saveCount: 0, content: data.content || '', tags: data.tags || [], csoundVersion: CSOUND_VERSION, }; await projectDb.put(project); return { success: true, data: project }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to create project'), }; } } /** * Get a project by ID */ async getProject(id: string): Promise> { try { const project = await projectDb.get(id); if (!project) { return { success: false, error: new Error(`Project not found: ${id}`), }; } return { success: true, data: project }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to get project'), }; } } /** * Get all projects */ async getAllProjects(): Promise> { try { const projects = await projectDb.getAll(); return { success: true, data: projects }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to get projects'), }; } } /** * Update an existing project */ async updateProject(data: UpdateProjectData): Promise> { try { const existingProject = await projectDb.get(data.id); if (!existingProject) { return { success: false, error: new Error(`Project not found: ${data.id}`), }; } const updatedProject: CsoundProject = { ...existingProject, ...(data.title !== undefined && { title: data.title }), ...(data.author !== undefined && { author: data.author }), ...(data.content !== undefined && { content: data.content }), ...(data.tags !== undefined && { tags: data.tags }), dateModified: getCurrentTimestamp(), saveCount: existingProject.saveCount + 1, }; await projectDb.put(updatedProject); return { success: true, data: updatedProject }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to update project'), }; } } /** * Delete a project */ async deleteProject(id: string): Promise> { try { await projectDb.delete(id); return { success: true, data: undefined }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to delete project'), }; } } /** * Search projects by tag */ async getProjectsByTag(tag: string): Promise> { try { const projects = await projectDb.getByTag(tag); return { success: true, data: projects }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to search projects by tag'), }; } } /** * Search projects by author */ async getProjectsByAuthor(author: string): Promise> { try { const projects = await projectDb.getByAuthor(author); return { success: true, data: projects }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to search projects by author'), }; } } /** * Export a project to a shareable URL */ async exportProjectToUrl(id: string, baseUrl?: string): Promise> { try { const project = await projectDb.get(id); if (!project) { return { success: false, error: new Error(`Project not found: ${id}`), }; } const url = projectToShareUrl(project, baseUrl); return { success: true, data: url }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to export project'), }; } } /** * Export a project to compressed data (for copying to clipboard, etc.) */ async exportProjectToCompressed(id: string): Promise> { try { const project = await projectDb.get(id); if (!project) { return { success: false, error: new Error(`Project not found: ${id}`), }; } const compressed = compressProject(project); return { success: true, data: compressed.data }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to export project'), }; } } /** * Import a project from a URL */ async importProjectFromUrl(url: string): Promise> { try { const project = projectFromShareUrl(url); // Generate a new ID and reset timestamps const now = getCurrentTimestamp(); const importedProject: CsoundProject = { ...project, id: generateId(), dateCreated: now, dateModified: now, saveCount: 0, title: `${project.title} (imported)`, }; await projectDb.put(importedProject); return { success: true, data: importedProject }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to import project'), }; } } /** * Import a project from compressed data */ async importProjectFromCompressed(compressedData: string): Promise> { try { const project = decompressProject({ data: compressedData, version: 1, }); // Generate a new ID and reset timestamps const now = getCurrentTimestamp(); const importedProject: CsoundProject = { ...project, id: generateId(), dateCreated: now, dateModified: now, saveCount: 0, title: `${project.title} (imported)`, }; await projectDb.put(importedProject); return { success: true, data: importedProject }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to import project'), }; } } /** * Duplicate a project */ async duplicateProject(id: string): Promise> { try { const originalProject = await projectDb.get(id); if (!originalProject) { return { success: false, error: new Error(`Project not found: ${id}`), }; } const now = getCurrentTimestamp(); const duplicatedProject: CsoundProject = { ...originalProject, id: generateId(), title: `${originalProject.title} (copy)`, dateCreated: now, dateModified: now, saveCount: 0, }; await projectDb.put(duplicatedProject); return { success: true, data: duplicatedProject }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to duplicate project'), }; } } /** * Clear all projects (use with caution!) */ async clearAllProjects(): Promise> { try { await projectDb.clear(); return { success: true, data: undefined }; } catch (error) { return { success: false, error: error instanceof Error ? error : new Error('Failed to clear projects'), }; } } } // Export singleton instance export const projectManager = new ProjectManager();