Files
immich/server/src/infra/repositories/library.repository.ts
T
Jonathan Jogenfors acdc66413c feat(server,web): libraries (#3124)
* feat: libraries

Co-authored-by: Jason Rasmussen <jrasm91@gmail.com>
Co-authored-by: Alex <alex.tran1502@gmail.com>
2023-09-20 13:16:33 +02:00

184 lines
4.8 KiB
TypeScript

import { ILibraryRepository, LibraryStatsResponseDto } from '@app/domain';
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { IsNull, Not } from 'typeorm';
import { Repository } from 'typeorm/repository/Repository';
import { LibraryEntity, LibraryType } from '../entities';
@Injectable()
export class LibraryRepository implements ILibraryRepository {
constructor(@InjectRepository(LibraryEntity) private repository: Repository<LibraryEntity>) {}
get(id: string, withDeleted = false): Promise<LibraryEntity | null> {
return this.repository.findOneOrFail({
where: {
id,
},
relations: { owner: true },
withDeleted,
});
}
existsByName(name: string, withDeleted = false): Promise<boolean> {
return this.repository.exist({
where: {
name,
},
withDeleted,
});
}
getCountForUser(ownerId: string): Promise<number> {
return this.repository.countBy({ ownerId });
}
getDefaultUploadLibrary(ownerId: string): Promise<LibraryEntity | null> {
return this.repository.findOne({
where: {
ownerId: ownerId,
type: LibraryType.UPLOAD,
},
order: {
createdAt: 'ASC',
},
});
}
getUploadLibraryCount(ownerId: string): Promise<number> {
return this.repository.count({
where: {
ownerId: ownerId,
type: LibraryType.UPLOAD,
},
});
}
getAllByUserId(ownerId: string, type?: LibraryType): Promise<LibraryEntity[]> {
return this.repository.find({
where: {
ownerId,
isVisible: true,
type,
},
relations: {
owner: true,
},
order: {
createdAt: 'ASC',
},
});
}
getAll(withDeleted = false, type?: LibraryType): Promise<LibraryEntity[]> {
return this.repository.find({
where: { type },
relations: {
owner: true,
},
order: {
createdAt: 'ASC',
},
withDeleted,
});
}
getAllDeleted(): Promise<LibraryEntity[]> {
return this.repository.find({
where: {
isVisible: true,
deletedAt: Not(IsNull()),
},
relations: {
owner: true,
},
order: {
createdAt: 'ASC',
},
withDeleted: true,
});
}
create(library: Omit<LibraryEntity, 'id' | 'createdAt' | 'updatedAt' | 'ownerId'>): Promise<LibraryEntity> {
return this.repository.save(library);
}
async delete(id: string): Promise<void> {
await this.repository.delete({ id });
}
async softDelete(id: string): Promise<void> {
await this.repository.softDelete({ id });
}
async update(library: Partial<LibraryEntity>): Promise<LibraryEntity> {
return this.save(library);
}
async getStatistics(id: string): Promise<LibraryStatsResponseDto> {
const stats = await this.repository
.createQueryBuilder('libraries')
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'IMAGE' AND assets.isVisible)`, 'photos')
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'VIDEO' AND assets.isVisible)`, 'videos')
.addSelect('COALESCE(SUM(exif.fileSizeInByte), 0)', 'usage')
.leftJoin('libraries.assets', 'assets')
.leftJoin('assets.exifInfo', 'exif')
.groupBy('libraries.id')
.where('libraries.id = :id', { id })
.getRawOne();
return {
photos: Number(stats.photos),
videos: Number(stats.videos),
usage: Number(stats.usage),
total: Number(stats.photos) + Number(stats.videos),
};
}
async getOnlineAssetPaths(libraryId: string): Promise<string[]> {
// Return all non-offline asset paths for a given library
const rawResults = await this.repository
.createQueryBuilder('library')
.innerJoinAndSelect('library.assets', 'assets')
.where('library.id = :id', { id: libraryId })
.andWhere('assets.isOffline = false')
.select('assets.originalPath')
.getRawMany();
const results: string[] = [];
for (const rawPath of rawResults) {
results.push(rawPath.assets_originalPath);
}
return results;
}
async getAssetIds(libraryId: string, withDeleted = false): Promise<string[]> {
let query = await this.repository
.createQueryBuilder('library')
.innerJoinAndSelect('library.assets', 'assets')
.where('library.id = :id', { id: libraryId })
.select('assets.id');
if (withDeleted) {
query = query.withDeleted();
}
// Return all asset paths for a given library
const rawResults = await query.getRawMany();
const results: string[] = [];
for (const rawPath of rawResults) {
results.push(rawPath.assets_id);
}
return results;
}
private async save(library: Partial<LibraryEntity>) {
const { id } = await this.repository.save(library);
return this.repository.findOneByOrFail({ id });
}
}