mirror of
https://github.com/immich-app/immich.git
synced 2025-12-29 09:14:59 +03:00
* add job to check for offline files * fix lint * only check for offline when using checkForOffline * improve tests * remove old test * wip * remove trie * refactor batches * also check offline status * fix spelling * don't do offline scan * rename scan to check * fix job statuses * fix lint * cleanup * add test * open-api * fix test * fix spinner * reset text * don't double batch * fix comments from mert * remove tries * fix tests * fix e2e * fix test * fix test * add tests * fix lint * fix e2e * interweave scans * fix errors * fix messages * fix test * add mock * fix sql * fix e2e * use library batch size * save -> update * add file extensions * update specs * test for import paths * check import paths when testing offline * fix lint * normalize import path * remove console logs * decrease batch size to 1000 * add test for import path * add test for already-online assets * fix merge * fix lint * add library job back * add offline job to correct queue * library spec compiles now * move one test to new e2e * fix comments * fix comments * fix lint * refactor path validation * fix loop bug * remove logging * expect responses * fix asset mock * take the straightforward approach * use generator correctly * fix vitest on file edit * bump vitest to 1.6.0 * test for offline check * add e2e tests for offlining assets depending on import path * cleanup e2e test after finish * cleanup library service * paginate the walk generator * fix tests * fix typo * refactoring handleOfflineCheck * better testing of handleOfflineCheck * fix lint * handle large library deletions * dont check if library is deleted * fix mock * add a 100k page size to library * fix loading animation * better log messages * Better logging for offline asset removal * fix sql and tests * fix number format * Remove submodule * fix format * chore: cleanup * chore: fix tests --------- Co-authored-by: Alex <alex.tran1502@gmail.com> Co-authored-by: Jason Rasmussen <jason@rasm.me>
102 lines
3.0 KiB
TypeScript
102 lines
3.0 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
|
import { LibraryStatsResponseDto } from 'src/dtos/library.dto';
|
|
import { LibraryEntity } from 'src/entities/library.entity';
|
|
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
|
import { Instrumentation } from 'src/utils/instrumentation';
|
|
import { IsNull, Not } from 'typeorm';
|
|
import { Repository } from 'typeorm/repository/Repository.js';
|
|
|
|
@Instrumentation()
|
|
@Injectable()
|
|
export class LibraryRepository implements ILibraryRepository {
|
|
constructor(@InjectRepository(LibraryEntity) private repository: Repository<LibraryEntity>) {}
|
|
|
|
@GenerateSql({ params: [DummyValue.UUID] })
|
|
get(id: string, withDeleted = false): Promise<LibraryEntity | null> {
|
|
return this.repository.findOneOrFail({
|
|
where: {
|
|
id,
|
|
},
|
|
relations: { owner: true },
|
|
withDeleted,
|
|
});
|
|
}
|
|
|
|
@GenerateSql({ params: [] })
|
|
getAll(withDeleted = false): Promise<LibraryEntity[]> {
|
|
return this.repository.find({
|
|
relations: {
|
|
owner: true,
|
|
},
|
|
order: {
|
|
createdAt: 'ASC',
|
|
},
|
|
withDeleted,
|
|
});
|
|
}
|
|
|
|
@GenerateSql()
|
|
getAllDeleted(): Promise<LibraryEntity[]> {
|
|
return this.repository.find({
|
|
where: {
|
|
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);
|
|
}
|
|
|
|
@GenerateSql({ params: [DummyValue.UUID] })
|
|
async getStatistics(id: string): Promise<LibraryStatsResponseDto | undefined> {
|
|
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();
|
|
|
|
if (!stats) {
|
|
return;
|
|
}
|
|
|
|
return {
|
|
photos: Number(stats.photos),
|
|
videos: Number(stats.videos),
|
|
usage: Number(stats.usage),
|
|
total: Number(stats.photos) + Number(stats.videos),
|
|
};
|
|
}
|
|
|
|
private async save(library: Partial<LibraryEntity>) {
|
|
const { id } = await this.repository.save(library);
|
|
return this.repository.findOneByOrFail({ id });
|
|
}
|
|
}
|