All files / src/entities/project/model project.service.ts

58.62% Statements 17/29
100% Branches 10/10
33.33% Functions 3/9
53.84% Lines 14/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98                25x   2x               10x 10x   9x 9x   8x                 8x 8x             3x   3x         3x 3x 2x                                                                                              
import { nanoid } from 'nanoid';
import { db } from '@/shared/lib/db';
import type { Project } from '@/shared/types';
import { layerRepository } from '@/entities/layer/api';
import { historyRepository } from '@/entities/history/api';
import { projectRepository } from '@/entities/project/api';
import { PROJECT_MESSAGES, REPOSITORY_FIELDS } from '@/shared/constants';
 
export const projectService = {
	async getProjects(): Promise<Project[]> {
		return projectRepository.getAll();
	},
 
	async createProject(data: {
		name: string;
		width?: number;
		height?: number;
	}): Promise<Project> {
		const name = data.name.trim();
		if (!name) throw new Error(PROJECT_MESSAGES.NAME_EMPTY);
 
		const exists = await projectRepository.findByName(name);
		if (exists) throw new Error(PROJECT_MESSAGES.NAME_DUPLICATE);
 
		const newProject: Project = {
			id: nanoid(),
			name,
			width: data.width ?? 800,
			height: data.height ?? 600,
			createdAt: Date.now(),
			updatedAt: Date.now(),
		};
 
		await projectRepository.add(newProject);
		return newProject;
	},
 
	async updateProject(args: {
		id: string;
		changes: Partial<Project>;
	}): Promise<Project> {
		const { id, changes } = args;
 
		await projectRepository.update(id, {
			...changes,
			updatedAt: Date.now(),
		});
 
		const updated = await projectRepository.getById(id);
		if (!updated) throw new Error(PROJECT_MESSAGES.NOT_FOUND_AFTER_UPDATE);
		return updated;
	},
 
	/**
	 * Complete project deletion with all dependencies.
	 */
	async deleteWithRelations(projectId: string): Promise<string> {
		await db.transaction(
			'rw',
			db.projects,
			db.layers,
			db.viewStates,
			db.history,
			async () => {
				await projectRepository.remove(projectId);
 
				await layerRepository.removeByProject(projectId);
 
				await db.viewStates
					.where(REPOSITORY_FIELDS.PROJECT_ID)
					.equals(projectId)
					.delete();
 
				await historyRepository.clearByProject(projectId);
			},
		);
 
		return projectId;
	},
	async clearAll(): Promise<void> {
		const projects = await projectRepository.getAll();
		for (const project of projects) {
			await this.deleteWithRelations(project.id);
		}
	},
	async getById(id: string): Promise<Project | undefined> {
		return projectRepository.getById(id);
	},
 
	async exists(id: string): Promise<boolean> {
		return projectRepository.exists(id);
	},
 
	async findByName(name: string): Promise<Project | undefined> {
		return projectRepository.findByName(name);
	},
};