import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { AssetEntity } from 'src/entities/asset.entity'; import { StackEntity } from 'src/entities/stack.entity'; import { IStackRepository, StackSearch } from 'src/interfaces/stack.interface'; import { DataSource, In, Repository } from 'typeorm'; @Injectable() export class StackRepository implements IStackRepository { constructor( @InjectDataSource() private dataSource: DataSource, @InjectRepository(StackEntity) private repository: Repository, ) {} @GenerateSql({ params: [{ ownerId: DummyValue.UUID }] }) search(query: StackSearch): Promise { return this.repository.find({ where: { ownerId: query.ownerId, primaryAssetId: query.primaryAssetId, }, relations: { assets: { exifInfo: true, }, }, }); } async create(entity: { ownerId: string; assetIds: string[] }): Promise { return this.dataSource.manager.transaction(async (manager) => { const stackRepository = manager.getRepository(StackEntity); const stacks = await stackRepository.find({ where: { ownerId: entity.ownerId, primaryAssetId: In(entity.assetIds), }, select: { id: true, assets: { id: true, }, }, relations: { assets: { exifInfo: true, }, }, }); const assetIds = new Set(entity.assetIds); // children for (const stack of stacks) { for (const asset of stack.assets) { assetIds.add(asset.id); } } if (stacks.length > 0) { await stackRepository.delete({ id: In(stacks.map((stack) => stack.id)) }); } const { id } = await stackRepository.save({ ownerId: entity.ownerId, primaryAssetId: entity.assetIds[0], assets: [...assetIds].map((id) => ({ id }) as AssetEntity), }); return stackRepository.findOneOrFail({ where: { id, }, relations: { assets: { exifInfo: true, }, }, }); }); } @GenerateSql({ params: [DummyValue.UUID] }) async delete(id: string): Promise { const stack = await this.getById(id); if (!stack) { return; } const assetIds = stack.assets.map(({ id }) => id); await this.repository.delete(id); // Update assets updatedAt await this.dataSource.manager.update(AssetEntity, assetIds, { updatedAt: new Date(), }); } async deleteAll(ids: string[]): Promise { const assetIds = []; for (const id of ids) { const stack = await this.getById(id); if (!stack) { continue; } assetIds.push(...stack.assets.map(({ id }) => id)); } await this.repository.delete(ids); // Update assets updatedAt await this.dataSource.manager.update(AssetEntity, assetIds, { updatedAt: new Date(), }); } update(entity: Partial) { return this.save(entity); } @GenerateSql({ params: [DummyValue.UUID] }) async getById(id: string): Promise { return this.repository.findOne({ where: { id, }, relations: { assets: { exifInfo: true, tags: true, }, }, order: { assets: { fileCreatedAt: 'ASC', }, }, }); } private async save(entity: Partial) { const { id } = await this.repository.save(entity); return this.repository.findOneOrFail({ where: { id, }, relations: { assets: { exifInfo: true, }, }, order: { assets: { fileCreatedAt: 'ASC', }, }, }); } }