164 lines
3.9 KiB
TypeScript
164 lines
3.9 KiB
TypeScript
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<StackEntity>,
|
|
) {}
|
|
|
|
@GenerateSql({ params: [{ ownerId: DummyValue.UUID }] })
|
|
search(query: StackSearch): Promise<StackEntity[]> {
|
|
return this.repository.find({
|
|
where: {
|
|
ownerId: query.ownerId,
|
|
primaryAssetId: query.primaryAssetId,
|
|
},
|
|
relations: {
|
|
assets: {
|
|
exifInfo: true,
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
async create(entity: { ownerId: string; assetIds: string[] }): Promise<StackEntity> {
|
|
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<string>(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<void> {
|
|
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<void> {
|
|
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<StackEntity>) {
|
|
return this.save(entity);
|
|
}
|
|
|
|
@GenerateSql({ params: [DummyValue.UUID] })
|
|
async getById(id: string): Promise<StackEntity | null> {
|
|
return this.repository.findOne({
|
|
where: {
|
|
id,
|
|
},
|
|
relations: {
|
|
assets: {
|
|
exifInfo: true,
|
|
tags: true,
|
|
},
|
|
},
|
|
order: {
|
|
assets: {
|
|
fileCreatedAt: 'ASC',
|
|
},
|
|
},
|
|
});
|
|
}
|
|
|
|
private async save(entity: Partial<StackEntity>) {
|
|
const { id } = await this.repository.save(entity);
|
|
return this.repository.findOneOrFail({
|
|
where: {
|
|
id,
|
|
},
|
|
relations: {
|
|
assets: {
|
|
exifInfo: true,
|
|
},
|
|
},
|
|
order: {
|
|
assets: {
|
|
fileCreatedAt: 'ASC',
|
|
},
|
|
},
|
|
});
|
|
}
|
|
}
|