refactor: migrate library repository to kysely (#15271)

This commit is contained in:
Daniel Dietzler 2025-01-15 22:01:28 +01:00 committed by GitHub
parent 81568dbda3
commit a2207f2eef
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 225 additions and 205 deletions

View File

@ -1,3 +1,5 @@
import { Insertable, Updateable } from 'kysely';
import { Libraries } from 'src/db';
import { LibraryStatsResponseDto } from 'src/dtos/library.dto'; import { LibraryStatsResponseDto } from 'src/dtos/library.dto';
import { LibraryEntity } from 'src/entities/library.entity'; import { LibraryEntity } from 'src/entities/library.entity';
@ -6,10 +8,10 @@ export const ILibraryRepository = 'ILibraryRepository';
export interface ILibraryRepository { export interface ILibraryRepository {
getAll(withDeleted?: boolean): Promise<LibraryEntity[]>; getAll(withDeleted?: boolean): Promise<LibraryEntity[]>;
getAllDeleted(): Promise<LibraryEntity[]>; getAllDeleted(): Promise<LibraryEntity[]>;
get(id: string, withDeleted?: boolean): Promise<LibraryEntity | null>; get(id: string, withDeleted?: boolean): Promise<LibraryEntity | undefined>;
create(library: Partial<LibraryEntity>): Promise<LibraryEntity>; create(library: Insertable<Libraries>): Promise<LibraryEntity>;
delete(id: string): Promise<void>; delete(id: string): Promise<void>;
softDelete(id: string): Promise<void>; softDelete(id: string): Promise<void>;
update(library: Partial<LibraryEntity>): Promise<LibraryEntity>; update(id: string, library: Updateable<Libraries>): Promise<LibraryEntity>;
getStatistics(id: string): Promise<LibraryStatsResponseDto | undefined>; getStatistics(id: string): Promise<LibraryStatsResponseDto | undefined>;
} }

View File

@ -1,150 +1,137 @@
-- NOTE: This file is auto generated by ./sql-generator -- NOTE: This file is auto generated by ./sql-generator
-- LibraryRepository.get -- LibraryRepository.get
SELECT DISTINCT select
"distinctAlias"."LibraryEntity_id" AS "ids_LibraryEntity_id" "libraries".*,
FROM
( (
SELECT select
"LibraryEntity"."id" AS "LibraryEntity_id", to_json(obj)
"LibraryEntity"."name" AS "LibraryEntity_name", from
"LibraryEntity"."ownerId" AS "LibraryEntity_ownerId", (
"LibraryEntity"."importPaths" AS "LibraryEntity_importPaths", select
"LibraryEntity"."exclusionPatterns" AS "LibraryEntity_exclusionPatterns", "users"."id",
"LibraryEntity"."createdAt" AS "LibraryEntity_createdAt", "users"."email",
"LibraryEntity"."updatedAt" AS "LibraryEntity_updatedAt", "users"."createdAt",
"LibraryEntity"."deletedAt" AS "LibraryEntity_deletedAt", "users"."profileImagePath",
"LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt", "users"."isAdmin",
"LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id", "users"."shouldChangePassword",
"LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name", "users"."deletedAt",
"LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin", "users"."oauthId",
"LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email", "users"."updatedAt",
"LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel", "users"."storageLabel",
"LibraryEntity__LibraryEntity_owner"."oauthId" AS "LibraryEntity__LibraryEntity_owner_oauthId", "users"."name",
"LibraryEntity__LibraryEntity_owner"."profileImagePath" AS "LibraryEntity__LibraryEntity_owner_profileImagePath", "users"."quotaSizeInBytes",
"LibraryEntity__LibraryEntity_owner"."shouldChangePassword" AS "LibraryEntity__LibraryEntity_owner_shouldChangePassword", "users"."quotaUsageInBytes",
"LibraryEntity__LibraryEntity_owner"."createdAt" AS "LibraryEntity__LibraryEntity_owner_createdAt", "users"."status",
"LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt", "users"."profileChangedAt"
"LibraryEntity__LibraryEntity_owner"."status" AS "LibraryEntity__LibraryEntity_owner_status", from
"LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt", "users"
"LibraryEntity__LibraryEntity_owner"."quotaSizeInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaSizeInBytes", where
"LibraryEntity__LibraryEntity_owner"."quotaUsageInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaUsageInBytes", "users"."id" = "libraries"."ownerId"
"LibraryEntity__LibraryEntity_owner"."profileChangedAt" AS "LibraryEntity__LibraryEntity_owner_profileChangedAt" ) as obj
FROM ) as "owner"
"libraries" "LibraryEntity" from
LEFT JOIN "users" "LibraryEntity__LibraryEntity_owner" ON "LibraryEntity__LibraryEntity_owner"."id" = "LibraryEntity"."ownerId" "libraries"
AND ( where
"LibraryEntity__LibraryEntity_owner"."deletedAt" IS NULL "libraries"."id" = $1
) and "libraries"."deletedAt" is null
WHERE
((("LibraryEntity"."id" = $1)))
AND ("LibraryEntity"."deletedAt" IS NULL)
) "distinctAlias"
ORDER BY
"LibraryEntity_id" ASC
LIMIT
1
-- LibraryRepository.getAll -- LibraryRepository.getAll
SELECT select
"LibraryEntity"."id" AS "LibraryEntity_id", "libraries".*,
"LibraryEntity"."name" AS "LibraryEntity_name", (
"LibraryEntity"."ownerId" AS "LibraryEntity_ownerId", select
"LibraryEntity"."importPaths" AS "LibraryEntity_importPaths", to_json(obj)
"LibraryEntity"."exclusionPatterns" AS "LibraryEntity_exclusionPatterns", from
"LibraryEntity"."createdAt" AS "LibraryEntity_createdAt", (
"LibraryEntity"."updatedAt" AS "LibraryEntity_updatedAt", select
"LibraryEntity"."deletedAt" AS "LibraryEntity_deletedAt", "users"."id",
"LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt", "users"."email",
"LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id", "users"."createdAt",
"LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name", "users"."profileImagePath",
"LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin", "users"."isAdmin",
"LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email", "users"."shouldChangePassword",
"LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel", "users"."deletedAt",
"LibraryEntity__LibraryEntity_owner"."oauthId" AS "LibraryEntity__LibraryEntity_owner_oauthId", "users"."oauthId",
"LibraryEntity__LibraryEntity_owner"."profileImagePath" AS "LibraryEntity__LibraryEntity_owner_profileImagePath", "users"."updatedAt",
"LibraryEntity__LibraryEntity_owner"."shouldChangePassword" AS "LibraryEntity__LibraryEntity_owner_shouldChangePassword", "users"."storageLabel",
"LibraryEntity__LibraryEntity_owner"."createdAt" AS "LibraryEntity__LibraryEntity_owner_createdAt", "users"."name",
"LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt", "users"."quotaSizeInBytes",
"LibraryEntity__LibraryEntity_owner"."status" AS "LibraryEntity__LibraryEntity_owner_status", "users"."quotaUsageInBytes",
"LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt", "users"."status",
"LibraryEntity__LibraryEntity_owner"."quotaSizeInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaSizeInBytes", "users"."profileChangedAt"
"LibraryEntity__LibraryEntity_owner"."quotaUsageInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaUsageInBytes", from
"LibraryEntity__LibraryEntity_owner"."profileChangedAt" AS "LibraryEntity__LibraryEntity_owner_profileChangedAt" "users"
FROM where
"libraries" "LibraryEntity" "users"."id" = "libraries"."ownerId"
LEFT JOIN "users" "LibraryEntity__LibraryEntity_owner" ON "LibraryEntity__LibraryEntity_owner"."id" = "LibraryEntity"."ownerId" ) as obj
AND ( ) as "owner"
"LibraryEntity__LibraryEntity_owner"."deletedAt" IS NULL from
) "libraries"
WHERE where
"LibraryEntity"."deletedAt" IS NULL "libraries"."deletedAt" is null
ORDER BY order by
"LibraryEntity"."createdAt" ASC "createdAt" asc
-- LibraryRepository.getAllDeleted -- LibraryRepository.getAllDeleted
SELECT select
"LibraryEntity"."id" AS "LibraryEntity_id", "libraries".*,
"LibraryEntity"."name" AS "LibraryEntity_name", (
"LibraryEntity"."ownerId" AS "LibraryEntity_ownerId", select
"LibraryEntity"."importPaths" AS "LibraryEntity_importPaths", to_json(obj)
"LibraryEntity"."exclusionPatterns" AS "LibraryEntity_exclusionPatterns", from
"LibraryEntity"."createdAt" AS "LibraryEntity_createdAt", (
"LibraryEntity"."updatedAt" AS "LibraryEntity_updatedAt", select
"LibraryEntity"."deletedAt" AS "LibraryEntity_deletedAt", "users"."id",
"LibraryEntity"."refreshedAt" AS "LibraryEntity_refreshedAt", "users"."email",
"LibraryEntity__LibraryEntity_owner"."id" AS "LibraryEntity__LibraryEntity_owner_id", "users"."createdAt",
"LibraryEntity__LibraryEntity_owner"."name" AS "LibraryEntity__LibraryEntity_owner_name", "users"."profileImagePath",
"LibraryEntity__LibraryEntity_owner"."isAdmin" AS "LibraryEntity__LibraryEntity_owner_isAdmin", "users"."isAdmin",
"LibraryEntity__LibraryEntity_owner"."email" AS "LibraryEntity__LibraryEntity_owner_email", "users"."shouldChangePassword",
"LibraryEntity__LibraryEntity_owner"."storageLabel" AS "LibraryEntity__LibraryEntity_owner_storageLabel", "users"."deletedAt",
"LibraryEntity__LibraryEntity_owner"."oauthId" AS "LibraryEntity__LibraryEntity_owner_oauthId", "users"."oauthId",
"LibraryEntity__LibraryEntity_owner"."profileImagePath" AS "LibraryEntity__LibraryEntity_owner_profileImagePath", "users"."updatedAt",
"LibraryEntity__LibraryEntity_owner"."shouldChangePassword" AS "LibraryEntity__LibraryEntity_owner_shouldChangePassword", "users"."storageLabel",
"LibraryEntity__LibraryEntity_owner"."createdAt" AS "LibraryEntity__LibraryEntity_owner_createdAt", "users"."name",
"LibraryEntity__LibraryEntity_owner"."deletedAt" AS "LibraryEntity__LibraryEntity_owner_deletedAt", "users"."quotaSizeInBytes",
"LibraryEntity__LibraryEntity_owner"."status" AS "LibraryEntity__LibraryEntity_owner_status", "users"."quotaUsageInBytes",
"LibraryEntity__LibraryEntity_owner"."updatedAt" AS "LibraryEntity__LibraryEntity_owner_updatedAt", "users"."status",
"LibraryEntity__LibraryEntity_owner"."quotaSizeInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaSizeInBytes", "users"."profileChangedAt"
"LibraryEntity__LibraryEntity_owner"."quotaUsageInBytes" AS "LibraryEntity__LibraryEntity_owner_quotaUsageInBytes", from
"LibraryEntity__LibraryEntity_owner"."profileChangedAt" AS "LibraryEntity__LibraryEntity_owner_profileChangedAt" "users"
FROM where
"libraries" "LibraryEntity" "users"."id" = "libraries"."ownerId"
LEFT JOIN "users" "LibraryEntity__LibraryEntity_owner" ON "LibraryEntity__LibraryEntity_owner"."id" = "LibraryEntity"."ownerId" ) as obj
WHERE ) as "owner"
((NOT ("LibraryEntity"."deletedAt" IS NULL))) from
ORDER BY "libraries"
"LibraryEntity"."createdAt" ASC where
"libraries"."deletedAt" is not null
order by
"createdAt" asc
-- LibraryRepository.getStatistics -- LibraryRepository.getStatistics
SELECT select
"libraries"."id" AS "libraries_id", count("assets"."id") filter (
"libraries"."name" AS "libraries_name", where
"libraries"."ownerId" AS "libraries_ownerId", (
"libraries"."importPaths" AS "libraries_importPaths", "assets"."type" = $1
"libraries"."exclusionPatterns" AS "libraries_exclusionPatterns", and "assets"."isVisible" = $2
"libraries"."createdAt" AS "libraries_createdAt", )
"libraries"."updatedAt" AS "libraries_updatedAt", ) as "photos",
"libraries"."deletedAt" AS "libraries_deletedAt", count(*) filter (
"libraries"."refreshedAt" AS "libraries_refreshedAt", where
COUNT("assets"."id") FILTER ( (
WHERE "assets"."type" = $3
"assets"."type" = 'IMAGE' and "assets"."isVisible" = $4
AND "assets"."isVisible" )
) AS "photos", ) as "videos",
COUNT("assets"."id") FILTER ( coalesce(sum("exif"."fileSizeInByte"), $5) as "usage"
WHERE from
"assets"."type" = 'VIDEO' "libraries"
AND "assets"."isVisible" inner join "assets" on "assets"."libraryId" = "libraries"."id"
) AS "videos", inner join "exif" on "exif"."assetId" = "assets"."id"
COALESCE(SUM("exif"."fileSizeInByte"), 0) AS "usage" where
FROM "libraries"."id" = $6
"libraries" "libraries" group by
LEFT JOIN "assets" "assets" ON "assets"."libraryId" = "libraries"."id"
AND ("assets"."deletedAt" IS NULL)
LEFT JOIN "exif" "exif" ON "exif"."assetId" = "assets"."id"
WHERE
("libraries"."id" = $1)
AND ("libraries"."deletedAt" IS NULL)
GROUP BY
"libraries"."id" "libraries"."id"

View File

@ -1,84 +1,122 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm'; import { ExpressionBuilder, Insertable, Kysely, Updateable } from 'kysely';
import { jsonObjectFrom } from 'kysely/helpers/postgres';
import { InjectKysely } from 'nestjs-kysely';
import { DB, Libraries } from 'src/db';
import { DummyValue, GenerateSql } from 'src/decorators'; import { DummyValue, GenerateSql } from 'src/decorators';
import { LibraryStatsResponseDto } from 'src/dtos/library.dto'; import { LibraryStatsResponseDto } from 'src/dtos/library.dto';
import { LibraryEntity } from 'src/entities/library.entity'; import { LibraryEntity } from 'src/entities/library.entity';
import { AssetType } from 'src/enum';
import { ILibraryRepository } from 'src/interfaces/library.interface'; import { ILibraryRepository } from 'src/interfaces/library.interface';
import { IsNull, Not } from 'typeorm';
import { Repository } from 'typeorm/repository/Repository.js'; const userColumns = [
'users.id',
'users.email',
'users.createdAt',
'users.profileImagePath',
'users.isAdmin',
'users.shouldChangePassword',
'users.deletedAt',
'users.oauthId',
'users.updatedAt',
'users.storageLabel',
'users.name',
'users.quotaSizeInBytes',
'users.quotaUsageInBytes',
'users.status',
'users.profileChangedAt',
] as const;
const withOwner = (eb: ExpressionBuilder<DB, 'libraries'>) => {
return jsonObjectFrom(eb.selectFrom('users').whereRef('users.id', '=', 'libraries.ownerId').select(userColumns)).as(
'owner',
);
};
@Injectable() @Injectable()
export class LibraryRepository implements ILibraryRepository { export class LibraryRepository implements ILibraryRepository {
constructor(@InjectRepository(LibraryEntity) private repository: Repository<LibraryEntity>) {} constructor(@InjectKysely() private db: Kysely<DB>) {}
@GenerateSql({ params: [DummyValue.UUID] }) @GenerateSql({ params: [DummyValue.UUID] })
get(id: string, withDeleted = false): Promise<LibraryEntity | null> { get(id: string, withDeleted = false): Promise<LibraryEntity | undefined> {
return this.repository.findOneOrFail({ return this.db
where: { .selectFrom('libraries')
id, .selectAll('libraries')
}, .select(withOwner)
relations: { owner: true }, .where('libraries.id', '=', id)
withDeleted, .$if(!withDeleted, (qb) => qb.where('libraries.deletedAt', 'is', null))
}); .executeTakeFirst() as Promise<LibraryEntity | undefined>;
} }
@GenerateSql({ params: [] }) @GenerateSql({ params: [] })
getAll(withDeleted = false): Promise<LibraryEntity[]> { getAll(withDeleted = false): Promise<LibraryEntity[]> {
return this.repository.find({ return this.db
relations: { .selectFrom('libraries')
owner: true, .selectAll('libraries')
}, .select(withOwner)
order: { .orderBy('createdAt', 'asc')
createdAt: 'ASC', .$if(!withDeleted, (qb) => qb.where('libraries.deletedAt', 'is', null))
}, .execute() as unknown as Promise<LibraryEntity[]>;
withDeleted,
});
} }
@GenerateSql() @GenerateSql()
getAllDeleted(): Promise<LibraryEntity[]> { getAllDeleted(): Promise<LibraryEntity[]> {
return this.repository.find({ return this.db
where: { .selectFrom('libraries')
deletedAt: Not(IsNull()), .selectAll('libraries')
}, .select(withOwner)
relations: { .where('libraries.deletedAt', 'is not', null)
owner: true, .orderBy('createdAt', 'asc')
}, .execute() as unknown as Promise<LibraryEntity[]>;
order: {
createdAt: 'ASC',
},
withDeleted: true,
});
} }
create(library: Omit<LibraryEntity, 'id' | 'createdAt' | 'updatedAt' | 'ownerId'>): Promise<LibraryEntity> { create(library: Insertable<Libraries>): Promise<LibraryEntity> {
return this.repository.save(library); return this.db
.insertInto('libraries')
.values(library)
.returningAll()
.executeTakeFirstOrThrow() as Promise<LibraryEntity>;
} }
async delete(id: string): Promise<void> { async delete(id: string): Promise<void> {
await this.repository.delete({ id }); await this.db.deleteFrom('libraries').where('libraries.id', '=', id).execute();
} }
async softDelete(id: string): Promise<void> { async softDelete(id: string): Promise<void> {
await this.repository.softDelete({ id }); await this.db.updateTable('libraries').set({ deletedAt: new Date() }).where('libraries.id', '=', id).execute();
} }
async update(library: Partial<LibraryEntity>): Promise<LibraryEntity> { update(id: string, library: Updateable<Libraries>): Promise<LibraryEntity> {
return this.save(library); return this.db
.updateTable('libraries')
.set(library)
.where('libraries.id', '=', id)
.returningAll()
.executeTakeFirstOrThrow() as Promise<LibraryEntity>;
} }
@GenerateSql({ params: [DummyValue.UUID] }) @GenerateSql({ params: [DummyValue.UUID] })
async getStatistics(id: string): Promise<LibraryStatsResponseDto | undefined> { async getStatistics(id: string): Promise<LibraryStatsResponseDto | undefined> {
const stats = await this.repository const stats = await this.db
.createQueryBuilder('libraries') .selectFrom('libraries')
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'IMAGE' AND assets.isVisible)`, 'photos') .innerJoin('assets', 'assets.libraryId', 'libraries.id')
.addSelect(`COUNT(assets.id) FILTER (WHERE assets.type = 'VIDEO' AND assets.isVisible)`, 'videos') .innerJoin('exif', 'exif.assetId', 'assets.id')
.addSelect('COALESCE(SUM(exif.fileSizeInByte), 0)', 'usage') .select((eb) =>
.leftJoin('libraries.assets', 'assets') eb.fn
.leftJoin('assets.exifInfo', 'exif') .count('assets.id')
.filterWhere((eb) => eb.and([eb('assets.type', '=', AssetType.IMAGE), eb('assets.isVisible', '=', true)]))
.as('photos'),
)
.select((eb) =>
eb.fn
.countAll()
.filterWhere((eb) => eb.and([eb('assets.type', '=', AssetType.VIDEO), eb('assets.isVisible', '=', true)]))
.as('videos'),
)
.select((eb) => eb.fn.coalesce((eb) => eb.fn.sum('exif.fileSizeInByte'), eb.val(0)).as('usage'))
.groupBy('libraries.id') .groupBy('libraries.id')
.where('libraries.id = :id', { id }) .where('libraries.id', '=', id)
.getRawOne(); .executeTakeFirst();
if (!stats) { if (!stats) {
return; return;
@ -91,9 +129,4 @@ export class LibraryRepository implements ILibraryRepository {
total: Number(stats.photos) + Number(stats.videos), 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 });
}
} }

View File

@ -87,7 +87,7 @@ describe(LibraryService.name, () => {
Promise.resolve( Promise.resolve(
[libraryStub.externalLibraryWithImportPaths1, libraryStub.externalLibraryWithImportPaths2].find( [libraryStub.externalLibraryWithImportPaths1, libraryStub.externalLibraryWithImportPaths2].find(
(library) => library.id === id, (library) => library.id === id,
) || null, ),
), ),
); );
@ -190,8 +190,6 @@ describe(LibraryService.name, () => {
}); });
it("should fail when library can't be found", async () => { it("should fail when library can't be found", async () => {
libraryMock.get.mockResolvedValue(null);
await expect(sut.handleQueueSyncFiles({ id: libraryStub.externalLibrary1.id })).resolves.toBe(JobStatus.SKIPPED); await expect(sut.handleQueueSyncFiles({ id: libraryStub.externalLibrary1.id })).resolves.toBe(JobStatus.SKIPPED);
}); });
@ -242,8 +240,6 @@ describe(LibraryService.name, () => {
}); });
it("should fail when library can't be found", async () => { it("should fail when library can't be found", async () => {
libraryMock.get.mockResolvedValue(null);
await expect(sut.handleQueueSyncAssets({ id: libraryStub.externalLibrary1.id })).resolves.toBe(JobStatus.SKIPPED); await expect(sut.handleQueueSyncAssets({ id: libraryStub.externalLibrary1.id })).resolves.toBe(JobStatus.SKIPPED);
}); });
}); });
@ -630,7 +626,6 @@ describe(LibraryService.name, () => {
}); });
it('should throw an error when a library is not found', async () => { it('should throw an error when a library is not found', async () => {
libraryMock.get.mockResolvedValue(null);
await expect(sut.get(libraryStub.externalLibrary1.id)).rejects.toBeInstanceOf(BadRequestException); await expect(sut.get(libraryStub.externalLibrary1.id)).rejects.toBeInstanceOf(BadRequestException);
expect(libraryMock.get).toHaveBeenCalledWith(libraryStub.externalLibrary1.id); expect(libraryMock.get).toHaveBeenCalledWith(libraryStub.externalLibrary1.id);
}); });
@ -825,7 +820,10 @@ describe(LibraryService.name, () => {
await expect(sut.update('library-id', { importPaths: [`${cwd}/foo/bar`] })).resolves.toEqual( await expect(sut.update('library-id', { importPaths: [`${cwd}/foo/bar`] })).resolves.toEqual(
mapLibrary(libraryStub.externalLibrary1), mapLibrary(libraryStub.externalLibrary1),
); );
expect(libraryMock.update).toHaveBeenCalledWith(expect.objectContaining({ id: 'library-id' })); expect(libraryMock.update).toHaveBeenCalledWith(
'library-id',
expect.objectContaining({ importPaths: [`${cwd}/foo/bar`] }),
);
}); });
}); });
@ -1015,7 +1013,7 @@ describe(LibraryService.name, () => {
Promise.resolve( Promise.resolve(
[libraryStub.externalLibraryWithImportPaths1, libraryStub.externalLibraryWithImportPaths2].find( [libraryStub.externalLibraryWithImportPaths1, libraryStub.externalLibraryWithImportPaths2].find(
(library) => library.id === id, (library) => library.id === id,
) || null, ),
), ),
); );

View File

@ -311,7 +311,7 @@ export class LibraryService extends BaseService {
} }
} }
const library = await this.libraryRepository.update({ id, ...dto }); const library = await this.libraryRepository.update(id, dto);
return mapLibrary(library); return mapLibrary(library);
} }
@ -571,7 +571,7 @@ export class LibraryService extends BaseService {
this.logger.debug(`No non-excluded assets found in any import path for library ${library.id}`); this.logger.debug(`No non-excluded assets found in any import path for library ${library.id}`);
} }
await this.libraryRepository.update({ id: job.id, refreshedAt: new Date() }); await this.libraryRepository.update(job.id, { refreshedAt: new Date() });
return JobStatus.SUCCESS; return JobStatus.SUCCESS;
} }