From 2daed747cd62a0ec86dac8a71e070d31b1a95686 Mon Sep 17 00:00:00 2001 From: Mert <101130780+mertalev@users.noreply.github.com> Date: Tue, 19 Mar 2024 22:42:10 -0400 Subject: [PATCH 001/152] chore(server): change `save` -> `update` in asset repository (#8055) * `save` -> `update` * change return type * include relations * fix tests * remove when mocks * fix * stricter typing * simpler type --- server/src/domain/asset/asset.service.spec.ts | 8 +-- server/src/domain/asset/asset.service.ts | 14 ++++- server/src/domain/audit/audit.service.ts | 10 ++-- .../domain/library/library.service.spec.ts | 8 +-- server/src/domain/library/library.service.ts | 6 +- server/src/domain/media/media.service.spec.ts | 20 +++---- server/src/domain/media/media.service.ts | 10 ++-- .../domain/metadata/metadata.service.spec.ts | 60 +++++++++---------- .../src/domain/metadata/metadata.service.ts | 14 ++--- .../domain/repositories/asset.repository.ts | 23 ++++++- .../storage-template.service.spec.ts | 60 +++++-------------- server/src/domain/storage/storage.core.ts | 10 ++-- .../infra/repositories/asset.repository.ts | 21 ++----- .../repositories/asset.repository.mock.ts | 2 +- 14 files changed, 128 insertions(+), 138 deletions(-) diff --git a/server/src/domain/asset/asset.service.spec.ts b/server/src/domain/asset/asset.service.spec.ts index 361946f61..11d2ed00b 100644 --- a/server/src/domain/asset/asset.service.spec.ts +++ b/server/src/domain/asset/asset.service.spec.ts @@ -548,19 +548,19 @@ describe(AssetService.name, () => { await expect(sut.update(authStub.admin, 'asset-1', { isArchived: false })).rejects.toBeInstanceOf( BadRequestException, ); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should update the asset', async () => { accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1'])); - assetMock.save.mockResolvedValue(assetStub.image); + assetMock.getById.mockResolvedValue(assetStub.image); await sut.update(authStub.admin, 'asset-1', { isFavorite: true }); - expect(assetMock.save).toHaveBeenCalledWith({ id: 'asset-1', isFavorite: true }); + expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-1', isFavorite: true }); }); it('should update the exif description', async () => { accessMock.asset.checkOwnerAccess.mockResolvedValue(new Set(['asset-1'])); - assetMock.save.mockResolvedValue(assetStub.image); + assetMock.getById.mockResolvedValue(assetStub.image); await sut.update(authStub.admin, 'asset-1', { description: 'Test description' }); expect(assetMock.upsertExif).toHaveBeenCalledWith({ assetId: 'asset-1', description: 'Test description' }); }); diff --git a/server/src/domain/asset/asset.service.ts b/server/src/domain/asset/asset.service.ts index e54eb8439..fbe4e91bd 100644 --- a/server/src/domain/asset/asset.service.ts +++ b/server/src/domain/asset/asset.service.ts @@ -324,7 +324,19 @@ export class AssetService { const { description, dateTimeOriginal, latitude, longitude, ...rest } = dto; await this.updateMetadata({ id, description, dateTimeOriginal, latitude, longitude }); - const asset = await this.assetRepository.save({ id, ...rest }); + await this.assetRepository.update({ id, ...rest }); + const asset = await this.assetRepository.getById(id, { + exifInfo: true, + owner: true, + smartInfo: true, + tags: true, + faces: { + person: true, + }, + }); + if (!asset) { + throw new BadRequestException('Asset not found'); + } return mapAsset(asset, { auth }); } diff --git a/server/src/domain/audit/audit.service.ts b/server/src/domain/audit/audit.service.ts index 91ebd78ee..c96f36d74 100644 --- a/server/src/domain/audit/audit.service.ts +++ b/server/src/domain/audit/audit.service.ts @@ -93,27 +93,27 @@ export class AuditService { switch (pathType) { case AssetPathType.ENCODED_VIDEO: { - await this.assetRepository.save({ id, encodedVideoPath: pathValue }); + await this.assetRepository.update({ id, encodedVideoPath: pathValue }); break; } case AssetPathType.JPEG_THUMBNAIL: { - await this.assetRepository.save({ id, resizePath: pathValue }); + await this.assetRepository.update({ id, resizePath: pathValue }); break; } case AssetPathType.WEBP_THUMBNAIL: { - await this.assetRepository.save({ id, webpPath: pathValue }); + await this.assetRepository.update({ id, webpPath: pathValue }); break; } case AssetPathType.ORIGINAL: { - await this.assetRepository.save({ id, originalPath: pathValue }); + await this.assetRepository.update({ id, originalPath: pathValue }); break; } case AssetPathType.SIDECAR: { - await this.assetRepository.save({ id, sidecarPath: pathValue }); + await this.assetRepository.update({ id, sidecarPath: pathValue }); break; } diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/domain/library/library.service.spec.ts index 3b5258b97..0c0daa165 100644 --- a/server/src/domain/library/library.service.spec.ts +++ b/server/src/domain/library/library.service.spec.ts @@ -584,7 +584,7 @@ describe(LibraryService.name, () => { await expect(sut.handleAssetRefresh(mockLibraryJob)).resolves.toBe(JobStatus.SUCCESS); - expect(assetMock.save).toHaveBeenCalledWith({ id: assetStub.image.id, isOffline: true }); + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, isOffline: true }); expect(jobMock.queue).not.toHaveBeenCalled(); expect(jobMock.queueAll).not.toHaveBeenCalled(); }); @@ -602,7 +602,7 @@ describe(LibraryService.name, () => { await expect(sut.handleAssetRefresh(mockLibraryJob)).resolves.toBe(JobStatus.SUCCESS); - expect(assetMock.save).toHaveBeenCalledWith({ id: assetStub.offline.id, isOffline: false }); + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.offline.id, isOffline: false }); expect(jobMock.queue).toHaveBeenCalledWith({ name: JobName.METADATA_EXTRACTION, @@ -631,7 +631,7 @@ describe(LibraryService.name, () => { assetMock.getByLibraryIdAndOriginalPath.mockResolvedValue(assetStub.image); assetMock.create.mockResolvedValue(assetStub.image); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); await expect(sut.handleAssetRefresh(mockLibraryJob)).resolves.toBe(JobStatus.SUCCESS); }); @@ -1257,7 +1257,7 @@ describe(LibraryService.name, () => { await sut.watchAll(); - expect(assetMock.save).toHaveBeenCalledWith({ id: assetStub.external.id, isOffline: true }); + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.external.id, isOffline: true }); }); it('should handle an error event', async () => { diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts index 000acac29..3ef59c919 100644 --- a/server/src/domain/library/library.service.ts +++ b/server/src/domain/library/library.service.ts @@ -173,7 +173,7 @@ export class LibraryService extends EventEmitter { this.logger.debug(`Detected deleted file at ${path} in library ${library.id}`); const asset = await this.assetRepository.getByLibraryIdAndOriginalPath(library.id, path); if (asset && matcher(path)) { - await this.assetRepository.save({ id: asset.id, isOffline: true }); + await this.assetRepository.update({ id: asset.id, isOffline: true }); } this.emit(StorageEventType.UNLINK, path); }; @@ -429,7 +429,7 @@ export class LibraryService extends EventEmitter { // Mark asset as offline this.logger.debug(`Marking asset as offline: ${assetPath}`); - await this.assetRepository.save({ id: existingAssetEntity.id, isOffline: true }); + await this.assetRepository.update({ id: existingAssetEntity.id, isOffline: true }); return JobStatus.SUCCESS; } else { // File can't be accessed and does not already exist in db @@ -462,7 +462,7 @@ export class LibraryService extends EventEmitter { if (stats && existingAssetEntity?.isOffline) { // File was previously offline but is now online this.logger.debug(`Marking previously-offline asset as online: ${assetPath}`); - await this.assetRepository.save({ id: existingAssetEntity.id, isOffline: false }); + await this.assetRepository.update({ id: existingAssetEntity.id, isOffline: false }); doRefresh = true; } diff --git a/server/src/domain/media/media.service.spec.ts b/server/src/domain/media/media.service.spec.ts index beea126bf..36d2cfdba 100644 --- a/server/src/domain/media/media.service.spec.ts +++ b/server/src/domain/media/media.service.spec.ts @@ -205,7 +205,7 @@ describe(MediaService.name, () => { assetMock.getByIds.mockResolvedValue([]); await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id }); expect(mediaMock.resize).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalledWith(); + expect(assetMock.update).not.toHaveBeenCalledWith(); }); it('should skip video thumbnail generation if no video stream', async () => { @@ -213,7 +213,7 @@ describe(MediaService.name, () => { assetMock.getByIds.mockResolvedValue([assetStub.video]); await sut.handleGenerateJpegThumbnail({ id: assetStub.image.id }); expect(mediaMock.resize).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalledWith(); + expect(assetMock.update).not.toHaveBeenCalledWith(); }); it('should generate a thumbnail for an image', async () => { @@ -227,7 +227,7 @@ describe(MediaService.name, () => { quality: 80, colorspace: Colorspace.SRGB, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', resizePath: 'upload/thumbs/user-id/as/se/asset-id.jpeg', }); @@ -246,7 +246,7 @@ describe(MediaService.name, () => { quality: 80, colorspace: Colorspace.P3, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', resizePath: 'upload/thumbs/user-id/as/se/asset-id.jpeg', }); @@ -271,7 +271,7 @@ describe(MediaService.name, () => { twoPass: false, }, ); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', resizePath: 'upload/thumbs/user-id/as/se/asset-id.jpeg', }); @@ -296,7 +296,7 @@ describe(MediaService.name, () => { twoPass: false, }, ); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', resizePath: 'upload/thumbs/user-id/as/se/asset-id.jpeg', }); @@ -337,7 +337,7 @@ describe(MediaService.name, () => { assetMock.getByIds.mockResolvedValue([]); await sut.handleGenerateWebpThumbnail({ id: assetStub.image.id }); expect(mediaMock.resize).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalledWith(); + expect(assetMock.update).not.toHaveBeenCalledWith(); }); it('should generate a thumbnail', async () => { @@ -350,7 +350,7 @@ describe(MediaService.name, () => { quality: 80, colorspace: Colorspace.SRGB, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', webpPath: 'upload/thumbs/user-id/as/se/asset-id.webp', }); @@ -370,7 +370,7 @@ describe(MediaService.name, () => { quality: 80, colorspace: Colorspace.P3, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', webpPath: 'upload/thumbs/user-id/as/se/asset-id.webp', }); @@ -397,7 +397,7 @@ describe(MediaService.name, () => { await sut.handleGenerateThumbhashThumbnail({ id: assetStub.image.id }); expect(mediaMock.generateThumbhash).toHaveBeenCalledWith('/uploads/user-id/thumbs/path.jpg'); - expect(assetMock.save).toHaveBeenCalledWith({ id: 'asset-id', thumbhash: thumbhashBuffer }); + expect(assetMock.update).toHaveBeenCalledWith({ id: 'asset-id', thumbhash: thumbhashBuffer }); }); }); diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index 9d522d104..31eafcbcf 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -172,7 +172,7 @@ export class MediaService { } const resizePath = await this.generateThumbnail(asset, 'jpeg'); - await this.assetRepository.save({ id: asset.id, resizePath }); + await this.assetRepository.update({ id: asset.id, resizePath }); return JobStatus.SUCCESS; } @@ -222,7 +222,7 @@ export class MediaService { } const webpPath = await this.generateThumbnail(asset, 'webp'); - await this.assetRepository.save({ id: asset.id, webpPath }); + await this.assetRepository.update({ id: asset.id, webpPath }); return JobStatus.SUCCESS; } @@ -233,7 +233,7 @@ export class MediaService { } const thumbhash = await this.mediaRepository.generateThumbhash(asset.resizePath); - await this.assetRepository.save({ id: asset.id, thumbhash }); + await this.assetRepository.update({ id: asset.id, thumbhash }); return JobStatus.SUCCESS; } @@ -286,7 +286,7 @@ export class MediaService { if (asset.encodedVideoPath) { this.logger.log(`Transcoded video exists for asset ${asset.id}, but is no longer required. Deleting...`); await this.jobRepository.queue({ name: JobName.DELETE_FILES, data: { files: [asset.encodedVideoPath] } }); - await this.assetRepository.save({ id: asset.id, encodedVideoPath: null }); + await this.assetRepository.update({ id: asset.id, encodedVideoPath: null }); } return JobStatus.SKIPPED; @@ -321,7 +321,7 @@ export class MediaService { this.logger.log(`Successfully encoded ${asset.id}`); - await this.assetRepository.save({ id: asset.id, encodedVideoPath: output }); + await this.assetRepository.update({ id: asset.id, encodedVideoPath: output }); return JobStatus.SUCCESS; } diff --git a/server/src/domain/metadata/metadata.service.spec.ts b/server/src/domain/metadata/metadata.service.spec.ts index c28c61f22..69d31cbd5 100644 --- a/server/src/domain/metadata/metadata.service.spec.ts +++ b/server/src/domain/metadata/metadata.service.spec.ts @@ -117,7 +117,7 @@ describe(MetadataService.name, () => { await expect(sut.handleLivePhotoLinking({ id: assetStub.image.id })).resolves.toBe(JobStatus.FAILED); expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id], { exifInfo: true }); expect(assetMock.findLivePhotoMatch).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); expect(albumMock.removeAsset).not.toHaveBeenCalled(); }); @@ -127,7 +127,7 @@ describe(MetadataService.name, () => { await expect(sut.handleLivePhotoLinking({ id: assetStub.image.id })).resolves.toBe(JobStatus.FAILED); expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id], { exifInfo: true }); expect(assetMock.findLivePhotoMatch).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); expect(albumMock.removeAsset).not.toHaveBeenCalled(); }); @@ -137,7 +137,7 @@ describe(MetadataService.name, () => { await expect(sut.handleLivePhotoLinking({ id: assetStub.image.id })).resolves.toBe(JobStatus.SKIPPED); expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id], { exifInfo: true }); expect(assetMock.findLivePhotoMatch).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); expect(albumMock.removeAsset).not.toHaveBeenCalled(); }); @@ -159,7 +159,7 @@ describe(MetadataService.name, () => { otherAssetId: assetStub.livePhotoMotionAsset.id, type: AssetType.IMAGE, }); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); expect(albumMock.removeAsset).not.toHaveBeenCalled(); }); @@ -182,11 +182,11 @@ describe(MetadataService.name, () => { otherAssetId: assetStub.livePhotoStillAsset.id, type: AssetType.VIDEO, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.livePhotoStillAsset.id, livePhotoVideoId: assetStub.livePhotoMotionAsset.id, }); - expect(assetMock.save).toHaveBeenCalledWith({ id: assetStub.livePhotoMotionAsset.id, isVisible: false }); + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.livePhotoMotionAsset.id, isVisible: false }); expect(albumMock.removeAsset).toHaveBeenCalledWith(assetStub.livePhotoMotionAsset.id); }); @@ -248,7 +248,7 @@ describe(MetadataService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]); expect(assetMock.upsertExif).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should handle a date in a sidecar file', async () => { @@ -267,7 +267,7 @@ describe(MetadataService.name, () => { await sut.handleMetadataExtraction({ id: assetStub.image.id }); expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.sidecar.id]); expect(assetMock.upsertExif).toHaveBeenCalledWith(expect.objectContaining({ dateTimeOriginal: sidecarDate })); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, duration: null, fileCreatedAt: sidecarDate, @@ -282,7 +282,7 @@ describe(MetadataService.name, () => { await sut.handleMetadataExtraction({ id: assetStub.image.id }); expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]); expect(assetMock.upsertExif).toHaveBeenCalledWith(expect.objectContaining({ iso: 160 })); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, duration: null, fileCreatedAt: assetStub.image.createdAt, @@ -304,7 +304,7 @@ describe(MetadataService.name, () => { expect(assetMock.upsertExif).toHaveBeenCalledWith( expect.objectContaining({ city: 'City', state: 'State', country: 'Country' }), ); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.withLocation.id, duration: null, fileCreatedAt: assetStub.withLocation.createdAt, @@ -333,7 +333,7 @@ describe(MetadataService.name, () => { expect(storageMock.writeFile).not.toHaveBeenCalled(); expect(jobMock.queue).not.toHaveBeenCalled(); expect(jobMock.queueAll).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalledWith( + expect(assetMock.update).not.toHaveBeenCalledWith( expect.objectContaining({ assetType: AssetType.VIDEO, isVisible: false }), ); }); @@ -376,7 +376,7 @@ describe(MetadataService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.livePhotoStillAsset.id]); expect(assetMock.create).toHaveBeenCalled(); // This could have arguments added expect(storageMock.writeFile).toHaveBeenCalledWith(assetStub.livePhotoMotionAsset.originalPath, video); - expect(assetMock.save).toHaveBeenNthCalledWith(1, { + expect(assetMock.update).toHaveBeenNthCalledWith(1, { id: assetStub.livePhotoStillAsset.id, livePhotoVideoId: fileStub.livePhotoMotion.uuid, }); @@ -404,7 +404,7 @@ describe(MetadataService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.livePhotoStillAsset.id]); expect(assetMock.create).toHaveBeenCalled(); // This could have arguments added expect(storageMock.writeFile).toHaveBeenCalledWith(assetStub.livePhotoMotionAsset.originalPath, video); - expect(assetMock.save).toHaveBeenNthCalledWith(1, { + expect(assetMock.update).toHaveBeenNthCalledWith(1, { id: assetStub.livePhotoStillAsset.id, livePhotoVideoId: fileStub.livePhotoMotion.uuid, }); @@ -430,7 +430,7 @@ describe(MetadataService.name, () => { expect(storageMock.readFile).toHaveBeenCalledWith(assetStub.livePhotoStillAsset.originalPath, expect.any(Object)); expect(assetMock.create).toHaveBeenCalled(); // This could have arguments added expect(storageMock.writeFile).toHaveBeenCalledWith(assetStub.livePhotoMotionAsset.originalPath, video); - expect(assetMock.save).toHaveBeenNthCalledWith(1, { + expect(assetMock.update).toHaveBeenNthCalledWith(1, { id: assetStub.livePhotoStillAsset.id, livePhotoVideoId: fileStub.livePhotoMotion.uuid, }); @@ -470,7 +470,7 @@ describe(MetadataService.name, () => { expect(assetMock.create).toHaveBeenCalledTimes(0); expect(storageMock.writeFile).toHaveBeenCalledTimes(0); // The still asset gets saved by handleMetadataExtraction, but not the video - expect(assetMock.save).toHaveBeenCalledTimes(1); + expect(assetMock.update).toHaveBeenCalledTimes(1); expect(jobMock.queue).toHaveBeenCalledTimes(0); }); @@ -529,7 +529,7 @@ describe(MetadataService.name, () => { projectionType: 'EQUIRECTANGULAR', timeZone: tags.tz, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, duration: null, fileCreatedAt: new Date('1970-01-01'), @@ -545,7 +545,7 @@ describe(MetadataService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]); expect(assetMock.upsertExif).toHaveBeenCalled(); - expect(assetMock.save).toHaveBeenCalledWith( + expect(assetMock.update).toHaveBeenCalledWith( expect.objectContaining({ id: assetStub.image.id, duration: '00:00:06.210', @@ -561,7 +561,7 @@ describe(MetadataService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]); expect(assetMock.upsertExif).toHaveBeenCalled(); - expect(assetMock.save).toHaveBeenCalledWith( + expect(assetMock.update).toHaveBeenCalledWith( expect.objectContaining({ id: assetStub.image.id, duration: '00:00:08.410', @@ -577,7 +577,7 @@ describe(MetadataService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]); expect(assetMock.upsertExif).toHaveBeenCalled(); - expect(assetMock.save).toHaveBeenCalledWith( + expect(assetMock.update).toHaveBeenCalledWith( expect.objectContaining({ id: assetStub.image.id, duration: '00:00:06.200', @@ -593,7 +593,7 @@ describe(MetadataService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.image.id]); expect(assetMock.upsertExif).toHaveBeenCalled(); - expect(assetMock.save).toHaveBeenCalledWith( + expect(assetMock.update).toHaveBeenCalledWith( expect.objectContaining({ id: assetStub.image.id, duration: '00:00:06.207', @@ -638,13 +638,13 @@ describe(MetadataService.name, () => { it('should do nothing if asset could not be found', async () => { assetMock.getByIds.mockResolvedValue([]); await expect(sut.handleSidecarSync({ id: assetStub.image.id })).resolves.toBe(JobStatus.FAILED); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should do nothing if asset has no sidecar path', async () => { assetMock.getByIds.mockResolvedValue([assetStub.image]); await expect(sut.handleSidecarSync({ id: assetStub.image.id })).resolves.toBe(JobStatus.FAILED); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should set sidecar path if exists (sidecar named photo.ext.xmp)', async () => { @@ -653,7 +653,7 @@ describe(MetadataService.name, () => { await expect(sut.handleSidecarSync({ id: assetStub.sidecar.id })).resolves.toBe(JobStatus.SUCCESS); expect(storageMock.checkFileExists).toHaveBeenCalledWith(`${assetStub.sidecar.originalPath}.xmp`, constants.R_OK); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.sidecar.id, sidecarPath: assetStub.sidecar.sidecarPath, }); @@ -670,7 +670,7 @@ describe(MetadataService.name, () => { assetStub.sidecarWithoutExt.sidecarPath, constants.R_OK, ); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.sidecarWithoutExt.id, sidecarPath: assetStub.sidecarWithoutExt.sidecarPath, }); @@ -688,7 +688,7 @@ describe(MetadataService.name, () => { assetStub.sidecarWithoutExt.sidecarPath, constants.R_OK, ); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.sidecar.id, sidecarPath: assetStub.sidecar.sidecarPath, }); @@ -700,7 +700,7 @@ describe(MetadataService.name, () => { await expect(sut.handleSidecarSync({ id: assetStub.sidecar.id })).resolves.toBe(JobStatus.SUCCESS); expect(storageMock.checkFileExists).toHaveBeenCalledWith(`${assetStub.sidecar.originalPath}.xmp`, constants.R_OK); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.sidecar.id, sidecarPath: null, }); @@ -724,16 +724,15 @@ describe(MetadataService.name, () => { assetMock.getByIds.mockResolvedValue([assetStub.image]); storageMock.checkFileExists.mockResolvedValue(false); await sut.handleSidecarDiscovery({ id: assetStub.image.id }); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should update a image asset when a sidecar is found', async () => { assetMock.getByIds.mockResolvedValue([assetStub.image]); - assetMock.save.mockResolvedValue(assetStub.image); storageMock.checkFileExists.mockResolvedValue(true); await sut.handleSidecarDiscovery({ id: assetStub.image.id }); expect(storageMock.checkFileExists).toHaveBeenCalledWith('/original/path.jpg.xmp', constants.R_OK); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, sidecarPath: '/original/path.jpg.xmp', }); @@ -741,11 +740,10 @@ describe(MetadataService.name, () => { it('should update a video asset when a sidecar is found', async () => { assetMock.getByIds.mockResolvedValue([assetStub.video]); - assetMock.save.mockResolvedValue(assetStub.video); storageMock.checkFileExists.mockResolvedValue(true); await sut.handleSidecarDiscovery({ id: assetStub.video.id }); expect(storageMock.checkFileExists).toHaveBeenCalledWith('/original/path.ext.xmp', constants.R_OK); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, sidecarPath: '/original/path.ext.xmp', }); diff --git a/server/src/domain/metadata/metadata.service.ts b/server/src/domain/metadata/metadata.service.ts index 5f0b28fc4..75838330d 100644 --- a/server/src/domain/metadata/metadata.service.ts +++ b/server/src/domain/metadata/metadata.service.ts @@ -177,8 +177,8 @@ export class MetadataService { const [photoAsset, motionAsset] = asset.type === AssetType.IMAGE ? [asset, match] : [match, asset]; - await this.assetRepository.save({ id: photoAsset.id, livePhotoVideoId: motionAsset.id }); - await this.assetRepository.save({ id: motionAsset.id, isVisible: false }); + await this.assetRepository.update({ id: photoAsset.id, livePhotoVideoId: motionAsset.id }); + await this.assetRepository.update({ id: motionAsset.id, isVisible: false }); await this.albumRepository.removeAsset(motionAsset.id); // Notify clients to hide the linked live photo asset @@ -249,7 +249,7 @@ export class MetadataService { if (dateTimeOriginal && timeZoneOffset) { localDateTime = new Date(dateTimeOriginal.getTime() + timeZoneOffset * 60_000); } - await this.assetRepository.save({ + await this.assetRepository.update({ id: asset.id, duration: tags.Duration ? this.getDuration(tags.Duration) : null, localDateTime, @@ -317,7 +317,7 @@ export class MetadataService { await this.repository.writeTags(sidecarPath, exif); if (!asset.sidecarPath) { - await this.assetRepository.save({ id, sidecarPath }); + await this.assetRepository.update({ id, sidecarPath }); } return JobStatus.SUCCESS; @@ -435,7 +435,7 @@ export class MetadataService { this.storageCore.ensureFolders(motionPath); await this.storageRepository.writeFile(motionAsset.originalPath, video); await this.jobRepository.queue({ name: JobName.METADATA_EXTRACTION, data: { id: motionAsset.id } }); - await this.assetRepository.save({ id: asset.id, livePhotoVideoId: motionAsset.id }); + await this.assetRepository.update({ id: asset.id, livePhotoVideoId: motionAsset.id }); // If the asset already had an associated livePhotoVideo, delete it, because // its checksum doesn't match the checksum of the motionAsset we just extracted @@ -587,7 +587,7 @@ export class MetadataService { } if (sidecarPath) { - await this.assetRepository.save({ id: asset.id, sidecarPath }); + await this.assetRepository.update({ id: asset.id, sidecarPath }); return JobStatus.SUCCESS; } @@ -598,7 +598,7 @@ export class MetadataService { this.logger.debug( `Sidecar file was not found. Checked paths '${sidecarPathWithExt}' and '${sidecarPathWithoutExt}'. Removing sidecarPath for asset ${asset.id}`, ); - await this.assetRepository.save({ id: asset.id, sidecarPath: null }); + await this.assetRepository.update({ id: asset.id, sidecarPath: null }); return JobStatus.SUCCESS; } diff --git a/server/src/domain/repositories/asset.repository.ts b/server/src/domain/repositories/asset.repository.ts index c4ddb3107..c504bbb7f 100644 --- a/server/src/domain/repositories/asset.repository.ts +++ b/server/src/domain/repositories/asset.repository.ts @@ -90,6 +90,25 @@ export type AssetCreate = Pick< > & Partial; +export type AssetWithoutRelations = Omit< + AssetEntity, + | 'livePhotoVideo' + | 'stack' + | 'albums' + | 'faces' + | 'owner' + | 'library' + | 'exifInfo' + | 'sharedLinks' + | 'smartInfo' + | 'smartSearch' + | 'tags' +>; + +export type AssetUpdateOptions = Pick & Partial; + +export type AssetUpdateAllOptions = Omit, 'id'>; + export interface MonthDay { day: number; month: number; @@ -138,8 +157,8 @@ export interface IAssetRepository { deleteAll(ownerId: string): Promise; getAll(pagination: PaginationOptions, options?: AssetSearchOptions): Paginated; getAllByDeviceId(userId: string, deviceId: string): Promise; - updateAll(ids: string[], options: Partial): Promise; - save(asset: Pick & Partial): Promise; + updateAll(ids: string[], options: Partial): Promise; + update(asset: AssetUpdateOptions): Promise; remove(asset: AssetEntity): Promise; softDeleteAll(ids: string[]): Promise; restoreAll(ids: string[]): Promise; diff --git a/server/src/domain/storage-template/storage-template.service.spec.ts b/server/src/domain/storage-template/storage-template.service.spec.ts index 21fa6ef7d..a81e27c8f 100644 --- a/server/src/domain/storage-template/storage-template.service.spec.ts +++ b/server/src/domain/storage-template/storage-template.service.spec.ts @@ -111,7 +111,7 @@ describe(StorageTemplateService.name, () => { expect(storageMock.checkFileExists).not.toHaveBeenCalled(); expect(storageMock.rename).not.toHaveBeenCalled(); expect(storageMock.copyFile).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); expect(moveMock.create).not.toHaveBeenCalled(); expect(moveMock.update).not.toHaveBeenCalled(); expect(storageMock.stat).not.toHaveBeenCalled(); @@ -122,14 +122,6 @@ describe(StorageTemplateService.name, () => { const newMotionPicturePath = `upload/library/${userStub.user1.id}/2022/2022-06-19/${assetStub.livePhotoStillAsset.id}.mp4`; const newStillPicturePath = `upload/library/${userStub.user1.id}/2022/2022-06-19/${assetStub.livePhotoStillAsset.id}.jpeg`; - when(assetMock.save) - .calledWith({ id: assetStub.livePhotoStillAsset.id, originalPath: newStillPicturePath }) - .mockResolvedValue(assetStub.livePhotoStillAsset); - - when(assetMock.save) - .calledWith({ id: assetStub.livePhotoMotionAsset.id, originalPath: newMotionPicturePath }) - .mockResolvedValue(assetStub.livePhotoMotionAsset); - when(assetMock.getByIds) .calledWith([assetStub.livePhotoStillAsset.id], { exifInfo: true }) .mockResolvedValue([assetStub.livePhotoStillAsset]); @@ -175,11 +167,11 @@ describe(StorageTemplateService.name, () => { expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.livePhotoStillAsset.id], { exifInfo: true }); expect(assetMock.getByIds).toHaveBeenCalledWith([assetStub.livePhotoMotionAsset.id], { exifInfo: true }); expect(storageMock.checkFileExists).toHaveBeenCalledTimes(2); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.livePhotoStillAsset.id, originalPath: newStillPicturePath, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.livePhotoMotionAsset.id, originalPath: newMotionPicturePath, }); @@ -200,10 +192,6 @@ describe(StorageTemplateService.name, () => { newPath: previousFailedNewPath, }); - when(assetMock.save) - .calledWith({ id: assetStub.image.id, originalPath: newPath }) - .mockResolvedValue(assetStub.image); - when(assetMock.getByIds) .calledWith([assetStub.image.id], { exifInfo: true }) .mockResolvedValue([assetStub.image]); @@ -232,7 +220,7 @@ describe(StorageTemplateService.name, () => { oldPath: assetStub.image.originalPath, newPath, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, originalPath: newPath, }); @@ -257,10 +245,6 @@ describe(StorageTemplateService.name, () => { newPath: previousFailedNewPath, }); - when(assetMock.save) - .calledWith({ id: assetStub.image.id, originalPath: newPath }) - .mockResolvedValue(assetStub.image); - when(assetMock.getByIds) .calledWith([assetStub.image.id], { exifInfo: true }) .mockResolvedValue([assetStub.image]); @@ -291,7 +275,7 @@ describe(StorageTemplateService.name, () => { oldPath: previousFailedNewPath, newPath, }); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, originalPath: newPath, }); @@ -307,10 +291,6 @@ describe(StorageTemplateService.name, () => { .mockResolvedValue({ size: 5000 } as Stats); when(cryptoMock.hashFile).calledWith(newPath).mockResolvedValue(Buffer.from('different-hash', 'utf8')); - when(assetMock.save) - .calledWith({ id: assetStub.image.id, originalPath: newPath }) - .mockResolvedValue(assetStub.image); - when(assetMock.getByIds) .calledWith([assetStub.image.id], { exifInfo: true }) .mockResolvedValue([assetStub.image]); @@ -345,7 +325,7 @@ describe(StorageTemplateService.name, () => { expect(storageMock.copyFile).toHaveBeenCalledWith(assetStub.image.originalPath, newPath); expect(storageMock.unlink).toHaveBeenCalledWith(newPath); expect(storageMock.unlink).toHaveBeenCalledTimes(1); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it.each` @@ -374,10 +354,6 @@ describe(StorageTemplateService.name, () => { newPath: previousFailedNewPath, }); - when(assetMock.save) - .calledWith({ id: assetStub.image.id, originalPath: newPath }) - .mockResolvedValue(assetStub.image); - when(assetMock.getByIds) .calledWith([assetStub.image.id], { exifInfo: true }) .mockResolvedValue([assetStub.image]); @@ -404,7 +380,7 @@ describe(StorageTemplateService.name, () => { expect(storageMock.rename).not.toHaveBeenCalled(); expect(storageMock.copyFile).not.toHaveBeenCalled(); expect(moveMock.update).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }, ); }); @@ -427,7 +403,6 @@ describe(StorageTemplateService.name, () => { items: [assetStub.image], hasNextPage: false, }); - assetMock.save.mockResolvedValue(assetStub.image); userMock.getList.mockResolvedValue([userStub.user1]); moveMock.create.mockResolvedValue({ id: '123', @@ -449,7 +424,7 @@ describe(StorageTemplateService.name, () => { expect(assetMock.getAll).toHaveBeenCalled(); expect(storageMock.checkFileExists).toHaveBeenCalledTimes(2); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, originalPath: 'upload/library/user-id/2023/2023-02-23/asset-id+1.jpg', }); @@ -474,7 +449,7 @@ describe(StorageTemplateService.name, () => { expect(storageMock.rename).not.toHaveBeenCalled(); expect(storageMock.copyFile).not.toHaveBeenCalled(); expect(storageMock.checkFileExists).not.toHaveBeenCalledTimes(2); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should skip when an asset is probably a duplicate', async () => { @@ -495,7 +470,7 @@ describe(StorageTemplateService.name, () => { expect(storageMock.rename).not.toHaveBeenCalled(); expect(storageMock.copyFile).not.toHaveBeenCalled(); expect(storageMock.checkFileExists).not.toHaveBeenCalledTimes(2); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should move an asset', async () => { @@ -503,7 +478,6 @@ describe(StorageTemplateService.name, () => { items: [assetStub.image], hasNextPage: false, }); - assetMock.save.mockResolvedValue(assetStub.image); userMock.getList.mockResolvedValue([userStub.user1]); moveMock.create.mockResolvedValue({ id: '123', @@ -520,7 +494,7 @@ describe(StorageTemplateService.name, () => { '/original/path.jpg', 'upload/library/user-id/2023/2023-02-23/asset-id.jpg', ); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, originalPath: 'upload/library/user-id/2023/2023-02-23/asset-id.jpg', }); @@ -531,7 +505,6 @@ describe(StorageTemplateService.name, () => { items: [assetStub.image], hasNextPage: false, }); - assetMock.save.mockResolvedValue(assetStub.image); userMock.getList.mockResolvedValue([userStub.storageLabel]); moveMock.create.mockResolvedValue({ id: '123', @@ -548,7 +521,7 @@ describe(StorageTemplateService.name, () => { '/original/path.jpg', 'upload/library/label-1/2023/2023-02-23/asset-id.jpg', ); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, originalPath: 'upload/library/label-1/2023/2023-02-23/asset-id.jpg', }); @@ -592,7 +565,7 @@ describe(StorageTemplateService.name, () => { expect(storageMock.utimes).toHaveBeenCalledWith(newPath, expect.any(Date), expect.any(Date)); expect(storageMock.unlink).toHaveBeenCalledWith(assetStub.image.originalPath); expect(storageMock.unlink).toHaveBeenCalledTimes(1); - expect(assetMock.save).toHaveBeenCalledWith({ + expect(assetMock.update).toHaveBeenCalledWith({ id: assetStub.image.id, originalPath: newPath, }); @@ -630,7 +603,7 @@ describe(StorageTemplateService.name, () => { 'upload/library/user-id/2023/2023-02-23/asset-id.jpg', ); expect(storageMock.stat).toHaveBeenCalledWith('upload/library/user-id/2023/2023-02-23/asset-id.jpg'); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should not update the database if the move fails', async () => { @@ -656,7 +629,7 @@ describe(StorageTemplateService.name, () => { '/original/path.jpg', 'upload/library/user-id/2023/2023-02-23/asset-id.jpg', ); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); it('should not move read-only asset', async () => { @@ -670,7 +643,6 @@ describe(StorageTemplateService.name, () => { ], hasNextPage: false, }); - assetMock.save.mockResolvedValue(assetStub.image); userMock.getList.mockResolvedValue([userStub.user1]); await sut.handleMigration(); @@ -678,7 +650,7 @@ describe(StorageTemplateService.name, () => { expect(assetMock.getAll).toHaveBeenCalled(); expect(storageMock.rename).not.toHaveBeenCalled(); expect(storageMock.copyFile).not.toHaveBeenCalled(); - expect(assetMock.save).not.toHaveBeenCalled(); + expect(assetMock.update).not.toHaveBeenCalled(); }); }); }); diff --git a/server/src/domain/storage/storage.core.ts b/server/src/domain/storage/storage.core.ts index 36e600b24..5cf65ad7c 100644 --- a/server/src/domain/storage/storage.core.ts +++ b/server/src/domain/storage/storage.core.ts @@ -286,19 +286,19 @@ export class StorageCore { private savePath(pathType: PathType, id: string, newPath: string) { switch (pathType) { case AssetPathType.ORIGINAL: { - return this.assetRepository.save({ id, originalPath: newPath }); + return this.assetRepository.update({ id, originalPath: newPath }); } case AssetPathType.JPEG_THUMBNAIL: { - return this.assetRepository.save({ id, resizePath: newPath }); + return this.assetRepository.update({ id, resizePath: newPath }); } case AssetPathType.WEBP_THUMBNAIL: { - return this.assetRepository.save({ id, webpPath: newPath }); + return this.assetRepository.update({ id, webpPath: newPath }); } case AssetPathType.ENCODED_VIDEO: { - return this.assetRepository.save({ id, encodedVideoPath: newPath }); + return this.assetRepository.update({ id, encodedVideoPath: newPath }); } case AssetPathType.SIDECAR: { - return this.assetRepository.save({ id, sidecarPath: newPath }); + return this.assetRepository.update({ id, sidecarPath: newPath }); } case PersonPathType.FACE: { return this.personRepository.update({ id, thumbnailPath: newPath }); diff --git a/server/src/infra/repositories/asset.repository.ts b/server/src/infra/repositories/asset.repository.ts index 09cf2c779..3af6eb150 100644 --- a/server/src/infra/repositories/asset.repository.ts +++ b/server/src/infra/repositories/asset.repository.ts @@ -6,6 +6,8 @@ import { AssetSearchOptions, AssetStats, AssetStatsOptions, + AssetUpdateAllOptions, + AssetUpdateOptions, IAssetRepository, LivePhotoSearchOptions, MapMarker, @@ -275,7 +277,7 @@ export class AssetRepository implements IAssetRepository { @GenerateSql({ params: [[DummyValue.UUID], { deviceId: DummyValue.STRING }] }) @Chunked() - async updateAll(ids: string[], options: Partial): Promise { + async updateAll(ids: string[], options: AssetUpdateAllOptions): Promise { await this.repository.update({ id: In(ids) }, options); } @@ -289,21 +291,8 @@ export class AssetRepository implements IAssetRepository { await this.repository.restore({ id: In(ids) }); } - async save(asset: Partial): Promise { - const { id } = await this.repository.save(asset); - return this.repository.findOneOrFail({ - where: { id }, - relations: { - exifInfo: true, - owner: true, - smartInfo: true, - tags: true, - faces: { - person: true, - }, - }, - withDeleted: true, - }); + async update(asset: AssetUpdateOptions): Promise { + await this.repository.update(asset.id, asset); } async remove(asset: AssetEntity): Promise { diff --git a/server/test/repositories/asset.repository.mock.ts b/server/test/repositories/asset.repository.mock.ts index b291b7183..b9451f34f 100644 --- a/server/test/repositories/asset.repository.mock.ts +++ b/server/test/repositories/asset.repository.mock.ts @@ -24,7 +24,7 @@ export const newAssetRepositoryMock = (): jest.Mocked => { getLibraryAssetPaths: jest.fn(), getByLibraryIdAndOriginalPath: jest.fn(), deleteAll: jest.fn(), - save: jest.fn(), + update: jest.fn(), remove: jest.fn(), findLivePhotoMatch: jest.fn(), getMapMarkers: jest.fn(), From f392fe7702ebb09773bf8cb6a08a369ef80f5ce5 Mon Sep 17 00:00:00 2001 From: Mert <101130780+mertalev@users.noreply.github.com> Date: Tue, 19 Mar 2024 23:23:57 -0400 Subject: [PATCH 002/152] fix(server): "view all" for cities only showing 12 cities (#8035) * view all cities * increase limit * rename endpoint * optimize query * remove pagination * update sql * linting * revert sort by count in explore page for now * fix query * fix * update sql * move to search, add partner support * update sql * pr feedback * euphemism * parameters as separate variable * move comment * update sql * linting --- mobile/openapi/README.md | 1 + mobile/openapi/doc/SearchApi.md | 52 +++++++++ mobile/openapi/lib/api/search_api.dart | 44 +++++++ mobile/openapi/test/search_api_test.dart | 5 + open-api/immich-openapi-specs.json | 35 ++++++ open-api/typescript-sdk/src/fetch-client.ts | 8 ++ .../domain/repositories/search.repository.ts | 1 + server/src/domain/search/search.service.ts | 46 ++++---- .../immich/controllers/search.controller.ts | 6 + .../infra/repositories/search.repository.ts | 58 ++++++++++ server/src/infra/sql/search.repository.sql | 108 ++++++++++++++++++ .../repositories/search.repository.mock.ts | 1 + web/src/routes/(user)/places/+page.svelte | 21 ++-- web/src/routes/(user)/places/+page.ts | 4 +- 14 files changed, 358 insertions(+), 32 deletions(-) diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index d8ff4d30f..938293568 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -161,6 +161,7 @@ Class | Method | HTTP request | Description *PersonApi* | [**reassignFaces**](doc//PersonApi.md#reassignfaces) | **PUT** /person/{id}/reassign | *PersonApi* | [**updatePeople**](doc//PersonApi.md#updatepeople) | **PUT** /person | *PersonApi* | [**updatePerson**](doc//PersonApi.md#updateperson) | **PUT** /person/{id} | +*SearchApi* | [**getAssetsByCity**](doc//SearchApi.md#getassetsbycity) | **GET** /search/cities | *SearchApi* | [**getExploreData**](doc//SearchApi.md#getexploredata) | **GET** /search/explore | *SearchApi* | [**getSearchSuggestions**](doc//SearchApi.md#getsearchsuggestions) | **GET** /search/suggestions | *SearchApi* | [**search**](doc//SearchApi.md#search) | **GET** /search | diff --git a/mobile/openapi/doc/SearchApi.md b/mobile/openapi/doc/SearchApi.md index f63488222..e4ab9ecfd 100644 --- a/mobile/openapi/doc/SearchApi.md +++ b/mobile/openapi/doc/SearchApi.md @@ -9,6 +9,7 @@ All URIs are relative to */api* Method | HTTP request | Description ------------- | ------------- | ------------- +[**getAssetsByCity**](SearchApi.md#getassetsbycity) | **GET** /search/cities | [**getExploreData**](SearchApi.md#getexploredata) | **GET** /search/explore | [**getSearchSuggestions**](SearchApi.md#getsearchsuggestions) | **GET** /search/suggestions | [**search**](SearchApi.md#search) | **GET** /search | @@ -18,6 +19,57 @@ Method | HTTP request | Description [**searchSmart**](SearchApi.md#searchsmart) | **POST** /search/smart | +# **getAssetsByCity** +> List getAssetsByCity() + + + +### Example +```dart +import 'package:openapi/api.dart'; +// TODO Configure API key authorization: cookie +//defaultApiClient.getAuthentication('cookie').apiKey = 'YOUR_API_KEY'; +// uncomment below to setup prefix (e.g. Bearer) for API key, if needed +//defaultApiClient.getAuthentication('cookie').apiKeyPrefix = 'Bearer'; +// TODO Configure API key authorization: api_key +//defaultApiClient.getAuthentication('api_key').apiKey = 'YOUR_API_KEY'; +// uncomment below to setup prefix (e.g. Bearer) for API key, if needed +//defaultApiClient.getAuthentication('api_key').apiKeyPrefix = 'Bearer'; +// TODO Configure HTTP Bearer authorization: bearer +// Case 1. Use String Token +//defaultApiClient.getAuthentication('bearer').setAccessToken('YOUR_ACCESS_TOKEN'); +// Case 2. Use Function which generate token. +// String yourTokenGeneratorFunction() { ... } +//defaultApiClient.getAuthentication('bearer').setAccessToken(yourTokenGeneratorFunction); + +final api_instance = SearchApi(); + +try { + final result = api_instance.getAssetsByCity(); + print(result); +} catch (e) { + print('Exception when calling SearchApi->getAssetsByCity: $e\n'); +} +``` + +### Parameters +This endpoint does not need any parameter. + +### Return type + +[**List**](AssetResponseDto.md) + +### Authorization + +[cookie](../README.md#cookie), [api_key](../README.md#api_key), [bearer](../README.md#bearer) + +### HTTP request headers + + - **Content-Type**: Not defined + - **Accept**: application/json + +[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md) + # **getExploreData** > List getExploreData() diff --git a/mobile/openapi/lib/api/search_api.dart b/mobile/openapi/lib/api/search_api.dart index 3a0bc56bb..386a2f353 100644 --- a/mobile/openapi/lib/api/search_api.dart +++ b/mobile/openapi/lib/api/search_api.dart @@ -16,6 +16,50 @@ class SearchApi { final ApiClient apiClient; + /// Performs an HTTP 'GET /search/cities' operation and returns the [Response]. + Future getAssetsByCityWithHttpInfo() async { + // ignore: prefer_const_declarations + final path = r'/search/cities'; + + // ignore: prefer_final_locals + Object? postBody; + + final queryParams = []; + final headerParams = {}; + final formParams = {}; + + const contentTypes = []; + + + return apiClient.invokeAPI( + path, + 'GET', + queryParams, + postBody, + headerParams, + formParams, + contentTypes.isEmpty ? null : contentTypes.first, + ); + } + + Future?> getAssetsByCity() async { + final response = await getAssetsByCityWithHttpInfo(); + if (response.statusCode >= HttpStatus.badRequest) { + throw ApiException(response.statusCode, await _decodeBodyBytes(response)); + } + // When a remote server returns no body with a status of 204, we shall not decode it. + // At the time of writing this, `dart:convert` will throw an "Unexpected end of input" + // FormatException when trying to decode an empty string. + if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) { + final responseBody = await _decodeBodyBytes(response); + return (await apiClient.deserializeAsync(responseBody, 'List') as List) + .cast() + .toList(growable: false); + + } + return null; + } + /// Performs an HTTP 'GET /search/explore' operation and returns the [Response]. Future getExploreDataWithHttpInfo() async { // ignore: prefer_const_declarations diff --git a/mobile/openapi/test/search_api_test.dart b/mobile/openapi/test/search_api_test.dart index aa4a94847..801c97a18 100644 --- a/mobile/openapi/test/search_api_test.dart +++ b/mobile/openapi/test/search_api_test.dart @@ -17,6 +17,11 @@ void main() { // final instance = SearchApi(); group('tests for SearchApi', () { + //Future> getAssetsByCity() async + test('test getAssetsByCity', () async { + // TODO + }); + //Future> getExploreData() async test('test getExploreData', () async { // TODO diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index 82562100a..f50abdffc 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -4597,6 +4597,41 @@ ] } }, + "/search/cities": { + "get": { + "operationId": "getAssetsByCity", + "parameters": [], + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/AssetResponseDto" + }, + "type": "array" + } + } + }, + "description": "" + } + }, + "security": [ + { + "bearer": [] + }, + { + "cookie": [] + }, + { + "api_key": [] + } + ], + "tags": [ + "Search" + ] + } + }, "/search/explore": { "get": { "operationId": "getExploreData", diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 6b5064252..00434aaba 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -2204,6 +2204,14 @@ export function search({ clip, motion, page, q, query, recent, size, smart, $typ ...opts })); } +export function getAssetsByCity(opts?: Oazapfts.RequestOpts) { + return oazapfts.ok(oazapfts.fetchJson<{ + status: 200; + data: AssetResponseDto[]; + }>("/search/cities", { + ...opts + })); +} export function getExploreData(opts?: Oazapfts.RequestOpts) { return oazapfts.ok(oazapfts.fetchJson<{ status: 200; diff --git a/server/src/domain/repositories/search.repository.ts b/server/src/domain/repositories/search.repository.ts index 10182a44e..bd4face86 100644 --- a/server/src/domain/repositories/search.repository.ts +++ b/server/src/domain/repositories/search.repository.ts @@ -187,5 +187,6 @@ export interface ISearchRepository { searchFaces(search: FaceEmbeddingSearch): Promise; upsert(smartInfo: Partial, embedding?: Embedding): Promise; searchPlaces(placeName: string): Promise; + getAssetsByCity(userIds: string[]): Promise; deleteAllSearchEmbeddings(): Promise; } diff --git a/server/src/domain/search/search.service.ts b/server/src/domain/search/search.service.ts index 56c4498bc..4b15dfd51 100644 --- a/server/src/domain/search/search.service.ts +++ b/server/src/domain/search/search.service.ts @@ -115,6 +115,32 @@ export class SearchService { return this.mapResponse(items, hasNextPage ? (page + 1).toString() : null); } + async getAssetsByCity(auth: AuthDto): Promise { + const userIds = await this.getUserIdsToSearch(auth); + const assets = await this.searchRepository.getAssetsByCity(userIds); + return assets.map((asset) => mapAsset(asset)); + } + + getSearchSuggestions(auth: AuthDto, dto: SearchSuggestionRequestDto): Promise { + switch (dto.type) { + case SearchSuggestionType.COUNTRY: { + return this.metadataRepository.getCountries(auth.user.id); + } + case SearchSuggestionType.STATE: { + return this.metadataRepository.getStates(auth.user.id, dto.country); + } + case SearchSuggestionType.CITY: { + return this.metadataRepository.getCities(auth.user.id, dto.country, dto.state); + } + case SearchSuggestionType.CAMERA_MAKE: { + return this.metadataRepository.getCameraMakes(auth.user.id, dto.model); + } + case SearchSuggestionType.CAMERA_MODEL: { + return this.metadataRepository.getCameraModels(auth.user.id, dto.make); + } + } + } + // TODO: remove after implementing new search filters /** @deprecated */ async search(auth: AuthDto, dto: SearchDto): Promise { @@ -191,24 +217,4 @@ export class SearchService { }, }; } - - async getSearchSuggestions(auth: AuthDto, dto: SearchSuggestionRequestDto): Promise { - switch (dto.type) { - case SearchSuggestionType.COUNTRY: { - return this.metadataRepository.getCountries(auth.user.id); - } - case SearchSuggestionType.STATE: { - return this.metadataRepository.getStates(auth.user.id, dto.country); - } - case SearchSuggestionType.CITY: { - return this.metadataRepository.getCities(auth.user.id, dto.country, dto.state); - } - case SearchSuggestionType.CAMERA_MAKE: { - return this.metadataRepository.getCameraMakes(auth.user.id, dto.model); - } - case SearchSuggestionType.CAMERA_MODEL: { - return this.metadataRepository.getCameraModels(auth.user.id, dto.make); - } - } - } } diff --git a/server/src/immich/controllers/search.controller.ts b/server/src/immich/controllers/search.controller.ts index d508531dd..a3527a66a 100644 --- a/server/src/immich/controllers/search.controller.ts +++ b/server/src/immich/controllers/search.controller.ts @@ -1,4 +1,5 @@ import { + AssetResponseDto, AuthDto, MetadataSearchDto, PersonResponseDto, @@ -55,6 +56,11 @@ export class SearchController { return this.service.searchPlaces(dto); } + @Get('cities') + getAssetsByCity(@Auth() auth: AuthDto): Promise { + return this.service.getAssetsByCity(auth); + } + @Get('suggestions') getSearchSuggestions(@Auth() auth: AuthDto, @Query() dto: SearchSuggestionRequestDto): Promise { return this.service.getSearchSuggestions(auth, dto); diff --git a/server/src/infra/repositories/search.repository.ts b/server/src/infra/repositories/search.repository.ts index f5d1cbda3..0e29506d1 100644 --- a/server/src/infra/repositories/search.repository.ts +++ b/server/src/infra/repositories/search.repository.ts @@ -15,6 +15,7 @@ import { getCLIPModelInfo } from '@app/domain/smart-info/smart-info.constant'; import { AssetEntity, AssetFaceEntity, + AssetType, GeodataPlacesEntity, SmartInfoEntity, SmartSearchEntity, @@ -33,6 +34,7 @@ import { Instrumentation } from '../instrumentation'; export class SearchRepository implements ISearchRepository { private logger = new ImmichLogger(SearchRepository.name); private faceColumns: string[]; + private assetsByCityQuery: string; constructor( @InjectRepository(SmartInfoEntity) private repository: Repository, @@ -45,6 +47,14 @@ export class SearchRepository implements ISearchRepository { .getMetadata(AssetFaceEntity) .ownColumns.map((column) => column.propertyName) .filter((propertyName) => propertyName !== 'embedding'); + this.assetsByCityQuery = + assetsByCityCte + + this.assetRepository + .createQueryBuilder('asset') + .innerJoinAndSelect('asset.exifInfo', 'exif') + .withDeleted() + .getQuery() + + ' INNER JOIN cte ON asset.id = cte."assetId"'; } async init(modelName: string): Promise { @@ -220,6 +230,27 @@ export class SearchRepository implements ISearchRepository { .getMany(); } + @GenerateSql({ params: [[DummyValue.UUID]] }) + async getAssetsByCity(userIds: string[]): Promise { + const parameters = [userIds.join(', '), true, false, AssetType.IMAGE]; + const rawRes = await this.repository.query(this.assetsByCityQuery, parameters); + + const items: AssetEntity[] = []; + for (const res of rawRes) { + const item = { exifInfo: {} as Record } as Record; + for (const [key, value] of Object.entries(res)) { + if (key.startsWith('exif_')) { + item.exifInfo[key.replace('exif_', '')] = value; + } else { + item[key.replace('asset_', '')] = value; + } + } + items.push(item as AssetEntity); + } + + return items; + } + async upsert(smartInfo: Partial, embedding?: Embedding): Promise { await this.repository.upsert(smartInfo, { conflictPaths: ['assetId'] }); if (!smartInfo.assetId || !embedding) { @@ -290,3 +321,30 @@ export class SearchRepository implements ISearchRepository { return runtimeConfig; } } + +// the performance difference between this and the normal way is too huge to ignore, e.g. 3s vs 4ms +const assetsByCityCte = ` +WITH RECURSIVE cte AS ( + ( + SELECT city, "assetId" + FROM exif + INNER JOIN assets ON exif."assetId" = assets.id + WHERE "ownerId" IN ($1) AND "isVisible" = $2 AND "isArchived" = $3 AND type = $4 + ORDER BY city + LIMIT 1 + ) + + UNION ALL + + SELECT l.city, l."assetId" + FROM cte c + , LATERAL ( + SELECT city, "assetId" + FROM exif + INNER JOIN assets ON exif."assetId" = assets.id + WHERE city > c.city AND "ownerId" IN ($1) AND "isVisible" = $2 AND "isArchived" = $3 AND type = $4 + ORDER BY city + LIMIT 1 + ) l +) +`; diff --git a/server/src/infra/sql/search.repository.sql b/server/src/infra/sql/search.repository.sql index a11f8805a..ff0239198 100644 --- a/server/src/infra/sql/search.repository.sql +++ b/server/src/infra/sql/search.repository.sql @@ -266,3 +266,111 @@ ORDER BY ) ASC LIMIT 20 + +-- SearchRepository.getAssetsByCity +WITH RECURSIVE + cte AS ( + ( + SELECT + city, + "assetId" + FROM + exif + INNER JOIN assets ON exif."assetId" = assets.id + WHERE + "ownerId" IN ($1) + AND "isVisible" = $2 + AND "isArchived" = $3 + AND type = $4 + ORDER BY + city + LIMIT + 1 + ) + UNION ALL + SELECT + l.city, + l."assetId" + FROM + cte c, + LATERAL ( + SELECT + city, + "assetId" + FROM + exif + INNER JOIN assets ON exif."assetId" = assets.id + WHERE + city > c.city + AND "ownerId" IN ($1) + AND "isVisible" = $2 + AND "isArchived" = $3 + AND type = $4 + ORDER BY + city + LIMIT + 1 + ) l + ) +SELECT + "asset"."id" AS "asset_id", + "asset"."deviceAssetId" AS "asset_deviceAssetId", + "asset"."ownerId" AS "asset_ownerId", + "asset"."libraryId" AS "asset_libraryId", + "asset"."deviceId" AS "asset_deviceId", + "asset"."type" AS "asset_type", + "asset"."originalPath" AS "asset_originalPath", + "asset"."resizePath" AS "asset_resizePath", + "asset"."webpPath" AS "asset_webpPath", + "asset"."thumbhash" AS "asset_thumbhash", + "asset"."encodedVideoPath" AS "asset_encodedVideoPath", + "asset"."createdAt" AS "asset_createdAt", + "asset"."updatedAt" AS "asset_updatedAt", + "asset"."deletedAt" AS "asset_deletedAt", + "asset"."fileCreatedAt" AS "asset_fileCreatedAt", + "asset"."localDateTime" AS "asset_localDateTime", + "asset"."fileModifiedAt" AS "asset_fileModifiedAt", + "asset"."isFavorite" AS "asset_isFavorite", + "asset"."isArchived" AS "asset_isArchived", + "asset"."isExternal" AS "asset_isExternal", + "asset"."isReadOnly" AS "asset_isReadOnly", + "asset"."isOffline" AS "asset_isOffline", + "asset"."checksum" AS "asset_checksum", + "asset"."duration" AS "asset_duration", + "asset"."isVisible" AS "asset_isVisible", + "asset"."livePhotoVideoId" AS "asset_livePhotoVideoId", + "asset"."originalFileName" AS "asset_originalFileName", + "asset"."sidecarPath" AS "asset_sidecarPath", + "asset"."stackId" AS "asset_stackId", + "exif"."assetId" AS "exif_assetId", + "exif"."description" AS "exif_description", + "exif"."exifImageWidth" AS "exif_exifImageWidth", + "exif"."exifImageHeight" AS "exif_exifImageHeight", + "exif"."fileSizeInByte" AS "exif_fileSizeInByte", + "exif"."orientation" AS "exif_orientation", + "exif"."dateTimeOriginal" AS "exif_dateTimeOriginal", + "exif"."modifyDate" AS "exif_modifyDate", + "exif"."timeZone" AS "exif_timeZone", + "exif"."latitude" AS "exif_latitude", + "exif"."longitude" AS "exif_longitude", + "exif"."projectionType" AS "exif_projectionType", + "exif"."city" AS "exif_city", + "exif"."livePhotoCID" AS "exif_livePhotoCID", + "exif"."autoStackId" AS "exif_autoStackId", + "exif"."state" AS "exif_state", + "exif"."country" AS "exif_country", + "exif"."make" AS "exif_make", + "exif"."model" AS "exif_model", + "exif"."lensModel" AS "exif_lensModel", + "exif"."fNumber" AS "exif_fNumber", + "exif"."focalLength" AS "exif_focalLength", + "exif"."iso" AS "exif_iso", + "exif"."exposureTime" AS "exif_exposureTime", + "exif"."profileDescription" AS "exif_profileDescription", + "exif"."colorspace" AS "exif_colorspace", + "exif"."bitsPerSample" AS "exif_bitsPerSample", + "exif"."fps" AS "exif_fps" +FROM + "assets" "asset" + INNER JOIN "exif" "exif" ON "exif"."assetId" = "asset"."id" + INNER JOIN cte ON asset.id = cte."assetId" diff --git a/server/test/repositories/search.repository.mock.ts b/server/test/repositories/search.repository.mock.ts index 5912d7745..7b428f0cc 100644 --- a/server/test/repositories/search.repository.mock.ts +++ b/server/test/repositories/search.repository.mock.ts @@ -8,6 +8,7 @@ export const newSearchRepositoryMock = (): jest.Mocked => { searchFaces: jest.fn(), upsert: jest.fn(), searchPlaces: jest.fn(), + getAssetsByCity: jest.fn(), deleteAllSearchEmbeddings: jest.fn(), }; }; diff --git a/web/src/routes/(user)/places/+page.svelte b/web/src/routes/(user)/places/+page.svelte index c5528fcb9..01222ab6b 100644 --- a/web/src/routes/(user)/places/+page.svelte +++ b/web/src/routes/(user)/places/+page.svelte @@ -3,20 +3,20 @@ import Icon from '$lib/components/elements/icon.svelte'; import UserPageLayout from '$lib/components/layouts/user-page-layout.svelte'; import { AppRoute } from '$lib/constants'; - import type { SearchExploreResponseDto } from '@immich/sdk'; import { mdiMapMarkerOff } from '@mdi/js'; import type { PageData } from './$types'; import { getMetadataSearchQuery } from '$lib/utils/metadata-search'; + import type { AssetResponseDto } from '@immich/sdk'; export let data: PageData; - const CITY_FIELD = 'exifInfo.city'; - const getFieldItems = (items: SearchExploreResponseDto[]) => { - const targetField = items.find((item) => item.fieldName === CITY_FIELD); - return targetField?.items || []; + type AssetWithCity = AssetResponseDto & { + exifInfo: { + city: string; + }; }; - $: places = getFieldItems(data.items); + $: places = data.items.filter((item): item is AssetWithCity => !!item.exifInfo?.city); $: hasPlaces = places.length > 0; let innerHeight: number; @@ -27,17 +27,18 @@ {#if hasPlaces}
- {#each places as item (item.data.id)} - + {#each places as item (item.id)} + {@const city = item.exifInfo.city} +
- +
- {item.value} + {city}
{/each} diff --git a/web/src/routes/(user)/places/+page.ts b/web/src/routes/(user)/places/+page.ts index 5627111ce..1f3a15fb6 100644 --- a/web/src/routes/(user)/places/+page.ts +++ b/web/src/routes/(user)/places/+page.ts @@ -1,10 +1,10 @@ import { authenticate } from '$lib/utils/auth'; -import { getExploreData } from '@immich/sdk'; +import { getAssetsByCity } from '@immich/sdk'; import type { PageLoad } from './$types'; export const load = (async () => { await authenticate(); - const items = await getExploreData(); + const items = await getAssetsByCity(); return { items, From 63b4fc6f6582396918803555f34bcfce82a4ace8 Mon Sep 17 00:00:00 2001 From: Alex Date: Tue, 19 Mar 2024 23:07:26 -0500 Subject: [PATCH 003/152] chore(mobile): svg logo (#8074) * chore(mobile): anti-aliasing logo * use svg * adjust height * better sizing --- mobile/assets/immich-logo-inline-dark.svg | 56 ++++++++++++++++++++++ mobile/assets/immich-logo-inline-light.svg | 54 +++++++++++++++++++++ mobile/ios/Podfile.lock | 2 +- mobile/lib/shared/ui/immich_app_bar.dart | 9 ++-- mobile/lib/shared/ui/immich_logo.dart | 1 + mobile/pubspec.lock | 40 ++++++++++++++++ mobile/pubspec.yaml | 1 + 7 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 mobile/assets/immich-logo-inline-dark.svg create mode 100644 mobile/assets/immich-logo-inline-light.svg diff --git a/mobile/assets/immich-logo-inline-dark.svg b/mobile/assets/immich-logo-inline-dark.svg new file mode 100644 index 000000000..8d72e075b --- /dev/null +++ b/mobile/assets/immich-logo-inline-dark.svg @@ -0,0 +1,56 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/mobile/assets/immich-logo-inline-light.svg b/mobile/assets/immich-logo-inline-light.svg new file mode 100644 index 000000000..d40a27a2b --- /dev/null +++ b/mobile/assets/immich-logo-inline-light.svg @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + diff --git a/mobile/ios/Podfile.lock b/mobile/ios/Podfile.lock index 6081988b7..a9ac5b338 100644 --- a/mobile/ios/Podfile.lock +++ b/mobile/ios/Podfile.lock @@ -180,4 +180,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: 64c9b5291666c0ca3caabdfe9865c141ac40321d -COCOAPODS: 1.11.3 +COCOAPODS: 1.12.1 diff --git a/mobile/lib/shared/ui/immich_app_bar.dart b/mobile/lib/shared/ui/immich_app_bar.dart index 5b26432d8..678302dd9 100644 --- a/mobile/lib/shared/ui/immich_app_bar.dart +++ b/mobile/lib/shared/ui/immich_app_bar.dart @@ -1,6 +1,7 @@ import 'package:auto_route/auto_route.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/shared/models/store.dart'; @@ -169,11 +170,11 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget { } return Padding( padding: const EdgeInsets.only(top: 3.0), - child: Image.asset( - height: 30, + child: SvgPicture.asset( context.isDarkTheme - ? 'assets/immich-logo-inline-dark.png' - : 'assets/immich-logo-inline-light.png', + ? 'assets/immich-logo-inline-dark.svg' + : 'assets/immich-logo-inline-light.svg', + height: 40, ), ); }, diff --git a/mobile/lib/shared/ui/immich_logo.dart b/mobile/lib/shared/ui/immich_logo.dart index af83887fb..9f7725aa1 100644 --- a/mobile/lib/shared/ui/immich_logo.dart +++ b/mobile/lib/shared/ui/immich_logo.dart @@ -18,6 +18,7 @@ class ImmichLogo extends StatelessWidget { image: const AssetImage('assets/immich-logo.png'), width: size, filterQuality: FilterQuality.high, + isAntiAlias: true, ), ); } diff --git a/mobile/pubspec.lock b/mobile/pubspec.lock index f7a57bb2b..2f35cf591 100644 --- a/mobile/pubspec.lock +++ b/mobile/pubspec.lock @@ -560,6 +560,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.4.9" + flutter_svg: + dependency: "direct main" + description: + name: flutter_svg + sha256: d39e7f95621fc84376bc0f7d504f05c3a41488c562f4a8ad410569127507402c + url: "https://pub.dev" + source: hosted + version: "2.0.9" flutter_test: dependency: "direct dev" description: flutter @@ -1006,6 +1014,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.8.3" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" + source: hosted + version: "1.0.1" path_provider: dependency: "direct main" description: @@ -1587,6 +1603,30 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.7" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "4ac59808bbfca6da38c99f415ff2d3a5d7ca0a6b4809c71d9cf30fba5daf9752" + url: "https://pub.dev" + source: hosted + version: "1.1.10+1" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: f3247e7ab0ec77dc759263e68394990edc608fb2b480b80db8aa86ed09279e33 + url: "https://pub.dev" + source: hosted + version: "1.1.10+1" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "18489bdd8850de3dd7ca8a34e0c446f719ec63e2bab2e7a8cc66a9028dd76c5a" + url: "https://pub.dev" + source: hosted + version: "1.1.10+1" vector_math: dependency: transitive description: diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index ed8a4fad6..a566d1aa9 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -34,6 +34,7 @@ dependencies: ref: acb428a005efd9832a0a8e7ef0945f899dfb3ca5 geolocator: ^11.0.0 # used to move to current location in map view flutter_udid: ^3.0.0 + flutter_svg: ^2.0.9 package_info_plus: ^5.0.1 url_launcher: ^6.2.4 http: 0.13.5 From 7395b03b1f99f659b3bc20e31bc1d6bf32cc21fa Mon Sep 17 00:00:00 2001 From: Thariq Shanavas Date: Tue, 19 Mar 2024 22:12:36 -0600 Subject: [PATCH 004/152] fix(docs) minor security warning raised by Borg (#8075) * Fix minor borg security warning * Update template-backup-script.md * removed one unnecessary step * Clarified optional steps * Update template-backup-script.md --- docs/docs/guides/template-backup-script.md | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/docs/docs/guides/template-backup-script.md b/docs/docs/guides/template-backup-script.md index cd43d660b..9a4f6c529 100644 --- a/docs/docs/guides/template-backup-script.md +++ b/docs/docs/guides/template-backup-script.md @@ -9,8 +9,8 @@ The database is saved to your Immich upload folder in the `database-backup` subd ### Prerequisites - Borg needs to be installed on your server as well as the remote machine. You can find instructions to install Borg [here](https://borgbackup.readthedocs.io/en/latest/installation.html). -- To run this sript as a non-root user, you should [add your username to the docker group](https://docs.docker.com/engine/install/linux-postinstall/). -- To run this script non-interactively, set up [passwordless ssh](https://www.redhat.com/sysadmin/passwordless-ssh) to your remote machine from your server. +- (Optional) To run this sript as a non-root user, you should [add your username to the docker group](https://docs.docker.com/engine/install/linux-postinstall/). +- To run this script non-interactively, set up [passwordless ssh](https://www.redhat.com/sysadmin/passwordless-ssh) to your remote machine from your server. If you skipped the previous step, make sure this step is done from your root account. To initialize the borg repository, run the following commands once. @@ -19,16 +19,13 @@ UPLOAD_LOCATION="/path/to/immich/directory" # Immich database location, as BACKUP_PATH="/path/to/local/backup/directory" mkdir "$UPLOAD_LOCATION/database-backup" -mkdir "$BACKUP_PATH/immich-borg" - borg init --encryption=none "$BACKUP_PATH/immich-borg" ## Remote set up REMOTE_HOST="remote_host@IP" REMOTE_BACKUP_PATH="/path/to/remote/backup/directory" -ssh "$REMOTE_HOST" "mkdir \"$REMOTE_BACKUP_PATH\"/immich-borg" -ssh "$REMOTE_HOST" "borg init --encryption=none \"$REMOTE_BACKUP_PATH\"/immich-borg" +borg init --encryption=none "$REMOTE_HOST:$REMOTE_BACKUP_PATH/immich-borg" ``` Edit the following script as necessary and add it to your crontab. Note that this script assumes there are no `:`, `@`, or `"` characters in your paths. If these characters exist, you will need to escape and/or rename the paths. From f908bd4a645306c89c5f90be41dbc7d5273fc308 Mon Sep 17 00:00:00 2001 From: Ethan Margaillan Date: Wed, 20 Mar 2024 05:28:13 +0100 Subject: [PATCH 005/152] fix(web): prevent drag-n-drop upload overlay from showing when not dragging files (#8082) --- .../shared-components/drag-and-drop-upload-overlay.svelte | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/src/lib/components/shared-components/drag-and-drop-upload-overlay.svelte b/web/src/lib/components/shared-components/drag-and-drop-upload-overlay.svelte index c4ecb5fb1..234448d66 100644 --- a/web/src/lib/components/shared-components/drag-and-drop-upload-overlay.svelte +++ b/web/src/lib/components/shared-components/drag-and-drop-upload-overlay.svelte @@ -6,7 +6,9 @@ let dragStartTarget: EventTarget | null = null; const handleDragEnter = (e: DragEvent) => { - dragStartTarget = e.target; + if (e.dataTransfer && e.dataTransfer.types.includes('Files')) { + dragStartTarget = e.target; + } }; From e6f2bb9f89c8f9b3010eec2d31f3c684d7d3bbae Mon Sep 17 00:00:00 2001 From: Jonathan Jogenfors Date: Wed, 20 Mar 2024 05:40:28 +0100 Subject: [PATCH 006/152] fix(server): use extension in originalFileName for libraries (#8083) * use file base * fix: test * fix: e2e-job tests --------- Co-authored-by: Alex Tran --- server/e2e/jobs/specs/library.e2e-spec.ts | 14 +++++++------- server/src/domain/library/library.service.spec.ts | 6 +++--- server/src/domain/library/library.service.ts | 2 +- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/server/e2e/jobs/specs/library.e2e-spec.ts b/server/e2e/jobs/specs/library.e2e-spec.ts index a4ee4977a..75411e8fa 100644 --- a/server/e2e/jobs/specs/library.e2e-spec.ts +++ b/server/e2e/jobs/specs/library.e2e-spec.ts @@ -61,11 +61,11 @@ describe(`${LibraryController.name} (e2e)`, () => { expect.arrayContaining([ expect.objectContaining({ isOffline: true, - originalFileName: 'el_torcal_rocks', + originalFileName: 'el_torcal_rocks.jpg', }), expect.objectContaining({ isOffline: true, - originalFileName: 'tanners_ridge', + originalFileName: 'tanners_ridge.jpg', }), ]), ); @@ -97,10 +97,10 @@ describe(`${LibraryController.name} (e2e)`, () => { expect(assets).toEqual( expect.arrayContaining([ expect.objectContaining({ - originalFileName: 'el_torcal_rocks', + originalFileName: 'el_torcal_rocks.jpg', }), expect.objectContaining({ - originalFileName: 'silver_fir', + originalFileName: 'silver_fir.jpg', }), ]), ); @@ -137,7 +137,7 @@ describe(`${LibraryController.name} (e2e)`, () => { expect(assets[0]).toEqual( expect.objectContaining({ - originalFileName: 'el_torcal_rocks', + originalFileName: 'el_torcal_rocks.jpg', exifInfo: expect.objectContaining({ dateTimeOriginal: '2023-09-25T08:33:30.880Z', exifImageHeight: 534, @@ -184,7 +184,7 @@ describe(`${LibraryController.name} (e2e)`, () => { expect(assets[0]).toEqual( expect.objectContaining({ - originalFileName: 'el_torcal_rocks', + originalFileName: 'el_torcal_rocks.jpg', exifInfo: expect.objectContaining({ dateTimeOriginal: '2012-08-05T11:39:59.000Z', }), @@ -224,7 +224,7 @@ describe(`${LibraryController.name} (e2e)`, () => { expect(assets[0]).toEqual( expect.objectContaining({ - originalFileName: 'el_torcal_rocks', + originalFileName: 'el_torcal_rocks.jpg', exifInfo: expect.objectContaining({ exifImageHeight: 534, exifImageWidth: 800, diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/domain/library/library.service.spec.ts index 0c0daa165..bd57a684d 100644 --- a/server/src/domain/library/library.service.spec.ts +++ b/server/src/domain/library/library.service.spec.ts @@ -377,7 +377,7 @@ describe(LibraryService.name, () => { fileModifiedAt: expect.any(Date), localDateTime: expect.any(Date), type: AssetType.IMAGE, - originalFileName: 'photo', + originalFileName: 'photo.jpg', sidecarPath: null, isReadOnly: true, isExternal: true, @@ -425,7 +425,7 @@ describe(LibraryService.name, () => { fileModifiedAt: expect.any(Date), localDateTime: expect.any(Date), type: AssetType.IMAGE, - originalFileName: 'photo', + originalFileName: 'photo.jpg', sidecarPath: '/data/user1/photo.jpg.xmp', isReadOnly: true, isExternal: true, @@ -472,7 +472,7 @@ describe(LibraryService.name, () => { fileModifiedAt: expect.any(Date), localDateTime: expect.any(Date), type: AssetType.VIDEO, - originalFileName: 'video', + originalFileName: 'video.mp4', sidecarPath: null, isReadOnly: true, isExternal: true, diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts index 3ef59c919..00667539b 100644 --- a/server/src/domain/library/library.service.ts +++ b/server/src/domain/library/library.service.ts @@ -511,7 +511,7 @@ export class LibraryService extends EventEmitter { fileModifiedAt: stats.mtime, localDateTime: stats.mtime, type: assetType, - originalFileName: parse(assetPath).name, + originalFileName: parse(assetPath).base, sidecarPath, isReadOnly: true, isExternal: true, From 9c6a26de9ff7a5e796a56696e9ab8e944a95e793 Mon Sep 17 00:00:00 2001 From: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Date: Wed, 20 Mar 2024 05:41:31 +0100 Subject: [PATCH 007/152] chore(web): add asset store unit tests (#8077) chore(web): asset store unit tests --- web/src/lib/__mocks__/sdk.mock.ts | 18 + .../album-page/__tests__/album-card.spec.ts | 11 +- web/src/lib/stores/asset.store.spec.ts | 357 ++++++++++++++++++ web/src/test-data/factories/asset-factory.ts | 30 ++ 4 files changed, 407 insertions(+), 9 deletions(-) create mode 100644 web/src/lib/__mocks__/sdk.mock.ts create mode 100644 web/src/lib/stores/asset.store.spec.ts create mode 100644 web/src/test-data/factories/asset-factory.ts diff --git a/web/src/lib/__mocks__/sdk.mock.ts b/web/src/lib/__mocks__/sdk.mock.ts new file mode 100644 index 000000000..a3e6f0f4d --- /dev/null +++ b/web/src/lib/__mocks__/sdk.mock.ts @@ -0,0 +1,18 @@ +import sdk from '@immich/sdk'; +import type { Mock, MockedObject } from 'vitest'; + +vi.mock('@immich/sdk', async (originalImport) => { + const module = await originalImport(); + + const mocks: Record = {}; + for (const [key, value] of Object.entries(module)) { + if (typeof value === 'function') { + mocks[key] = vi.fn(); + } + } + + const mock = { ...module, ...mocks }; + return { ...mock, default: mock }; +}); + +export const sdkMock = sdk as MockedObject; diff --git a/web/src/lib/components/album-page/__tests__/album-card.spec.ts b/web/src/lib/components/album-page/__tests__/album-card.spec.ts index b273271ce..6c6dc98f7 100644 --- a/web/src/lib/components/album-page/__tests__/album-card.spec.ts +++ b/web/src/lib/components/album-page/__tests__/album-card.spec.ts @@ -1,18 +1,11 @@ import { createObjectURLMock } from '$lib/__mocks__/jsdom-url.mock'; -import sdk, { ThumbnailFormat } from '@immich/sdk'; +import { sdkMock } from '$lib/__mocks__/sdk.mock'; +import { ThumbnailFormat } from '@immich/sdk'; import { albumFactory } from '@test-data'; import '@testing-library/jest-dom'; import { fireEvent, render, waitFor, type RenderResult } from '@testing-library/svelte'; -import type { MockedObject } from 'vitest'; import AlbumCard from '../album-card.svelte'; -vi.mock('@immich/sdk', async (originalImport) => { - const module = await originalImport(); - const mock = { ...module, getAssetThumbnail: vi.fn() }; - return { ...mock, default: mock }; -}); - -const sdkMock: MockedObject = sdk as MockedObject; const onShowContextMenu = vi.fn(); describe('AlbumCard component', () => { diff --git a/web/src/lib/stores/asset.store.spec.ts b/web/src/lib/stores/asset.store.spec.ts new file mode 100644 index 000000000..d97692ef6 --- /dev/null +++ b/web/src/lib/stores/asset.store.spec.ts @@ -0,0 +1,357 @@ +import { sdkMock } from '$lib/__mocks__/sdk.mock'; +import { TimeBucketSize, type AssetResponseDto } from '@immich/sdk'; +import { assetFactory } from '@test-data/factories/asset-factory'; +import { AssetStore, BucketPosition } from './assets.store'; + +describe('AssetStore', () => { + beforeEach(() => { + vi.resetAllMocks(); + }); + + describe('init', () => { + let assetStore: AssetStore; + const bucketAssets: Record = { + '2024-03-01T00:00:00.000Z': assetFactory.buildList(1), + '2024-02-01T00:00:00.000Z': assetFactory.buildList(100), + '2024-01-01T00:00:00.000Z': assetFactory.buildList(3), + }; + + beforeEach(async () => { + assetStore = new AssetStore({}); + sdkMock.getTimeBuckets.mockResolvedValue([ + { count: 1, timeBucket: '2024-03-01T00:00:00.000Z' }, + { count: 100, timeBucket: '2024-02-01T00:00:00.000Z' }, + { count: 3, timeBucket: '2024-01-01T00:00:00.000Z' }, + ]); + sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssets[timeBucket])); + + await assetStore.init({ width: 1588, height: 1000 }); + }); + + it('should load buckets in viewport', () => { + expect(sdkMock.getTimeBuckets).toBeCalledTimes(1); + expect(sdkMock.getTimeBuckets).toBeCalledWith({ size: TimeBucketSize.Month }); + expect(sdkMock.getTimeBucket).toHaveBeenCalledTimes(2); + }); + + it('calculates bucket height', () => { + expect(assetStore.buckets).toEqual( + expect.arrayContaining([ + expect.objectContaining({ bucketDate: '2024-03-01T00:00:00.000Z', bucketHeight: 235 }), + expect.objectContaining({ bucketDate: '2024-02-01T00:00:00.000Z', bucketHeight: 3760 }), + expect.objectContaining({ bucketDate: '2024-01-01T00:00:00.000Z', bucketHeight: 235 }), + ]), + ); + }); + + it('calculates timeline height', () => { + expect(assetStore.timelineHeight).toBe(4230); + }); + }); + + describe('loadBucket', () => { + let assetStore: AssetStore; + const bucketAssets: Record = { + '2024-01-03T00:00:00.000Z': assetFactory.buildList(1), + '2024-01-01T00:00:00.000Z': assetFactory.buildList(3), + }; + + beforeEach(async () => { + assetStore = new AssetStore({}); + sdkMock.getTimeBuckets.mockResolvedValue([ + { count: 1, timeBucket: '2024-01-03T00:00:00.000Z' }, + { count: 3, timeBucket: '2024-01-01T00:00:00.000Z' }, + ]); + sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssets[timeBucket])); + await assetStore.init({ width: 0, height: 0 }); + }); + + it('loads a bucket', async () => { + expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.assets.length).toEqual(0); + await assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Visible); + expect(sdkMock.getTimeBucket).toBeCalledTimes(1); + expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.assets.length).toEqual(3); + }); + + it('ignores invalid buckets', async () => { + await assetStore.loadBucket('2023-01-01T00:00:00.000Z', BucketPosition.Visible); + expect(sdkMock.getTimeBucket).toBeCalledTimes(0); + }); + + it('only updates the position of loaded buckets', async () => { + await assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Unknown); + expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.position).toEqual(BucketPosition.Unknown); + + await assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Visible); + expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.position).toEqual(BucketPosition.Visible); + }); + + it('cancels bucket loading', async () => { + const abortSpy = vi.spyOn(AbortController.prototype, 'abort'); + const loadPromise = assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Unknown); + + const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z'); + expect(bucket).not.toBeNull(); + + assetStore.cancelBucket(bucket!); + expect(abortSpy).toBeCalledTimes(1); + await loadPromise; + expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.assets.length).toEqual(0); + }); + }); + + describe('addAssets', () => { + let assetStore: AssetStore; + + beforeEach(async () => { + assetStore = new AssetStore({}); + sdkMock.getTimeBuckets.mockResolvedValue([]); + await assetStore.init({ width: 1588, height: 1000 }); + }); + + it('is empty initially', () => { + expect(assetStore.buckets.length).toEqual(0); + expect(assetStore.assets.length).toEqual(0); + }); + + it('adds assets to new bucket', () => { + const asset = assetFactory.build({ fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + assetStore.addAssets([asset]); + + expect(assetStore.buckets.length).toEqual(1); + expect(assetStore.assets.length).toEqual(1); + expect(assetStore.buckets[0].assets.length).toEqual(1); + expect(assetStore.buckets[0].bucketDate).toEqual('2024-01-01T00:00:00.000Z'); + expect(assetStore.assets[0].id).toEqual(asset.id); + }); + + it('adds assets to existing bucket', () => { + const [assetOne, assetTwo] = assetFactory.buildList(2, { fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + assetStore.addAssets([assetOne]); + assetStore.addAssets([assetTwo]); + + expect(assetStore.buckets.length).toEqual(1); + expect(assetStore.assets.length).toEqual(2); + expect(assetStore.buckets[0].assets.length).toEqual(2); + expect(assetStore.buckets[0].bucketDate).toEqual('2024-01-01T00:00:00.000Z'); + }); + + it('orders assets in buckets by descending date', () => { + const assetOne = assetFactory.build({ fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + const assetTwo = assetFactory.build({ fileCreatedAt: '2024-01-15T12:00:00.000Z' }); + const assetThree = assetFactory.build({ fileCreatedAt: '2024-01-16T12:00:00.000Z' }); + assetStore.addAssets([assetOne, assetTwo, assetThree]); + + const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z'); + expect(bucket).not.toBeNull(); + expect(bucket?.assets.length).toEqual(3); + expect(bucket?.assets[0].id).toEqual(assetOne.id); + expect(bucket?.assets[1].id).toEqual(assetThree.id); + expect(bucket?.assets[2].id).toEqual(assetTwo.id); + }); + + it('orders buckets by descending date', () => { + const assetOne = assetFactory.build({ fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + const assetTwo = assetFactory.build({ fileCreatedAt: '2024-04-20T12:00:00.000Z' }); + const assetThree = assetFactory.build({ fileCreatedAt: '2023-01-20T12:00:00.000Z' }); + assetStore.addAssets([assetOne, assetTwo, assetThree]); + + expect(assetStore.buckets.length).toEqual(3); + expect(assetStore.buckets[0].bucketDate).toEqual('2024-04-01T00:00:00.000Z'); + expect(assetStore.buckets[1].bucketDate).toEqual('2024-01-01T00:00:00.000Z'); + expect(assetStore.buckets[2].bucketDate).toEqual('2023-01-01T00:00:00.000Z'); + }); + + it('updates existing asset', () => { + const updateAssetsSpy = vi.spyOn(assetStore, 'updateAssets'); + const asset = assetFactory.build(); + assetStore.addAssets([asset]); + + assetStore.addAssets([asset]); + expect(updateAssetsSpy).toBeCalledWith([asset]); + expect(assetStore.assets.length).toEqual(1); + }); + }); + + describe('updateAssets', () => { + let assetStore: AssetStore; + + beforeEach(async () => { + assetStore = new AssetStore({}); + sdkMock.getTimeBuckets.mockResolvedValue([]); + await assetStore.init({ width: 1588, height: 1000 }); + }); + + it('ignores non-existing assets', () => { + assetStore.updateAssets([assetFactory.build()]); + + expect(assetStore.buckets.length).toEqual(0); + expect(assetStore.assets.length).toEqual(0); + }); + + it('updates an asset', () => { + const asset = assetFactory.build({ isFavorite: false }); + const updatedAsset = { ...asset, isFavorite: true }; + + assetStore.addAssets([asset]); + expect(assetStore.assets.length).toEqual(1); + expect(assetStore.assets[0].isFavorite).toEqual(false); + + assetStore.updateAssets([updatedAsset]); + expect(assetStore.assets.length).toEqual(1); + expect(assetStore.assets[0].isFavorite).toEqual(true); + }); + + it('replaces bucket date when asset date changes', () => { + const asset = assetFactory.build({ fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + const updatedAsset = { ...asset, fileCreatedAt: '2024-03-20T12:00:00.000Z' }; + + assetStore.addAssets([asset]); + expect(assetStore.buckets.length).toEqual(1); + expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')).not.toBeNull(); + + assetStore.updateAssets([updatedAsset]); + expect(assetStore.buckets.length).toEqual(1); + expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')).toBeNull(); + expect(assetStore.getBucketByDate('2024-03-01T00:00:00.000Z')).not.toBeNull(); + }); + }); + + describe('removeAssets', () => { + let assetStore: AssetStore; + + beforeEach(async () => { + assetStore = new AssetStore({}); + sdkMock.getTimeBuckets.mockResolvedValue([]); + await assetStore.init({ width: 1588, height: 1000 }); + }); + + it('ignores invalid IDs', () => { + assetStore.addAssets(assetFactory.buildList(2, { fileCreatedAt: '2024-01-20T12:00:00.000Z' })); + assetStore.removeAssets(['', 'invalid', '4c7d9acc']); + + expect(assetStore.assets.length).toEqual(2); + expect(assetStore.buckets.length).toEqual(1); + expect(assetStore.buckets[0].assets.length).toEqual(2); + }); + + it('removes asset from bucket', () => { + const [assetOne, assetTwo] = assetFactory.buildList(2, { fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + assetStore.addAssets([assetOne, assetTwo]); + assetStore.removeAssets([assetOne.id]); + + expect(assetStore.assets.length).toEqual(1); + expect(assetStore.buckets.length).toEqual(1); + expect(assetStore.buckets[0].assets.length).toEqual(1); + }); + + it('removes bucket when empty', () => { + const assets = assetFactory.buildList(2, { fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + assetStore.addAssets(assets); + assetStore.removeAssets(assets.map((asset) => asset.id)); + + expect(assetStore.assets.length).toEqual(0); + expect(assetStore.buckets.length).toEqual(0); + }); + }); + + describe('getPreviousAssetId', () => { + let assetStore: AssetStore; + const bucketAssets: Record = { + '2024-03-01T00:00:00.000Z': assetFactory.buildList(1), + '2024-02-01T00:00:00.000Z': assetFactory.buildList(6), + '2024-01-01T00:00:00.000Z': assetFactory.buildList(3), + }; + + beforeEach(async () => { + assetStore = new AssetStore({}); + sdkMock.getTimeBuckets.mockResolvedValue([ + { count: 1, timeBucket: '2024-03-01T00:00:00.000Z' }, + { count: 6, timeBucket: '2024-02-01T00:00:00.000Z' }, + { count: 3, timeBucket: '2024-01-01T00:00:00.000Z' }, + ]); + sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssets[timeBucket])); + + await assetStore.init({ width: 0, height: 0 }); + }); + + it('returns null for invalid assetId', async () => { + expect(() => assetStore.getPreviousAssetId('invalid')).not.toThrow(); + expect(await assetStore.getPreviousAssetId('invalid')).toBeNull(); + }); + + it('returns previous assetId', async () => { + await assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Visible); + const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z'); + + expect(await assetStore.getPreviousAssetId(bucket!.assets[1].id)).toEqual(bucket!.assets[0].id); + }); + + it('returns previous assetId spanning multiple buckets', async () => { + await assetStore.loadBucket('2024-02-01T00:00:00.000Z', BucketPosition.Visible); + await assetStore.loadBucket('2024-03-01T00:00:00.000Z', BucketPosition.Visible); + + const bucket = assetStore.getBucketByDate('2024-02-01T00:00:00.000Z'); + const previousBucket = assetStore.getBucketByDate('2024-03-01T00:00:00.000Z'); + expect(await assetStore.getPreviousAssetId(bucket!.assets[0].id)).toEqual(previousBucket!.assets[0].id); + }); + + it('loads previous bucket', async () => { + await assetStore.loadBucket('2024-02-01T00:00:00.000Z', BucketPosition.Visible); + + const loadBucketSpy = vi.spyOn(assetStore, 'loadBucket'); + const bucket = assetStore.getBucketByDate('2024-02-01T00:00:00.000Z'); + const previousBucket = assetStore.getBucketByDate('2024-03-01T00:00:00.000Z'); + expect(await assetStore.getPreviousAssetId(bucket!.assets[0].id)).toEqual(previousBucket!.assets[0].id); + expect(loadBucketSpy).toBeCalledTimes(1); + }); + + it('skips removed assets', async () => { + await assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Visible); + await assetStore.loadBucket('2024-02-01T00:00:00.000Z', BucketPosition.Visible); + await assetStore.loadBucket('2024-03-01T00:00:00.000Z', BucketPosition.Visible); + + const [assetOne, assetTwo, assetThree] = assetStore.assets; + assetStore.removeAssets([assetTwo.id]); + expect(await assetStore.getPreviousAssetId(assetThree.id)).toEqual(assetOne.id); + }); + + it('returns null when no more assets', async () => { + await assetStore.loadBucket('2024-03-01T00:00:00.000Z', BucketPosition.Visible); + expect(await assetStore.getPreviousAssetId(assetStore.assets[0].id)).toBeNull(); + }); + }); + + describe('getBucketIndexByAssetId', () => { + let assetStore: AssetStore; + + beforeEach(async () => { + assetStore = new AssetStore({}); + sdkMock.getTimeBuckets.mockResolvedValue([]); + await assetStore.init({ width: 0, height: 0 }); + }); + + it('returns null for invalid buckets', () => { + expect(assetStore.getBucketByDate('invalid')).toBeNull(); + expect(assetStore.getBucketByDate('2024-03-01T00:00:00.000Z')).toBeNull(); + }); + + it('returns the bucket index', () => { + const assetOne = assetFactory.build({ fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + const assetTwo = assetFactory.build({ fileCreatedAt: '2024-02-15T12:00:00.000Z' }); + assetStore.addAssets([assetOne, assetTwo]); + + expect(assetStore.getBucketIndexByAssetId(assetTwo.id)).toEqual(0); + expect(assetStore.getBucketIndexByAssetId(assetOne.id)).toEqual(1); + }); + + it('ignores removed buckets', () => { + const assetOne = assetFactory.build({ fileCreatedAt: '2024-01-20T12:00:00.000Z' }); + const assetTwo = assetFactory.build({ fileCreatedAt: '2024-02-15T12:00:00.000Z' }); + assetStore.addAssets([assetOne, assetTwo]); + + assetStore.removeAssets([assetTwo.id]); + expect(assetStore.getBucketIndexByAssetId(assetOne.id)).toEqual(0); + }); + }); +}); diff --git a/web/src/test-data/factories/asset-factory.ts b/web/src/test-data/factories/asset-factory.ts new file mode 100644 index 000000000..32cb723c0 --- /dev/null +++ b/web/src/test-data/factories/asset-factory.ts @@ -0,0 +1,30 @@ +import { faker } from '@faker-js/faker'; +import { AssetTypeEnum, type AssetResponseDto } from '@immich/sdk'; +import { Sync } from 'factory.ts'; + +export const assetFactory = Sync.makeFactory({ + id: Sync.each(() => faker.string.uuid()), + deviceAssetId: Sync.each(() => faker.string.uuid()), + ownerId: Sync.each(() => faker.string.uuid()), + deviceId: '', + libraryId: Sync.each(() => faker.string.uuid()), + type: Sync.each(() => faker.helpers.enumValue(AssetTypeEnum)), + originalPath: Sync.each(() => faker.system.filePath()), + originalFileName: Sync.each(() => faker.system.fileName()), + resized: true, + thumbhash: Sync.each(() => faker.string.alphanumeric(28)), + fileCreatedAt: Sync.each(() => faker.date.past().toISOString()), + fileModifiedAt: Sync.each(() => faker.date.past().toISOString()), + localDateTime: Sync.each(() => faker.date.past().toISOString()), + updatedAt: Sync.each(() => faker.date.past().toISOString()), + isFavorite: Sync.each(() => faker.datatype.boolean()), + isArchived: Sync.each(() => faker.datatype.boolean()), + isTrashed: Sync.each(() => faker.datatype.boolean()), + duration: '0:00:00.00000', + checksum: Sync.each(() => faker.string.alphanumeric(28)), + isExternal: Sync.each(() => faker.datatype.boolean()), + isOffline: Sync.each(() => faker.datatype.boolean()), + isReadOnly: Sync.each(() => faker.datatype.boolean()), + hasMetadata: Sync.each(() => faker.datatype.boolean()), + stackCount: null, +}); From e810aae21240be2baea365a99e2b61e2eb1e0996 Mon Sep 17 00:00:00 2001 From: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Date: Wed, 20 Mar 2024 13:24:08 +0100 Subject: [PATCH 008/152] fix(web): show search page errors and use feature flag (#8088) --- web/src/routes/(user)/search/+page.svelte | 36 ++++++++++++++--------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/web/src/routes/(user)/search/+page.svelte b/web/src/routes/(user)/search/+page.svelte index 77ebe7ad2..5774541e4 100644 --- a/web/src/routes/(user)/search/+page.svelte +++ b/web/src/routes/(user)/search/+page.svelte @@ -37,6 +37,8 @@ import LoadingSpinner from '$lib/components/shared-components/loading-spinner.svelte'; import { handlePromiseError } from '$lib/utils'; import { parseUtcDate } from '$lib/utils/date-time'; + import { featureFlags } from '$lib/stores/server-config.store'; + import { handleError } from '$lib/utils/handle-error'; const MAX_ASSET_COUNT = 5000; let { isViewing: showAssetViewer } = assetViewingStore; @@ -98,11 +100,12 @@ type SearchTerms = MetadataSearchDto & Pick; $: searchQuery = $page.url.searchParams.get(QueryParameter.QUERY); - $: terms = ((): SearchTerms => { - return searchQuery ? JSON.parse(searchQuery) : {}; - })(); + let terms: SearchTerms; + $: terms = searchQuery ? JSON.parse(searchQuery) : {}; - $: terms, handlePromiseError(onSearchQueryUpdate()); + $: if (terms && $featureFlags.loaded) { + handlePromiseError(onSearchQueryUpdate()); + } async function onSearchQueryUpdate() { nextPage = 1; @@ -124,18 +127,23 @@ ...terms, }; - const { albums, assets } = - 'query' in searchDto - ? await searchSmart({ smartSearchDto: searchDto }) - : await searchMetadata({ metadataSearchDto: searchDto }); + try { + const { albums, assets } = + 'query' in searchDto && $featureFlags.smartSearch + ? await searchSmart({ smartSearchDto: searchDto }) + : await searchMetadata({ metadataSearchDto: searchDto }); - searchResultAlbums.push(...albums.items); - searchResultAssets.push(...assets.items); - searchResultAlbums = searchResultAlbums; - searchResultAssets = searchResultAssets; + searchResultAlbums.push(...albums.items); + searchResultAssets.push(...assets.items); + searchResultAlbums = searchResultAlbums; + searchResultAssets = searchResultAssets; - nextPage = assets.nextPage ? Number(assets.nextPage) : null; - isLoading = false; + nextPage = assets.nextPage ? Number(assets.nextPage) : null; + } catch (error) { + handleError(error, 'Loading search results failed'); + } finally { + isLoading = false; + } }; function getHumanReadableDate(dateString: string) { From 0544c687b939f0375c35aed49c42a2fbb336ad74 Mon Sep 17 00:00:00 2001 From: Ethan Margaillan Date: Wed, 20 Mar 2024 13:29:30 +0100 Subject: [PATCH 009/152] fix(web): missing margin on people page (#8081) --- web/src/routes/(user)/people/[personId]/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/routes/(user)/people/[personId]/+page.svelte b/web/src/routes/(user)/people/[personId]/+page.svelte index d532018a4..ae99b0762 100644 --- a/web/src/routes/(user)/people/[personId]/+page.svelte +++ b/web/src/routes/(user)/people/[personId]/+page.svelte @@ -434,7 +434,7 @@ {/if} -
+
{#key refreshAssetGrid} Date: Wed, 20 Mar 2024 06:31:52 -0600 Subject: [PATCH 010/152] test: temporarily disable flaky audit e2e test until #7436 is fixed (#8089) --- e2e/src/api/specs/audit.e2e-spec.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/e2e/src/api/specs/audit.e2e-spec.ts b/e2e/src/api/specs/audit.e2e-spec.ts index 2b551fd24..ec8c3799c 100644 --- a/e2e/src/api/specs/audit.e2e-spec.ts +++ b/e2e/src/api/specs/audit.e2e-spec.ts @@ -12,7 +12,8 @@ describe('/audit', () => { admin = await utils.adminSetup(); }); - describe('GET :/file-report', () => { + // TODO: Enable these tests again once #7436 is resolved as these were flaky + describe.skip('GET :/file-report', () => { it('excludes assets without issues from report', async () => { const [trashedAsset, archivedAsset] = await Promise.all([ utils.createAsset(admin.accessToken), From 48e32269f42d8ec4ab01111110b79605ad9c3db6 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 20 Mar 2024 09:16:00 -0500 Subject: [PATCH 011/152] chore: add prometheus.yml to release artifact (#8096) --- .github/workflows/prepare-release.yml | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml index 000dbe2dd..9d50f6f8f 100644 --- a/.github/workflows/prepare-release.yml +++ b/.github/workflows/prepare-release.yml @@ -4,16 +4,16 @@ on: workflow_dispatch: inputs: serverBump: - description: "Bump server version" + description: 'Bump server version' required: true - default: "false" + default: 'false' type: choice options: - - "false" + - 'false' - minor - patch mobileBump: - description: "Bump mobile build number" + description: 'Bump mobile build number' required: false type: boolean @@ -46,8 +46,8 @@ jobs: with: author_name: Alex The Bot author_email: alex.tran1502@gmail.com - default_author: user_info - message: "Version ${{ env.IMMICH_VERSION }}" + default_author: user_info + message: 'Version ${{ env.IMMICH_VERSION }}' tag: ${{ env.IMMICH_VERSION }} push: true @@ -85,4 +85,5 @@ jobs: docker/example.env docker/hwaccel.ml.yml docker/hwaccel.transcoding.yml + docker/prometheus.yml *.apk From 5a2394af7cdaef46a0990913a7f6f18ffbdd16da Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 20 Mar 2024 09:16:20 -0500 Subject: [PATCH 012/152] fix(web): shift-select (#8093) * fix(web): shift-select * remove unused code * proper fix --- web/src/lib/components/photos-page/asset-grid.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte index c21439d24..8822e1e0b 100644 --- a/web/src/lib/components/photos-page/asset-grid.svelte +++ b/web/src/lib/components/photos-page/asset-grid.svelte @@ -207,7 +207,7 @@ return; } - if (matchesShortcut(event, { key: 'Shift' })) { + if (matchesShortcut(event, { key: 'Shift', shift: true })) { event.preventDefault(); shiftKeyIsDown = true; } @@ -218,7 +218,7 @@ return; } - if (matchesShortcut(event, { key: 'Shift' })) { + if (matchesShortcut(event, { key: 'Shift', shift: true })) { event.preventDefault(); shiftKeyIsDown = false; } From c4e910dd3d0087ca7dda2daa2a344dcc25582a97 Mon Sep 17 00:00:00 2001 From: Mert <101130780+mertalev@users.noreply.github.com> Date: Wed, 20 Mar 2024 10:20:46 -0400 Subject: [PATCH 013/152] docs(server): add documentation for prometheus metrics (#8084) * add monitoring doc * wording * indent * note instead of tip * Update docs/docs/features/monitoring.md Co-authored-by: bo0tzz * Update docs/docs/features/monitoring.md Co-authored-by: bo0tzz --------- Co-authored-by: Alex Tran Co-authored-by: bo0tzz --- docs/docs/features/monitoring.md | 113 +++++++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 docs/docs/features/monitoring.md diff --git a/docs/docs/features/monitoring.md b/docs/docs/features/monitoring.md new file mode 100644 index 000000000..7e001c992 --- /dev/null +++ b/docs/docs/features/monitoring.md @@ -0,0 +1,113 @@ +# Monitoring + +## Overview + +Immich provides a variety of performance metrics to allow for local monitoring and insights. This integration is primarily in the form of Prometheus metrics. However, exporting traces is also possible due to the use of OpenTelemetry instrumentation. + +:::note +This is an opt-in feature intended for you to monitor immich's performance. This data isn't sent anywhere beyond what you've configured. +::: + +## Prometheus + +Prometheus is a tool that collects metrics from a number of sources you configure. It operates in a "pull" strategy - that is, it periodically requests metrics from each defined source. This means that the source doesn't send anything until it's requested. It also means that the source -- immich, in this case -- has to expose an endpoint for Prometheus to target when it requests metrics. + +### Metrics + +These metrics come in a variety of forms: + +- Counters, which can only increase. Example: the number of times an endpoint has been called. +- Gauges, which can increase or decrease within a certain range. Example: CPU utilization. +- Histograms, where each observation is assigned to a certain number of "buckets". Example: response time, where each bucket is a number of milliseconds. This one is a bit more complicated. + - Buckets in this case are _cumulative_; that is, an observation is placed not only into the smallest bucket that contains it, but also to all buckets larger than this. For example, if a histogram has three buckets for 1ms, 5ms and 10ms, an observation of 3ms will be bucketed into both 5ms and 10ms. + +The metrics in immich are grouped into API (endpoint calls and response times), host (memory and CPU utilization), and IO (internal database queries, image processing, and so on). Each group of metrics can be enabled or disabled independently. + +### Configuration + +Immich will not expose an endpoint for metrics by default. To enable this endpoint, you can add the `IMMICH_METRICS=true` environmental variable to your `.env` file. Note that only the server and microservices containers currently use this variable. + +:::note +`IMMICH_METRICS` is equivalent to enabling the following three environmental variables: `IMMICH_API_METRICS`, `IMMICH_HOST_METRICS`, and `IMMICH_IO_METRICS`. If you would like to only expose certain kinds of metrics, you can set only those environmental variables to `true`. Explicitly setting the environmental variable for a metric group overrides `IMMICH_METRICS` for that group. +::: + +The next step is to configure a new or existing Prometheus instance to scrape this endpoint. The following steps assume that you do not have an existing Prometheus instance, but the steps will be similar either way. + +You can start by defining a Prometheus service in the Compose file: + +```yaml +immich-prometheus: + container_name: immich_prometheus + ports: + # this exposes the default port for Prometheus so you can interact with it + - 9090:9090 + image: prom/prometheus + volumes: + # the Prometheus configuration file - a barebones one is provided to get started + - ./prometheus.yml:/etc/prometheus/prometheus.yml + # a named volume defined in the bottom of the Compose file; it can also be a mounted folder + - prometheus-data:/prometheus +``` + +You will also need to add `prometheus-data` to the list of volumes in the bottom of the Compose file: + +```yaml +volumes: + model-cache: + prometheus-data: +``` + +The last piece is the [configuration file][prom-file]. This file defines (among other things) the sources Prometheus should target. Download it and place it in the same folder as the Compose file. + +:::tip +The provided file is just a starting point. There are a ton of ways to configure Prometheus, so feel free to experiment! +::: + +After bringing down the containers with `docker compose down` and back up with `docker compose up -d`, a Prometheus instance will now collect metrics from the immich server and microservices containers. Note that we didn't need to expose any new ports for these containers - the communication is handled in the internal Docker network. + +:::note +To see exactly what metrics are made available, you can additionally add `8081:8081` to the server container's ports and `8082:8081` to the microservices container's ports. Visiting the `/metrics` endpoint for these services will show the same raw data that Prometheus collects. +::: + +### Usage + +So after setting up Prometheus, how do you actually view the metrics? The simplest way is to use Prometheus directly. Visiting Prometheus will show you a web UI where you can search for and visualize metrics. You can also view the status of your data sources and configure settings, but this is beyond the scope of this guide. + +## Grafana + +For a dedicated tool with nice presentation, you can use Grafana instead. This connects to Prometheus (and possibly other sources) for sophisticated data visualization. + +Setting up Grafana is similar to Prometheus. You can add a service for it: + +```yaml +immich-grafana: + container_name: immich_grafana + command: ['./run.sh', '-disable-reporting'] # this is to disable Grafana's telemetry + ports: + - 3000:3000 + image: grafana/grafana + volumes: + # stores your pretty dashboards and panels + - grafana-data:/var/lib/grafana +``` + +And add another volume for it: + +```yaml +volumes: + model-cache: + prometheus-data: + grafana-data: +``` + +After bringing down the services and back up again, you can now visit Grafana to view your metrics. On the first login, enter `admin` for both username and password and update your password. You can then go to the settings and add a data source with `http://immich-prometheus:9090` to point Grafana to your Prometheus instance. + +### Usage + +You can make your first dashboard to get started. Don't forget to save it frequently, or you'll lose all your progress! + +You can then make a new panel, specifying Prometheus as the data source for it. + +-- TODO: add images and more details here + +[prom-file]: https://github.com/immich-app/immich/releases/latest/download/prometheus.yml From 5e090646ba4cedf2b045677a22e1407eff27c289 Mon Sep 17 00:00:00 2001 From: waclaw66 Date: Wed, 20 Mar 2024 16:26:09 +0200 Subject: [PATCH 014/152] fix(mobile): missing "Add name" translation (#8087) fix(mobile): missing "Add name" translation, positioning --- mobile/assets/i18n/en-US.json | 1 + .../lib/modules/asset_viewer/ui/exif_sheet/exif_map.dart | 2 +- mobile/lib/modules/search/ui/curated_people_row.dart | 7 ++++--- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/mobile/assets/i18n/en-US.json b/mobile/assets/i18n/en-US.json index 9da867386..3bebcb2b1 100644 --- a/mobile/assets/i18n/en-US.json +++ b/mobile/assets/i18n/en-US.json @@ -190,6 +190,7 @@ "exif_bottom_sheet_location": "LOCATION", "exif_bottom_sheet_location_add": "Add a location", "exif_bottom_sheet_people": "PEOPLE", + "exif_bottom_sheet_person_add_person": "Add name", "experimental_settings_new_asset_list_subtitle": "Work in progress", "experimental_settings_new_asset_list_title": "Enable experimental photo grid", "experimental_settings_subtitle": "Use at your own risk!", diff --git a/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_map.dart b/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_map.dart index 6c0050aee..69644e678 100644 --- a/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_map.dart +++ b/mobile/lib/modules/asset_viewer/ui/exif_sheet/exif_map.dart @@ -64,7 +64,7 @@ class ExifMap extends StatelessWidget { } return Padding( - padding: const EdgeInsets.symmetric(vertical: 16.0), + padding: const EdgeInsets.symmetric(vertical: 8.0), child: LayoutBuilder( builder: (context, constraints) { return MapThumbnail( diff --git a/mobile/lib/modules/search/ui/curated_people_row.dart b/mobile/lib/modules/search/ui/curated_people_row.dart index 049c1ce46..8af610ad1 100644 --- a/mobile/lib/modules/search/ui/curated_people_row.dart +++ b/mobile/lib/modules/search/ui/curated_people_row.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:easy_localization/easy_localization.dart'; import 'package:immich_mobile/extensions/build_context_extensions.dart'; import 'package:immich_mobile/modules/search/models/curated_content.dart'; import 'package:immich_mobile/modules/search/ui/thumbnail_with_info.dart'; @@ -23,7 +24,7 @@ class CuratedPeopleRow extends StatelessWidget { @override Widget build(BuildContext context) { - const imageSize = 80.0; + const imageSize = 70.0; // Guard empty [content] if (content.isEmpty) { @@ -82,11 +83,11 @@ class CuratedPeopleRow extends StatelessWidget { child: Padding( padding: const EdgeInsets.only(top: 8.0), child: Text( - "Add name", + "exif_bottom_sheet_person_add_person", style: context.textTheme.labelLarge?.copyWith( color: context.primaryColor, ), - ), + ).tr(), ), ) else From 0d5584ecbb507332d95facc3c3e87f3f51222e8e Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 20 Mar 2024 09:28:19 -0500 Subject: [PATCH 015/152] fix(web): shift-select again (#8098) --- web/src/lib/components/photos-page/asset-grid.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte index 8822e1e0b..5892442df 100644 --- a/web/src/lib/components/photos-page/asset-grid.svelte +++ b/web/src/lib/components/photos-page/asset-grid.svelte @@ -218,7 +218,7 @@ return; } - if (matchesShortcut(event, { key: 'Shift', shift: true })) { + if (matchesShortcut(event, { key: 'Shift', shift: false })) { event.preventDefault(); shiftKeyIsDown = false; } From 0b078c9f9913b057486b033a8a9114b02428f35c Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 20 Mar 2024 09:46:31 -0500 Subject: [PATCH 016/152] fix(web): Share button visible when viewing album has only shared link (#8100) --- web/src/routes/(user)/albums/[albumId]/+page.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/routes/(user)/albums/[albumId]/+page.svelte b/web/src/routes/(user)/albums/[albumId]/+page.svelte index 0d171d5a4..2f74a7872 100644 --- a/web/src/routes/(user)/albums/[albumId]/+page.svelte +++ b/web/src/routes/(user)/albums/[albumId]/+page.svelte @@ -148,7 +148,7 @@ backUrl = url || AppRoute.ALBUMS; - if (backUrl === AppRoute.SHARING && album.sharedUsers.length === 0) { + if (backUrl === AppRoute.SHARING && album.sharedUsers.length === 0 && !album.hasSharedLink) { isCreatingSharedAlbum = true; } }); From 5b314ffd46f0438f3a60e241240d435c8598e8cf Mon Sep 17 00:00:00 2001 From: Alex The Bot Date: Wed, 20 Mar 2024 14:50:57 +0000 Subject: [PATCH 017/152] Version v1.99.0 --- cli/package-lock.json | 2 +- e2e/package-lock.json | 6 +++--- e2e/package.json | 2 +- machine-learning/pyproject.toml | 2 +- mobile/android/fastlane/Fastfile | 4 ++-- mobile/ios/fastlane/Fastfile | 2 +- mobile/openapi/README.md | 2 +- mobile/pubspec.yaml | 2 +- open-api/immich-openapi-specs.json | 2 +- open-api/typescript-sdk/package-lock.json | 4 ++-- open-api/typescript-sdk/package.json | 2 +- open-api/typescript-sdk/src/fetch-client.ts | 2 +- server/package-lock.json | 4 ++-- server/package.json | 2 +- web/package-lock.json | 6 +++--- web/package.json | 2 +- 16 files changed, 23 insertions(+), 23 deletions(-) diff --git a/cli/package-lock.json b/cli/package-lock.json index 69be80132..8646b6b37 100644 --- a/cli/package-lock.json +++ b/cli/package-lock.json @@ -47,7 +47,7 @@ }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.98.2", + "version": "1.99.0", "dev": true, "license": "GNU Affero General Public License version 3", "dependencies": { diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 1b6d8ad19..083964cb6 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -1,12 +1,12 @@ { "name": "immich-e2e", - "version": "1.98.2", + "version": "1.99.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immich-e2e", - "version": "1.98.2", + "version": "1.99.0", "license": "GNU Affero General Public License version 3", "devDependencies": { "@immich/cli": "file:../cli", @@ -80,7 +80,7 @@ }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.98.2", + "version": "1.99.0", "dev": true, "license": "GNU Affero General Public License version 3", "dependencies": { diff --git a/e2e/package.json b/e2e/package.json index 99d3a91cd..fef02501f 100644 --- a/e2e/package.json +++ b/e2e/package.json @@ -1,6 +1,6 @@ { "name": "immich-e2e", - "version": "1.98.2", + "version": "1.99.0", "description": "", "main": "index.js", "type": "module", diff --git a/machine-learning/pyproject.toml b/machine-learning/pyproject.toml index c0e549af5..6c55ada1c 100644 --- a/machine-learning/pyproject.toml +++ b/machine-learning/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "machine-learning" -version = "1.98.2" +version = "1.99.0" description = "" authors = ["Hau Tran "] readme = "README.md" diff --git a/mobile/android/fastlane/Fastfile b/mobile/android/fastlane/Fastfile index a11d60267..c046ee56a 100644 --- a/mobile/android/fastlane/Fastfile +++ b/mobile/android/fastlane/Fastfile @@ -35,8 +35,8 @@ platform :android do task: 'bundle', build_type: 'Release', properties: { - "android.injected.version.code" => 128, - "android.injected.version.name" => "1.98.2", + "android.injected.version.code" => 129, + "android.injected.version.name" => "1.99.0", } ) upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab') diff --git a/mobile/ios/fastlane/Fastfile b/mobile/ios/fastlane/Fastfile index 00cbeb8ac..a2ad017af 100644 --- a/mobile/ios/fastlane/Fastfile +++ b/mobile/ios/fastlane/Fastfile @@ -19,7 +19,7 @@ platform :ios do desc "iOS Beta" lane :beta do increment_version_number( - version_number: "1.98.2" + version_number: "1.99.0" ) increment_build_number( build_number: latest_testflight_build_number + 1, diff --git a/mobile/openapi/README.md b/mobile/openapi/README.md index 938293568..3b605abfc 100644 --- a/mobile/openapi/README.md +++ b/mobile/openapi/README.md @@ -3,7 +3,7 @@ Immich API This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project: -- API version: 1.98.2 +- API version: 1.99.0 - Build package: org.openapitools.codegen.languages.DartClientCodegen ## Requirements diff --git a/mobile/pubspec.yaml b/mobile/pubspec.yaml index a566d1aa9..785d338da 100644 --- a/mobile/pubspec.yaml +++ b/mobile/pubspec.yaml @@ -2,7 +2,7 @@ name: immich_mobile description: Immich - selfhosted backup media file on mobile phone publish_to: 'none' -version: 1.98.2+128 +version: 1.99.0+129 isar_version: &isar_version 3.1.0+1 environment: diff --git a/open-api/immich-openapi-specs.json b/open-api/immich-openapi-specs.json index f50abdffc..d04b91aa8 100644 --- a/open-api/immich-openapi-specs.json +++ b/open-api/immich-openapi-specs.json @@ -6538,7 +6538,7 @@ "info": { "title": "Immich", "description": "Immich API", - "version": "1.98.2", + "version": "1.99.0", "contact": {} }, "tags": [], diff --git a/open-api/typescript-sdk/package-lock.json b/open-api/typescript-sdk/package-lock.json index 0f1926996..165fb98e9 100644 --- a/open-api/typescript-sdk/package-lock.json +++ b/open-api/typescript-sdk/package-lock.json @@ -1,12 +1,12 @@ { "name": "@immich/sdk", - "version": "1.98.2", + "version": "1.99.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@immich/sdk", - "version": "1.98.2", + "version": "1.99.0", "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" diff --git a/open-api/typescript-sdk/package.json b/open-api/typescript-sdk/package.json index 4b04ee7c2..c9a7b930d 100644 --- a/open-api/typescript-sdk/package.json +++ b/open-api/typescript-sdk/package.json @@ -1,6 +1,6 @@ { "name": "@immich/sdk", - "version": "1.98.2", + "version": "1.99.0", "description": "Auto-generated TypeScript SDK for the Immich API", "type": "module", "main": "./build/index.js", diff --git a/open-api/typescript-sdk/src/fetch-client.ts b/open-api/typescript-sdk/src/fetch-client.ts index 00434aaba..883456403 100644 --- a/open-api/typescript-sdk/src/fetch-client.ts +++ b/open-api/typescript-sdk/src/fetch-client.ts @@ -1,6 +1,6 @@ /** * Immich - * 1.98.2 + * 1.99.0 * DO NOT MODIFY - This file has been generated using oazapfts. * See https://www.npmjs.com/package/oazapfts */ diff --git a/server/package-lock.json b/server/package-lock.json index eecc75bb2..8d623c509 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -1,12 +1,12 @@ { "name": "immich", - "version": "1.98.2", + "version": "1.99.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "immich", - "version": "1.98.2", + "version": "1.99.0", "license": "GNU Affero General Public License version 3", "dependencies": { "@babel/runtime": "^7.22.11", diff --git a/server/package.json b/server/package.json index d60f67a1f..3138db565 100644 --- a/server/package.json +++ b/server/package.json @@ -1,6 +1,6 @@ { "name": "immich", - "version": "1.98.2", + "version": "1.99.0", "description": "", "author": "", "private": true, diff --git a/web/package-lock.json b/web/package-lock.json index 899ec9156..c1af8d11f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1,12 +1,12 @@ { "name": "immich-web", - "version": "1.98.2", + "version": "1.99.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "immich-web", - "version": "1.98.2", + "version": "1.99.0", "license": "GNU Affero General Public License version 3", "dependencies": { "@immich/sdk": "file:../open-api/typescript-sdk", @@ -63,7 +63,7 @@ }, "../open-api/typescript-sdk": { "name": "@immich/sdk", - "version": "1.98.2", + "version": "1.99.0", "license": "GNU Affero General Public License version 3", "dependencies": { "@oazapfts/runtime": "^1.0.2" diff --git a/web/package.json b/web/package.json index 4714b09b0..d151faaa9 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "immich-web", - "version": "1.98.2", + "version": "1.99.0", "license": "GNU Affero General Public License version 3", "scripts": { "dev": "vite dev --host 0.0.0.0 --port 3000", From 591a641d8d83e4a3c0d7fb0028b671e80a93b653 Mon Sep 17 00:00:00 2001 From: Alex Date: Wed, 20 Mar 2024 10:00:35 -0500 Subject: [PATCH 018/152] chore: post release tasks --- mobile/android/fastlane/report.xml | 6 +++--- mobile/ios/Runner.xcodeproj/project.pbxproj | 6 +++--- mobile/ios/Runner/Info.plist | 4 ++-- mobile/ios/fastlane/report.xml | 12 ++++++------ 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/mobile/android/fastlane/report.xml b/mobile/android/fastlane/report.xml index 0dcf80996..4afb67dd1 100644 --- a/mobile/android/fastlane/report.xml +++ b/mobile/android/fastlane/report.xml @@ -5,17 +5,17 @@ - + - + - + diff --git a/mobile/ios/Runner.xcodeproj/project.pbxproj b/mobile/ios/Runner.xcodeproj/project.pbxproj index 5f44646ec..d6056f3f1 100644 --- a/mobile/ios/Runner.xcodeproj/project.pbxproj +++ b/mobile/ios/Runner.xcodeproj/project.pbxproj @@ -383,7 +383,7 @@ CODE_SIGN_ENTITLEMENTS = Runner/RunnerProfile.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 144; + CURRENT_PROJECT_VERSION = 145; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -525,7 +525,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 144; + CURRENT_PROJECT_VERSION = 145; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; @@ -553,7 +553,7 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 144; + CURRENT_PROJECT_VERSION = 145; DEVELOPMENT_TEAM = 2F67MQ8R79; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; diff --git a/mobile/ios/Runner/Info.plist b/mobile/ios/Runner/Info.plist index a750a446b..9570af99d 100644 --- a/mobile/ios/Runner/Info.plist +++ b/mobile/ios/Runner/Info.plist @@ -55,11 +55,11 @@ CFBundlePackageType APPL CFBundleShortVersionString - 1.98.2 + 1.99.0 CFBundleSignature ???? CFBundleVersion - 144 + 145 FLTEnableImpeller ITSAppUsesNonExemptEncryption diff --git a/mobile/ios/fastlane/report.xml b/mobile/ios/fastlane/report.xml index f1e83434b..2b91e3faf 100644 --- a/mobile/ios/fastlane/report.xml +++ b/mobile/ios/fastlane/report.xml @@ -5,32 +5,32 @@ - + - + - + - + - + - + From 30f499cf2e68c5bdfde866193523dbb1232ae3b4 Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Wed, 20 Mar 2024 19:32:04 +0100 Subject: [PATCH 019/152] chore(server): use absolute import paths (#8080) update server to use absolute import paths --- .vscode/settings.json | 30 +++++ server/.eslintrc.js | 1 + server/e2e/client/asset-api.ts | 2 +- server/e2e/client/auth-api.ts | 5 +- server/e2e/client/index.ts | 6 +- server/e2e/client/library-api.ts | 2 +- server/e2e/jobs/jest-e2e.json | 6 +- .../jobs/specs/library-watcher.e2e-spec.ts | 12 +- server/e2e/jobs/specs/library.e2e-spec.ts | 20 ++- server/package.json | 10 +- server/src/domain/access/access.core.ts | 8 +- server/src/domain/access/index.ts | 1 - server/src/domain/activity/activity.dto.ts | 6 +- .../src/domain/activity/activity.service.ts | 11 +- server/src/domain/activity/activity.spec.ts | 13 +- server/src/domain/activity/index.ts | 2 - .../domain/album/album-response.dto.spec.ts | 4 +- server/src/domain/album/album-response.dto.ts | 10 +- server/src/domain/album/album.service.spec.ts | 30 ++--- server/src/domain/album/album.service.ts | 34 ++--- .../domain/album/dto/album-add-users.dto.ts | 2 +- .../src/domain/album/dto/album-create.dto.ts | 2 +- .../src/domain/album/dto/album-update.dto.ts | 4 +- server/src/domain/album/dto/album.dto.ts | 2 +- server/src/domain/album/dto/get-albums.dto.ts | 2 +- server/src/domain/album/dto/index.ts | 5 - server/src/domain/album/index.ts | 3 - server/src/domain/api-key/api-key.dto.ts | 2 +- .../domain/api-key/api-key.service.spec.ts | 10 +- server/src/domain/api-key/api-key.service.ts | 9 +- server/src/domain/api-key/index.ts | 2 - server/src/domain/asset/asset.service.spec.ts | 65 ++++------ server/src/domain/asset/asset.service.ts | 71 +++++----- server/src/domain/asset/dto/asset-ids.dto.ts | 2 +- .../src/domain/asset/dto/asset-stack.dto.ts | 2 +- .../domain/asset/dto/asset-statistics.dto.ts | 6 +- server/src/domain/asset/dto/asset.dto.ts | 4 +- server/src/domain/asset/dto/index.ts | 7 - server/src/domain/asset/dto/map-marker.dto.ts | 2 +- .../src/domain/asset/dto/time-bucket.dto.ts | 6 +- server/src/domain/asset/index.ts | 3 - .../response-dto/asset-ids-response.dto.ts | 2 +- .../asset/response-dto/asset-response.dto.ts | 15 ++- .../asset/response-dto/exif-response.dto.ts | 2 +- server/src/domain/asset/response-dto/index.ts | 6 - .../response-dto/smart-info-response.dto.ts | 2 +- server/src/domain/audit/audit.dto.ts | 5 +- server/src/domain/audit/audit.service.spec.ts | 41 +++--- server/src/domain/audit/audit.service.ts | 37 +++--- server/src/domain/audit/index.ts | 2 - server/src/domain/auth/auth.dto.ts | 5 +- server/src/domain/auth/auth.service.spec.ts | 56 ++++---- server/src/domain/auth/auth.service.ts | 36 +++--- server/src/domain/auth/index.ts | 3 - .../domain/database/database.service.spec.ts | 15 +-- .../src/domain/database/database.service.ts | 6 +- server/src/domain/database/index.ts | 1 - server/src/domain/domain.config.ts | 2 +- server/src/domain/domain.constant.spec.ts | 2 +- server/src/domain/domain.constant.ts | 2 +- server/src/domain/domain.module.ts | 50 +++---- server/src/domain/domain.util.ts | 2 +- server/src/domain/download/download.dto.ts | 2 +- .../domain/download/download.service.spec.ts | 22 ++-- .../src/domain/download/download.service.ts | 18 +-- server/src/domain/download/index.ts | 2 - server/src/domain/index.ts | 30 ----- server/src/domain/job/index.ts | 4 - server/src/domain/job/job.dto.ts | 4 +- server/src/domain/job/job.service.spec.ts | 37 +++--- server/src/domain/job/job.service.ts | 29 ++--- server/src/domain/library/index.ts | 2 - server/src/domain/library/library.dto.ts | 4 +- .../domain/library/library.service.spec.ts | 77 +++++------ server/src/domain/library/library.service.ts | 46 +++---- server/src/domain/media/index.ts | 2 - server/src/domain/media/media.service.spec.ts | 58 ++++----- server/src/domain/media/media.service.ts | 67 +++++----- server/src/domain/media/media.util.ts | 13 +- server/src/domain/metadata/index.ts | 1 - .../domain/metadata/metadata.service.spec.ts | 70 +++++----- .../src/domain/metadata/metadata.service.ts | 45 +++---- server/src/domain/partner/index.ts | 2 - server/src/domain/partner/partner.dto.ts | 2 +- .../domain/partner/partner.service.spec.ts | 13 +- server/src/domain/partner/partner.service.ts | 13 +- server/src/domain/person/index.ts | 2 - server/src/domain/person/person.dto.ts | 7 +- .../src/domain/person/person.service.spec.ts | 71 +++++----- server/src/domain/person/person.service.ts | 61 ++++----- .../repositories/activity.repository.ts | 4 +- .../domain/repositories/album.repository.ts | 2 +- .../domain/repositories/api-key.repository.ts | 2 +- .../repositories/asset-stack.repository.ts | 2 +- .../domain/repositories/asset.repository.ts | 10 +- .../domain/repositories/audit.repository.ts | 2 +- .../repositories/communication.repository.ts | 5 +- .../repositories/database.repository.ts | 2 +- server/src/domain/repositories/index.ts | 27 ---- .../src/domain/repositories/job.repository.ts | 5 +- .../domain/repositories/library.repository.ts | 4 +- .../machine-learning.repository.ts | 2 +- .../domain/repositories/media.repository.ts | 2 +- .../domain/repositories/move.repository.ts | 2 +- .../domain/repositories/partner.repository.ts | 2 +- .../domain/repositories/person.repository.ts | 6 +- .../domain/repositories/search.repository.ts | 7 +- .../repositories/shared-link.repository.ts | 2 +- .../domain/repositories/storage.repository.ts | 2 +- .../repositories/system-config.repository.ts | 2 +- .../system-metadata.repository.ts | 2 +- .../src/domain/repositories/tag.repository.ts | 3 +- .../repositories/user-token.repository.ts | 2 +- .../domain/repositories/user.repository.ts | 2 +- server/src/domain/search/dto/index.ts | 1 - .../search/dto/search-suggestion.dto.ts | 2 +- server/src/domain/search/dto/search.dto.ts | 6 +- server/src/domain/search/index.ts | 3 - .../src/domain/search/response-dto/index.ts | 2 - .../search-explore.response.dto.ts | 2 +- .../response-dto/search-response.dto.ts | 4 +- .../src/domain/search/search.service.spec.ts | 46 +++---- server/src/domain/search/search.service.ts | 35 +++-- server/src/domain/server-info/index.ts | 2 - .../src/domain/server-info/server-info.dto.ts | 5 +- .../server-info/server-info.service.spec.ts | 34 +++-- .../domain/server-info/server-info.service.ts | 30 ++--- server/src/domain/shared-link/index.ts | 3 - .../shared-link/shared-link-response.dto.ts | 6 +- .../src/domain/shared-link/shared-link.dto.ts | 4 +- .../shared-link/shared-link.service.spec.ts | 27 ++-- .../domain/shared-link/shared-link.service.ts | 24 ++-- server/src/domain/smart-info/dto/index.ts | 1 - .../domain/smart-info/dto/model-config.dto.ts | 4 +- server/src/domain/smart-info/index.ts | 2 - .../smart-info/smart-info.service.spec.ts | 40 +++--- .../domain/smart-info/smart-info.service.ts | 26 ++-- server/src/domain/storage-template/index.ts | 1 - .../storage-template.service.spec.ts | 54 ++++---- .../storage-template.service.ts | 47 ++++--- server/src/domain/storage/index.ts | 2 - server/src/domain/storage/storage.core.ts | 28 ++-- .../domain/storage/storage.service.spec.ts | 6 +- server/src/domain/storage/storage.service.ts | 9 +- server/src/domain/system-config/dto/index.ts | 8 -- .../dto/system-config-ffmpeg.dto.ts | 11 +- .../dto/system-config-job.dto.ts | 2 +- .../dto/system-config-library.dto.ts | 2 +- .../dto/system-config-logging.dto.ts | 4 +- .../dto/system-config-machine-learning.dto.ts | 4 +- .../dto/system-config-map.dto.ts | 2 +- .../system-config-new-version-check.dto.ts | 2 +- .../dto/system-config-oauth.dto.ts | 2 +- .../dto/system-config-password-login.dto.ts | 2 +- .../system-config-reverse-geocoding.dto.ts | 2 +- .../dto/system-config-storage-template.dto.ts | 2 +- .../dto/system-config-thumbnail.dto.ts | 2 +- .../dto/system-config-trash.dto.ts | 2 +- .../system-config/dto/system-config.dto.ts | 34 ++--- server/src/domain/system-config/index.ts | 5 - .../system-config/response-dto/index.ts | 1 - .../system-config/system-config.core.ts | 26 ++-- .../system-config.service.spec.ts | 21 +-- .../system-config/system-config.service.ts | 18 +-- server/src/domain/tag/index.ts | 3 - server/src/domain/tag/tag-response.dto.ts | 2 +- server/src/domain/tag/tag.dto.ts | 4 +- server/src/domain/tag/tag.service.spec.ts | 13 +- server/src/domain/tag/tag.service.ts | 12 +- server/src/domain/trash/index.ts | 1 - server/src/domain/trash/trash.service.spec.ts | 23 ++-- server/src/domain/trash/trash.service.ts | 21 ++- .../user/dto/create-profile-image.dto.ts | 2 +- .../domain/user/dto/create-user.dto.spec.ts | 2 +- server/src/domain/user/dto/create-user.dto.ts | 2 +- server/src/domain/user/dto/delete-user.dto.ts | 2 +- server/src/domain/user/dto/index.ts | 4 - .../domain/user/dto/update-user.dto.spec.ts | 2 +- server/src/domain/user/dto/update-user.dto.ts | 4 +- server/src/domain/user/index.ts | 4 - server/src/domain/user/response-dto/index.ts | 2 - .../user/response-dto/user-response.dto.ts | 2 +- server/src/domain/user/user.core.ts | 9 +- server/src/domain/user/user.service.spec.ts | 50 ++++--- server/src/domain/user/user.service.ts | 43 +++--- server/src/immich-admin/app.module.ts | 15 ++- .../commands/list-users.command.ts | 4 +- .../src/immich-admin/commands/oauth-login.ts | 2 +- .../immich-admin/commands/password-login.ts | 2 +- .../commands/reset-admin-password.command.ts | 3 +- server/src/immich-admin/constants.ts | 4 +- server/src/immich-admin/main.ts | 4 +- .../immich/api-v1/asset/asset-repository.ts | 15 ++- .../immich/api-v1/asset/asset.controller.ts | 42 +++--- .../immich/api-v1/asset/asset.service.spec.ts | 46 +++---- .../src/immich/api-v1/asset/asset.service.ts | 63 +++++---- .../api-v1/asset/dto/asset-search.dto.ts | 2 +- .../dto/check-existing-assets.dto.spec.ts | 2 +- .../api-v1/asset/dto/create-asset.dto.ts | 3 +- .../asset/dto/get-asset-thumbnail.dto.ts | 2 +- .../immich/api-v1/asset/dto/serve-file.dto.ts | 2 +- server/src/immich/app.guard.ts | 6 +- server/src/immich/app.module.ts | 67 +++++----- server/src/immich/app.service.ts | 23 ++-- server/src/immich/app.utils.ts | 18 +-- .../immich/controllers/activity.controller.ts | 30 ++--- .../immich/controllers/album.controller.ts | 32 ++--- .../immich/controllers/api-key.controller.ts | 14 +- .../src/immich/controllers/app.controller.ts | 4 +- .../immich/controllers/asset.controller.ts | 49 +++---- .../immich/controllers/audit.controller.ts | 12 +- .../src/immich/controllers/auth.controller.ts | 34 +++-- .../immich/controllers/download.controller.ts | 11 +- .../src/immich/controllers/face.controller.ts | 8 +- server/src/immich/controllers/index.ts | 21 --- .../src/immich/controllers/job.controller.ts | 5 +- .../immich/controllers/library.controller.ts | 34 ++--- .../immich/controllers/oauth.controller.ts | 15 +-- .../immich/controllers/partner.controller.ts | 10 +- .../immich/controllers/person.controller.ts | 22 ++-- .../immich/controllers/search.controller.ts | 32 ++--- .../controllers/server-info.controller.ts | 10 +- .../controllers/shared-link.controller.ts | 22 ++-- .../controllers/system-config.controller.ts | 8 +- .../src/immich/controllers/tag.controller.ts | 21 ++- .../immich/controllers/trash.controller.ts | 6 +- .../src/immich/controllers/user.controller.ts | 30 ++--- server/src/immich/index.ts | 2 - .../immich/interceptors/error.interceptor.ts | 6 +- .../interceptors/file-upload.interceptor.ts | 6 +- server/src/immich/interceptors/index.ts | 2 - server/src/immich/main.ts | 15 ++- server/src/infra/database.config.ts | 2 +- server/src/infra/entities/activity.entity.ts | 6 +- server/src/infra/entities/album.entity.ts | 6 +- server/src/infra/entities/api-key.entity.ts | 2 +- .../src/infra/entities/asset-face.entity.ts | 4 +- .../infra/entities/asset-job-status.entity.ts | 2 +- .../src/infra/entities/asset-stack.entity.ts | 2 +- server/src/infra/entities/asset.entity.ts | 22 ++-- server/src/infra/entities/exif.entity.ts | 2 +- server/src/infra/entities/index.ts | 67 ++++------ server/src/infra/entities/library.entity.ts | 4 +- server/src/infra/entities/partner.entity.ts | 3 +- server/src/infra/entities/person.entity.ts | 4 +- .../src/infra/entities/shared-link.entity.ts | 6 +- .../src/infra/entities/smart-info.entity.ts | 2 +- .../src/infra/entities/smart-search.entity.ts | 2 +- .../infra/entities/system-config.entity.ts | 2 +- server/src/infra/entities/tag.entity.ts | 4 +- .../src/infra/entities/user-token.entity.ts | 2 +- server/src/infra/entities/user.entity.ts | 4 +- server/src/infra/index.ts | 4 - server/src/infra/infra.config.ts | 2 +- server/src/infra/infra.module.ts | 122 +++++++++--------- server/src/infra/infra.utils.ts | 16 ++- server/src/infra/instrumentation.ts | 6 +- server/src/infra/logger.ts | 2 +- .../migrations/1700713871511-UsePgVectors.ts | 12 +- .../1700713994428-AddCLIPEmbeddingIndex.ts | 4 +- .../1700714033632-AddFaceEmbeddingIndex.ts | 4 +- .../infra/repositories/access.repository.ts | 28 ++-- .../infra/repositories/activity.repository.ts | 8 +- .../infra/repositories/album.repository.ts | 21 ++- .../infra/repositories/api-key.repository.ts | 8 +- .../repositories/asset-stack.repository.ts | 6 +- .../infra/repositories/asset.repository.ts | 36 ++++-- .../infra/repositories/audit.repository.ts | 6 +- .../repositories/communication.repository.ts | 22 ++-- .../infra/repositories/crypto.repository.ts | 4 +- .../infra/repositories/database.repository.ts | 19 ++- .../repositories/filesystem.provider.spec.ts | 4 +- .../infra/repositories/filesystem.provider.ts | 24 ++-- server/src/infra/repositories/index.ts | 27 ---- .../src/infra/repositories/job.repository.ts | 24 ++-- .../infra/repositories/library.repository.ts | 9 +- .../machine-learning.repository.ts | 12 +- .../infra/repositories/media.repository.ts | 20 +-- .../infra/repositories/metadata.repository.ts | 32 +++-- .../src/infra/repositories/move.repository.ts | 8 +- .../infra/repositories/partner.repository.ts | 6 +- .../infra/repositories/person.repository.ts | 19 +-- .../infra/repositories/search.repository.ts | 39 +++--- .../repositories/server-info.repository.ts | 4 +- .../repositories/shared-link.repository.ts | 8 +- .../repositories/system-config.repository.ts | 10 +- .../system-metadata.repository.ts | 6 +- .../src/infra/repositories/tag.repository.ts | 7 +- .../repositories/user-token.repository.ts | 8 +- .../src/infra/repositories/user.repository.ts | 14 +- server/src/infra/sql-generator/index.ts | 44 +++---- .../src/infra/subscribers/audit.subscriber.ts | 4 +- server/src/main.ts | 6 +- server/src/microservices/app.service.ts | 34 +++-- server/src/microservices/main.ts | 10 +- .../src/microservices/microservices.module.ts | 6 +- .../utils/exif/coordinates.spec.ts | 2 +- .../microservices/utils/exif/coordinates.ts | 2 +- .../src/microservices/utils/numbers.spec.ts | 2 +- server/src/test-utils/utils.ts | 18 ++- server/test/fixtures/activity.stub.ts | 10 +- server/test/fixtures/album.stub.ts | 8 +- server/test/fixtures/api-key.stub.ts | 6 +- server/test/fixtures/asset.stub.ts | 12 +- server/test/fixtures/audit.stub.ts | 4 +- server/test/fixtures/auth.stub.ts | 6 +- server/test/fixtures/face.stub.ts | 6 +- server/test/fixtures/index.ts | 18 --- server/test/fixtures/library.stub.ts | 7 +- server/test/fixtures/media.stub.ts | 2 +- server/test/fixtures/partner.stub.ts | 4 +- server/test/fixtures/person.stub.ts | 4 +- server/test/fixtures/shared-link.stub.ts | 19 ++- server/test/fixtures/system-config.stub.ts | 2 +- server/test/fixtures/tag.stub.ts | 6 +- server/test/fixtures/user-token.stub.ts | 4 +- server/test/fixtures/user.stub.ts | 4 +- server/test/index.ts | 2 - .../repositories/access.repository.mock.ts | 3 +- .../repositories/activity.repository.mock.ts | 2 +- .../repositories/album.repository.mock.ts | 2 +- .../repositories/api-key.repository.mock.ts | 2 +- .../asset-stack.repository.mock.ts | 2 +- .../repositories/asset.repository.mock.ts | 2 +- .../repositories/audit.repository.mock.ts | 2 +- .../communication.repository.mock.ts | 2 +- .../repositories/crypto.repository.mock.ts | 2 +- .../repositories/database.repository.mock.ts | 3 +- server/test/repositories/index.ts | 26 ---- .../test/repositories/job.repository.mock.ts | 2 +- .../repositories/library.repository.mock.ts | 2 +- .../machine-learning.repository.mock.ts | 2 +- .../repositories/media.repository.mock.ts | 2 +- .../repositories/metadata.repository.mock.ts | 2 +- .../test/repositories/move.repository.mock.ts | 2 +- .../repositories/partner.repository.mock.ts | 2 +- .../repositories/person.repository.mock.ts | 2 +- .../repositories/search.repository.mock.ts | 2 +- .../shared-link.repository.mock.ts | 2 +- .../repositories/storage.repository.mock.ts | 3 +- .../system-config.repository.mock.ts | 3 +- .../system-info.repository.mock.ts | 2 +- .../system-metadata.repository.mock.ts | 2 +- .../test/repositories/tag.repository.mock.ts | 2 +- .../user-token.repository.mock.ts | 2 +- .../test/repositories/user.repository.mock.ts | 3 +- server/tsconfig.json | 18 +-- 347 files changed, 1962 insertions(+), 2274 deletions(-) create mode 100644 .vscode/settings.json delete mode 100644 server/src/domain/access/index.ts delete mode 100644 server/src/domain/activity/index.ts delete mode 100644 server/src/domain/album/dto/index.ts delete mode 100644 server/src/domain/album/index.ts delete mode 100644 server/src/domain/api-key/index.ts delete mode 100644 server/src/domain/asset/dto/index.ts delete mode 100644 server/src/domain/asset/index.ts delete mode 100644 server/src/domain/asset/response-dto/index.ts delete mode 100644 server/src/domain/audit/index.ts delete mode 100644 server/src/domain/auth/index.ts delete mode 100644 server/src/domain/database/index.ts delete mode 100644 server/src/domain/download/index.ts delete mode 100644 server/src/domain/index.ts delete mode 100644 server/src/domain/job/index.ts delete mode 100644 server/src/domain/library/index.ts delete mode 100644 server/src/domain/media/index.ts delete mode 100644 server/src/domain/metadata/index.ts delete mode 100644 server/src/domain/partner/index.ts delete mode 100644 server/src/domain/person/index.ts delete mode 100644 server/src/domain/repositories/index.ts delete mode 100644 server/src/domain/search/dto/index.ts delete mode 100644 server/src/domain/search/index.ts delete mode 100644 server/src/domain/search/response-dto/index.ts delete mode 100644 server/src/domain/server-info/index.ts delete mode 100644 server/src/domain/shared-link/index.ts delete mode 100644 server/src/domain/smart-info/dto/index.ts delete mode 100644 server/src/domain/smart-info/index.ts delete mode 100644 server/src/domain/storage-template/index.ts delete mode 100644 server/src/domain/storage/index.ts delete mode 100644 server/src/domain/system-config/dto/index.ts delete mode 100644 server/src/domain/system-config/index.ts delete mode 100644 server/src/domain/system-config/response-dto/index.ts delete mode 100644 server/src/domain/tag/index.ts delete mode 100644 server/src/domain/trash/index.ts delete mode 100644 server/src/domain/user/dto/index.ts delete mode 100644 server/src/domain/user/index.ts delete mode 100644 server/src/domain/user/response-dto/index.ts delete mode 100644 server/src/immich/controllers/index.ts delete mode 100644 server/src/immich/index.ts delete mode 100644 server/src/immich/interceptors/index.ts delete mode 100644 server/src/infra/index.ts delete mode 100644 server/src/infra/repositories/index.ts delete mode 100644 server/test/fixtures/index.ts delete mode 100644 server/test/index.ts delete mode 100644 server/test/repositories/index.ts diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 000000000..eae6e1a16 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,30 @@ +{ + "editor.formatOnSave": true, + "[javascript][typescript][css]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.tabSize": 2, + "editor.formatOnSave": true + }, + "[svelte]": { + "editor.defaultFormatter": "svelte.svelte-vscode", + "editor.tabSize": 2 + }, + "svelte.enable-ts-plugin": true, + "eslint.validate": [ + "javascript", + "svelte" + ], + "typescript.preferences.importModuleSpecifier": "non-relative", + "[dart]": { + "editor.formatOnSave": true, + "editor.selectionHighlight": false, + "editor.suggest.snippetsPreventQuickSuggestions": false, + "editor.suggestSelection": "first", + "editor.tabCompletion": "onlySnippets", + "editor.wordBasedSuggestions": "off", + "editor.defaultFormatter": "Dart-Code.dart-code" + }, + "cSpell.words": [ + "immich" + ], +} \ No newline at end of file diff --git a/server/.eslintrc.js b/server/.eslintrc.js index 3673add3c..75138ff23 100644 --- a/server/.eslintrc.js +++ b/server/.eslintrc.js @@ -33,5 +33,6 @@ module.exports = { '@typescript-eslint/require-await': 'error', curly: 2, 'prettier/prettier': 0, + 'no-restricted-imports': ['error', { patterns: [{ group: ['.*'], message: 'Relative imports are not allowed.' }] }], }, }; diff --git a/server/e2e/client/asset-api.ts b/server/e2e/client/asset-api.ts index 63d439586..8f30e1f4a 100644 --- a/server/e2e/client/asset-api.ts +++ b/server/e2e/client/asset-api.ts @@ -1,4 +1,4 @@ -import { AssetResponseDto } from '@app/domain'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; import request from 'supertest'; export const assetApi = { diff --git a/server/e2e/client/auth-api.ts b/server/e2e/client/auth-api.ts index e89e6d057..46b21fb98 100644 --- a/server/e2e/client/auth-api.ts +++ b/server/e2e/client/auth-api.ts @@ -1,6 +1,7 @@ -import { LoginResponseDto, UserResponseDto } from '@app/domain'; -import { adminSignupStub, loginResponseStub, loginStub } from '@test'; +import { LoginResponseDto } from 'src/domain/auth/auth.dto'; +import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; import request from 'supertest'; +import { adminSignupStub, loginResponseStub, loginStub } from 'test/fixtures/auth.stub'; export const authApi = { adminSignUp: async (server: any) => { diff --git a/server/e2e/client/index.ts b/server/e2e/client/index.ts index b4aa2a141..41418ddcc 100644 --- a/server/e2e/client/index.ts +++ b/server/e2e/client/index.ts @@ -1,6 +1,6 @@ -import { assetApi } from './asset-api'; -import { authApi } from './auth-api'; -import { libraryApi } from './library-api'; +import { assetApi } from 'e2e/client/asset-api'; +import { authApi } from 'e2e/client/auth-api'; +import { libraryApi } from 'e2e/client/library-api'; export const api = { authApi, diff --git a/server/e2e/client/library-api.ts b/server/e2e/client/library-api.ts index 070683eb0..90b1b7451 100644 --- a/server/e2e/client/library-api.ts +++ b/server/e2e/client/library-api.ts @@ -1,4 +1,4 @@ -import { CreateLibraryDto, LibraryResponseDto, ScanLibraryDto } from '@app/domain'; +import { CreateLibraryDto, LibraryResponseDto, ScanLibraryDto } from 'src/domain/library/library.dto'; import request from 'supertest'; export const libraryApi = { diff --git a/server/e2e/jobs/jest-e2e.json b/server/e2e/jobs/jest-e2e.json index 333174c5a..b9a238d83 100644 --- a/server/e2e/jobs/jest-e2e.json +++ b/server/e2e/jobs/jest-e2e.json @@ -16,9 +16,7 @@ ], "coverageDirectory": "./coverage", "moduleNameMapper": { - "^@test(|/.*)$": "/test/$1", - "^@app/immich(|/.*)$": "/src/immich/$1", - "^@app/infra(|/.*)$": "/src/infra/$1", - "^@app/domain(|/.*)$": "/src/domain/$1" + "^test(|/.*)$": "/test/$1", + "^src(|/.*)$": "/src/$1" } } diff --git a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts index 5f05d736b..50d29f8ff 100644 --- a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts +++ b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts @@ -1,15 +1,19 @@ -import { LibraryResponseDto, LibraryService, LoginResponseDto, StorageEventType } from '@app/domain'; -import { AssetType, LibraryType } from '@app/infra/entities'; +import { api } from 'e2e/client'; import fs from 'node:fs/promises'; import path from 'node:path'; +import { LoginResponseDto } from 'src/domain/auth/auth.dto'; +import { LibraryResponseDto } from 'src/domain/library/library.dto'; +import { LibraryService } from 'src/domain/library/library.service'; +import { StorageEventType } from 'src/domain/repositories/storage.repository'; +import { AssetType } from 'src/infra/entities/asset.entity'; +import { LibraryType } from 'src/infra/entities/library.entity'; import { IMMICH_TEST_ASSET_PATH, IMMICH_TEST_ASSET_TEMP_PATH, restoreTempFolder, testApp, waitForEvent, -} from '../../../src/test-utils/utils'; -import { api } from '../../client'; +} from 'src/test-utils/utils'; describe(`Library watcher (e2e)`, () => { let server: any; diff --git a/server/e2e/jobs/specs/library.e2e-spec.ts b/server/e2e/jobs/specs/library.e2e-spec.ts index 75411e8fa..24d7a620b 100644 --- a/server/e2e/jobs/specs/library.e2e-spec.ts +++ b/server/e2e/jobs/specs/library.e2e-spec.ts @@ -1,17 +1,13 @@ -import { LoginResponseDto } from '@app/domain'; -import { LibraryController } from '@app/immich'; -import { LibraryType } from '@app/infra/entities'; -import { errorStub, uuidStub } from '@test/fixtures'; -import * as fs from 'node:fs'; +import { api } from 'e2e/client'; +import fs from 'node:fs'; +import { LoginResponseDto } from 'src/domain/auth/auth.dto'; +import { LibraryController } from 'src/immich/controllers/library.controller'; +import { LibraryType } from 'src/infra/entities/library.entity'; +import { IMMICH_TEST_ASSET_PATH, IMMICH_TEST_ASSET_TEMP_PATH, restoreTempFolder, testApp } from 'src/test-utils/utils'; import request from 'supertest'; +import { errorStub } from 'test/fixtures/error.stub'; +import { uuidStub } from 'test/fixtures/uuid.stub'; import { utimes } from 'utimes'; -import { - IMMICH_TEST_ASSET_PATH, - IMMICH_TEST_ASSET_TEMP_PATH, - restoreTempFolder, - testApp, -} from '../../../src/test-utils/utils'; -import { api } from '../../client'; describe(`${LibraryController.name} (e2e)`, () => { let server: any; diff --git a/server/package.json b/server/package.json index 3138db565..5aede827b 100644 --- a/server/package.json +++ b/server/package.json @@ -155,16 +155,14 @@ "./src/domain/": { "branches": 75, "functions": 80, - "lines": 90, - "statements": 90 + "lines": 85, + "statements": 85 } }, "testEnvironment": "node", "moduleNameMapper": { - "^@test(|/.*)$": "/test/$1", - "^@app/immich(|/.*)$": "/src/immich/$1", - "^@app/infra(|/.*)$": "/src/infra/$1", - "^@app/domain(|/.*)$": "/src/domain/$1" + "^test(|/.*)$": "/test/$1", + "^src(|/.*)$": "/src/$1" }, "globalSetup": "/test/global-setup.js" }, diff --git a/server/src/domain/access/access.core.ts b/server/src/domain/access/access.core.ts index 40b01de1d..a51412856 100644 --- a/server/src/domain/access/access.core.ts +++ b/server/src/domain/access/access.core.ts @@ -1,8 +1,8 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; -import { SharedLinkEntity } from '../../infra/entities'; -import { AuthDto } from '../auth'; -import { setDifference, setIsEqual, setUnion } from '../domain.util'; -import { IAccessRepository } from '../repositories'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { setDifference, setIsEqual, setUnion } from 'src/domain/domain.util'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; export enum Permission { ACTIVITY_CREATE = 'activity.create', diff --git a/server/src/domain/access/index.ts b/server/src/domain/access/index.ts deleted file mode 100644 index 80ae0c534..000000000 --- a/server/src/domain/access/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './access.core'; diff --git a/server/src/domain/activity/activity.dto.ts b/server/src/domain/activity/activity.dto.ts index a5a5bd3df..627a06c42 100644 --- a/server/src/domain/activity/activity.dto.ts +++ b/server/src/domain/activity/activity.dto.ts @@ -1,8 +1,8 @@ -import { ActivityEntity } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString, ValidateIf } from 'class-validator'; -import { Optional, ValidateUUID } from '../domain.util'; -import { UserDto, mapSimpleUser } from '../user/response-dto'; +import { Optional, ValidateUUID } from 'src/domain/domain.util'; +import { UserDto, mapSimpleUser } from 'src/domain/user/response-dto/user-response.dto'; +import { ActivityEntity } from 'src/infra/entities/activity.entity'; export enum ReactionType { COMMENT = 'comment', diff --git a/server/src/domain/activity/activity.service.ts b/server/src/domain/activity/activity.service.ts index 69386f561..f8727141c 100644 --- a/server/src/domain/activity/activity.service.ts +++ b/server/src/domain/activity/activity.service.ts @@ -1,8 +1,5 @@ -import { ActivityEntity } from '@app/infra/entities'; import { Inject, Injectable } from '@nestjs/common'; -import { AccessCore, Permission } from '../access'; -import { AuthDto } from '../auth'; -import { IAccessRepository, IActivityRepository } from '../repositories'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; import { ActivityCreateDto, ActivityDto, @@ -13,7 +10,11 @@ import { ReactionLevel, ReactionType, mapActivity, -} from './activity.dto'; +} from 'src/domain/activity/activity.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IActivityRepository } from 'src/domain/repositories/activity.repository'; +import { ActivityEntity } from 'src/infra/entities/activity.entity'; @Injectable() export class ActivityService { diff --git a/server/src/domain/activity/activity.spec.ts b/server/src/domain/activity/activity.spec.ts index 10a4c0725..cd70572ca 100644 --- a/server/src/domain/activity/activity.spec.ts +++ b/server/src/domain/activity/activity.spec.ts @@ -1,10 +1,11 @@ import { BadRequestException } from '@nestjs/common'; -import { authStub, IAccessRepositoryMock, newAccessRepositoryMock } from '@test'; -import { activityStub } from '@test/fixtures/activity.stub'; -import { newActivityRepositoryMock } from '@test/repositories/activity.repository.mock'; -import { IActivityRepository } from '../repositories'; -import { ReactionType } from './activity.dto'; -import { ActivityService } from './activity.service'; +import { ReactionType } from 'src/domain/activity/activity.dto'; +import { ActivityService } from 'src/domain/activity/activity.service'; +import { IActivityRepository } from 'src/domain/repositories/activity.repository'; +import { activityStub } from 'test/fixtures/activity.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newActivityRepositoryMock } from 'test/repositories/activity.repository.mock'; describe(ActivityService.name, () => { let sut: ActivityService; diff --git a/server/src/domain/activity/index.ts b/server/src/domain/activity/index.ts deleted file mode 100644 index f0d954014..000000000 --- a/server/src/domain/activity/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './activity.dto'; -export * from './activity.service'; diff --git a/server/src/domain/album/album-response.dto.spec.ts b/server/src/domain/album/album-response.dto.spec.ts index c8485af65..568b416b4 100644 --- a/server/src/domain/album/album-response.dto.spec.ts +++ b/server/src/domain/album/album-response.dto.spec.ts @@ -1,5 +1,5 @@ -import { albumStub } from '@test'; -import { mapAlbum } from './album-response.dto'; +import { mapAlbum } from 'src/domain/album/album-response.dto'; +import { albumStub } from 'test/fixtures/album.stub'; describe('mapAlbum', () => { it('should set start and end dates', () => { diff --git a/server/src/domain/album/album-response.dto.ts b/server/src/domain/album/album-response.dto.ts index bcca1cd31..ab8454a49 100644 --- a/server/src/domain/album/album-response.dto.ts +++ b/server/src/domain/album/album-response.dto.ts @@ -1,9 +1,9 @@ -import { AlbumEntity, AssetOrder } from '@app/infra/entities'; -import { Optional } from '@nestjs/common'; import { ApiProperty } from '@nestjs/swagger'; -import { AssetResponseDto, mapAsset } from '../asset'; -import { AuthDto } from '../auth/auth.dto'; -import { UserResponseDto, mapUser } from '../user'; +import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { Optional } from 'src/domain/domain.util'; +import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { AlbumEntity, AssetOrder } from 'src/infra/entities/album.entity'; export class AlbumResponseDto { id!: string; diff --git a/server/src/domain/album/album.service.spec.ts b/server/src/domain/album/album.service.spec.ts index fa0852d8c..e8122b73c 100644 --- a/server/src/domain/album/album.service.spec.ts +++ b/server/src/domain/album/album.service.spec.ts @@ -1,36 +1,32 @@ import { BadRequestException } from '@nestjs/common'; -import { - albumStub, - authStub, - IAccessRepositoryMock, - newAccessRepositoryMock, - newAlbumRepositoryMock, - newAssetRepositoryMock, - newJobRepositoryMock, - newUserRepositoryMock, - userStub, -} from '@test'; import _ from 'lodash'; -import { BulkIdErrorReason } from '../asset'; -import { IAlbumRepository, IAssetRepository, IJobRepository, IUserRepository } from '../repositories'; -import { AlbumService } from './album.service'; +import { AlbumService } from 'src/domain/album/album.service'; +import { BulkIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { albumStub } from 'test/fixtures/album.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { userStub } from 'test/fixtures/user.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newAlbumRepositoryMock } from 'test/repositories/album.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; describe(AlbumService.name, () => { let sut: AlbumService; let accessMock: IAccessRepositoryMock; let albumMock: jest.Mocked; let assetMock: jest.Mocked; - let jobMock: jest.Mocked; let userMock: jest.Mocked; beforeEach(() => { accessMock = newAccessRepositoryMock(); albumMock = newAlbumRepositoryMock(); assetMock = newAssetRepositoryMock(); - jobMock = newJobRepositoryMock(); userMock = newUserRepositoryMock(); - sut = new AlbumService(accessMock, albumMock, assetMock, jobMock, userMock); + sut = new AlbumService(accessMock, albumMock, assetMock, userMock); }); it('should work', () => { diff --git a/server/src/domain/album/album.service.ts b/server/src/domain/album/album.service.ts index dc3d510d4..7ba91f1d9 100644 --- a/server/src/domain/album/album.service.ts +++ b/server/src/domain/album/album.service.ts @@ -1,26 +1,27 @@ -import { AlbumEntity, AssetEntity, UserEntity } from '@app/infra/entities'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { AccessCore, Permission } from '../access'; -import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from '../asset'; -import { AuthDto } from '../auth'; -import { setUnion } from '../domain.util'; -import { - AlbumAssetCount, - AlbumInfoOptions, - IAccessRepository, - IAlbumRepository, - IAssetRepository, - IJobRepository, - IUserRepository, -} from '../repositories'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; import { AlbumCountResponseDto, AlbumResponseDto, mapAlbum, mapAlbumWithAssets, mapAlbumWithoutAssets, -} from './album-response.dto'; -import { AddUsersDto, AlbumInfoDto, CreateAlbumDto, GetAlbumsDto, UpdateAlbumDto } from './dto'; +} from 'src/domain/album/album-response.dto'; +import { AddUsersDto } from 'src/domain/album/dto/album-add-users.dto'; +import { CreateAlbumDto } from 'src/domain/album/dto/album-create.dto'; +import { UpdateAlbumDto } from 'src/domain/album/dto/album-update.dto'; +import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; +import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; +import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { setUnion } from 'src/domain/domain.util'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; @Injectable() export class AlbumService { @@ -29,7 +30,6 @@ export class AlbumService { @Inject(IAccessRepository) accessRepository: IAccessRepository, @Inject(IAlbumRepository) private albumRepository: IAlbumRepository, @Inject(IAssetRepository) private assetRepository: IAssetRepository, - @Inject(IJobRepository) private jobRepository: IJobRepository, @Inject(IUserRepository) private userRepository: IUserRepository, ) { this.access = AccessCore.create(accessRepository); diff --git a/server/src/domain/album/dto/album-add-users.dto.ts b/server/src/domain/album/dto/album-add-users.dto.ts index f238b9a05..b6a9e8be9 100644 --- a/server/src/domain/album/dto/album-add-users.dto.ts +++ b/server/src/domain/album/dto/album-add-users.dto.ts @@ -1,5 +1,5 @@ import { ArrayNotEmpty } from 'class-validator'; -import { ValidateUUID } from '../../domain.util'; +import { ValidateUUID } from 'src/domain/domain.util'; export class AddUsersDto { @ValidateUUID({ each: true }) diff --git a/server/src/domain/album/dto/album-create.dto.ts b/server/src/domain/album/dto/album-create.dto.ts index bebbed20b..0765e4d77 100644 --- a/server/src/domain/album/dto/album-create.dto.ts +++ b/server/src/domain/album/dto/album-create.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsString } from 'class-validator'; -import { Optional, ValidateUUID } from '../../domain.util'; +import { Optional, ValidateUUID } from 'src/domain/domain.util'; export class CreateAlbumDto { @IsString() diff --git a/server/src/domain/album/dto/album-update.dto.ts b/server/src/domain/album/dto/album-update.dto.ts index 4f88cefbb..c6b21e08d 100644 --- a/server/src/domain/album/dto/album-update.dto.ts +++ b/server/src/domain/album/dto/album-update.dto.ts @@ -1,7 +1,7 @@ -import { AssetOrder } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateUUID } from '../../domain.util'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; +import { AssetOrder } from 'src/infra/entities/album.entity'; export class UpdateAlbumDto { @Optional() diff --git a/server/src/domain/album/dto/album.dto.ts b/server/src/domain/album/dto/album.dto.ts index b7aad98b5..f1772b4c2 100644 --- a/server/src/domain/album/dto/album.dto.ts +++ b/server/src/domain/album/dto/album.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class AlbumInfoDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/album/dto/get-albums.dto.ts b/server/src/domain/album/dto/get-albums.dto.ts index 2628a3fc7..e03c219aa 100644 --- a/server/src/domain/album/dto/get-albums.dto.ts +++ b/server/src/domain/album/dto/get-albums.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean, ValidateUUID } from '../../domain.util'; +import { ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; export class GetAlbumsDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/album/dto/index.ts b/server/src/domain/album/dto/index.ts deleted file mode 100644 index b1a4c2141..000000000 --- a/server/src/domain/album/dto/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './album-add-users.dto'; -export * from './album-create.dto'; -export * from './album-update.dto'; -export * from './album.dto'; -export * from './get-albums.dto'; diff --git a/server/src/domain/album/index.ts b/server/src/domain/album/index.ts deleted file mode 100644 index f06f6d33c..000000000 --- a/server/src/domain/album/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './album-response.dto'; -export * from './album.service'; -export * from './dto'; diff --git a/server/src/domain/api-key/api-key.dto.ts b/server/src/domain/api-key/api-key.dto.ts index c25ef5fd4..19099ba18 100644 --- a/server/src/domain/api-key/api-key.dto.ts +++ b/server/src/domain/api-key/api-key.dto.ts @@ -1,5 +1,5 @@ import { IsNotEmpty, IsString } from 'class-validator'; -import { Optional } from '../domain.util'; +import { Optional } from 'src/domain/domain.util'; export class APIKeyCreateDto { @IsString() @IsNotEmpty() diff --git a/server/src/domain/api-key/api-key.service.spec.ts b/server/src/domain/api-key/api-key.service.spec.ts index f3b291084..e50d0d9b3 100644 --- a/server/src/domain/api-key/api-key.service.spec.ts +++ b/server/src/domain/api-key/api-key.service.spec.ts @@ -1,7 +1,11 @@ import { BadRequestException } from '@nestjs/common'; -import { authStub, keyStub, newCryptoRepositoryMock, newKeyRepositoryMock } from '@test'; -import { ICryptoRepository, IKeyRepository } from '../repositories'; -import { APIKeyService } from './api-key.service'; +import { APIKeyService } from 'src/domain/api-key/api-key.service'; +import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { keyStub } from 'test/fixtures/api-key.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { newKeyRepositoryMock } from 'test/repositories/api-key.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; describe(APIKeyService.name, () => { let sut: APIKeyService; diff --git a/server/src/domain/api-key/api-key.service.ts b/server/src/domain/api-key/api-key.service.ts index 0eef1981c..5a531e9d5 100644 --- a/server/src/domain/api-key/api-key.service.ts +++ b/server/src/domain/api-key/api-key.service.ts @@ -1,8 +1,9 @@ -import { APIKeyEntity } from '@app/infra/entities'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { AuthDto } from '../auth'; -import { ICryptoRepository, IKeyRepository } from '../repositories'; -import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto } from './api-key.dto'; +import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto } from 'src/domain/api-key/api-key.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; @Injectable() export class APIKeyService { diff --git a/server/src/domain/api-key/index.ts b/server/src/domain/api-key/index.ts deleted file mode 100644 index 94076f2a3..000000000 --- a/server/src/domain/api-key/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './api-key.dto'; -export * from './api-key.service'; diff --git a/server/src/domain/asset/asset.service.spec.ts b/server/src/domain/asset/asset.service.spec.ts index 11d2ed00b..fdf89739f 100644 --- a/server/src/domain/asset/asset.service.spec.ts +++ b/server/src/domain/asset/asset.service.spec.ts @@ -1,42 +1,33 @@ -import { AssetEntity, AssetType } from '@app/infra/entities'; import { BadRequestException, UnauthorizedException } from '@nestjs/common'; -import { - IAccessRepositoryMock, - assetStackStub, - assetStub, - authStub, - faceStub, - newAccessRepositoryMock, - newAssetRepositoryMock, - newAssetStackRepositoryMock, - newCommunicationRepositoryMock, - newJobRepositoryMock, - newPartnerRepositoryMock, - newStorageRepositoryMock, - newSystemConfigRepositoryMock, - newUserRepositoryMock, - partnerStub, - userStub, -} from '@test'; import { when } from 'jest-when'; -import { JobName } from '../job'; -import { - AssetStats, - ClientEvent, - IAssetRepository, - IAssetStackRepository, - ICommunicationRepository, - IJobRepository, - IPartnerRepository, - IStorageRepository, - ISystemConfigRepository, - IUserRepository, - JobItem, - TimeBucketSize, -} from '../repositories'; -import { AssetService, UploadFieldName } from './asset.service'; -import { AssetJobName, AssetStatsResponseDto } from './dto'; -import { mapAsset } from './response-dto'; +import { AssetService, UploadFieldName } from 'src/domain/asset/asset.service'; +import { AssetJobName } from 'src/domain/asset/dto/asset-ids.dto'; +import { AssetStatsResponseDto } from 'src/domain/asset/dto/asset-statistics.dto'; +import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { JobName } from 'src/domain/job/job.constants'; +import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; +import { AssetStats, IAssetRepository, TimeBucketSize } from 'src/domain/repositories/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { IJobRepository, JobItem } from 'src/domain/repositories/job.repository'; +import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { assetStackStub, assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { faceStub } from 'test/fixtures/face.stub'; +import { partnerStub } from 'test/fixtures/partner.stub'; +import { userStub } from 'test/fixtures/user.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newAssetStackRepositoryMock } from 'test/repositories/asset-stack.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newPartnerRepositoryMock } from 'test/repositories/partner.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; +import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; const stats: AssetStats = { [AssetType.IMAGE]: 10, diff --git a/server/src/domain/asset/asset.service.ts b/server/src/domain/asset/asset.service.ts index fbe4e91bd..3d78c8c7b 100644 --- a/server/src/domain/asset/asset.service.ts +++ b/server/src/domain/asset/asset.service.ts @@ -1,54 +1,43 @@ -import { AssetEntity, LibraryType } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, Inject } from '@nestjs/common'; import _ from 'lodash'; import { DateTime, Duration } from 'luxon'; import { extname } from 'node:path'; import sanitize from 'sanitize-filename'; -import { AccessCore, Permission } from '../access'; -import { AuthDto } from '../auth'; -import { mimeTypes } from '../domain.constant'; -import { usePagination } from '../domain.util'; -import { IAssetDeletionJob, ISidecarWriteJob, JOBS_ASSET_PAGINATION_SIZE, JobName } from '../job'; -import { - ClientEvent, - IAccessRepository, - IAssetRepository, - IAssetStackRepository, - ICommunicationRepository, - IJobRepository, - IPartnerRepository, - IStorageRepository, - ISystemConfigRepository, - IUserRepository, - JobItem, - JobStatus, - TimeBucketOptions, -} from '../repositories'; -import { StorageCore, StorageFolder } from '../storage'; -import { SystemConfigCore } from '../system-config'; -import { - AssetBulkDeleteDto, - AssetBulkUpdateDto, - AssetJobName, - AssetJobsDto, - AssetStatsDto, - MapMarkerDto, - MemoryLaneDto, - TimeBucketAssetDto, - TimeBucketDto, - UpdateAssetDto, - UpdateStackParentDto, - mapStats, -} from './dto'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AssetJobName, AssetJobsDto } from 'src/domain/asset/dto/asset-ids.dto'; +import { UpdateStackParentDto } from 'src/domain/asset/dto/asset-stack.dto'; +import { AssetStatsDto, mapStats } from 'src/domain/asset/dto/asset-statistics.dto'; +import { AssetBulkDeleteDto, AssetBulkUpdateDto, UpdateAssetDto } from 'src/domain/asset/dto/asset.dto'; +import { MapMarkerDto } from 'src/domain/asset/dto/map-marker.dto'; +import { MemoryLaneDto } from 'src/domain/asset/dto/memory-lane.dto'; +import { TimeBucketAssetDto, TimeBucketDto } from 'src/domain/asset/dto/time-bucket.dto'; import { AssetResponseDto, - MapMarkerResponseDto, MemoryLaneResponseDto, SanitizedAssetResponseDto, - TimeBucketResponseDto, mapAsset, -} from './response-dto'; +} from 'src/domain/asset/response-dto/asset-response.dto'; +import { MapMarkerResponseDto } from 'src/domain/asset/response-dto/map-marker-response.dto'; +import { TimeBucketResponseDto } from 'src/domain/asset/response-dto/time-bucket-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { mimeTypes } from 'src/domain/domain.constant'; +import { usePagination } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; +import { IAssetDeletionJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; +import { IAssetRepository, TimeBucketOptions } from 'src/domain/repositories/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { IJobRepository, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; +import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { LibraryType } from 'src/infra/entities/library.entity'; +import { ImmichLogger } from 'src/infra/logger'; export enum UploadFieldName { ASSET_DATA = 'assetData', diff --git a/server/src/domain/asset/dto/asset-ids.dto.ts b/server/src/domain/asset/dto/asset-ids.dto.ts index 5ee988bb4..ae236f13d 100644 --- a/server/src/domain/asset/dto/asset-ids.dto.ts +++ b/server/src/domain/asset/dto/asset-ids.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; -import { ValidateUUID } from '../../domain.util'; +import { ValidateUUID } from 'src/domain/domain.util'; export class AssetIdsDto { @ValidateUUID({ each: true }) diff --git a/server/src/domain/asset/dto/asset-stack.dto.ts b/server/src/domain/asset/dto/asset-stack.dto.ts index 80dabdb34..e05bf6a0b 100644 --- a/server/src/domain/asset/dto/asset-stack.dto.ts +++ b/server/src/domain/asset/dto/asset-stack.dto.ts @@ -1,4 +1,4 @@ -import { ValidateUUID } from '../../domain.util'; +import { ValidateUUID } from 'src/domain/domain.util'; export class UpdateStackParentDto { @ValidateUUID() diff --git a/server/src/domain/asset/dto/asset-statistics.dto.ts b/server/src/domain/asset/dto/asset-statistics.dto.ts index c313ccdf4..9d935789a 100644 --- a/server/src/domain/asset/dto/asset-statistics.dto.ts +++ b/server/src/domain/asset/dto/asset-statistics.dto.ts @@ -1,7 +1,7 @@ -import { AssetType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; -import { ValidateBoolean } from '../../domain.util'; -import { AssetStats } from '../../repositories'; +import { ValidateBoolean } from 'src/domain/domain.util'; +import { AssetStats } from 'src/domain/repositories/asset.repository'; +import { AssetType } from 'src/infra/entities/asset.entity'; export class AssetStatsDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/asset/dto/asset.dto.ts b/server/src/domain/asset/dto/asset.dto.ts index 2abe31d0a..31eaa916e 100644 --- a/server/src/domain/asset/dto/asset.dto.ts +++ b/server/src/domain/asset/dto/asset.dto.ts @@ -9,8 +9,8 @@ import { IsString, ValidateIf, } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateUUID } from '../../domain.util'; -import { BulkIdsDto } from '../response-dto'; +import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; export class DeviceIdDto { @IsNotEmpty() diff --git a/server/src/domain/asset/dto/index.ts b/server/src/domain/asset/dto/index.ts deleted file mode 100644 index bc7a100b9..000000000 --- a/server/src/domain/asset/dto/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -export * from './asset-ids.dto'; -export * from './asset-stack.dto'; -export * from './asset-statistics.dto'; -export * from './asset.dto'; -export * from './map-marker.dto'; -export * from './memory-lane.dto'; -export * from './time-bucket.dto'; diff --git a/server/src/domain/asset/dto/map-marker.dto.ts b/server/src/domain/asset/dto/map-marker.dto.ts index 4fe6c16b8..f06dc201e 100644 --- a/server/src/domain/asset/dto/map-marker.dto.ts +++ b/server/src/domain/asset/dto/map-marker.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean, ValidateDate } from '../../domain.util'; +import { ValidateBoolean, ValidateDate } from 'src/domain/domain.util'; export class MapMarkerDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/asset/dto/time-bucket.dto.ts b/server/src/domain/asset/dto/time-bucket.dto.ts index 7c5b9c212..052e3732e 100644 --- a/server/src/domain/asset/dto/time-bucket.dto.ts +++ b/server/src/domain/asset/dto/time-bucket.dto.ts @@ -1,8 +1,8 @@ -import { AssetOrder } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateUUID } from '../../domain.util'; -import { TimeBucketSize } from '../../repositories'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; +import { TimeBucketSize } from 'src/domain/repositories/asset.repository'; +import { AssetOrder } from 'src/infra/entities/album.entity'; export class TimeBucketDto { @IsNotEmpty() diff --git a/server/src/domain/asset/index.ts b/server/src/domain/asset/index.ts deleted file mode 100644 index 71ad3c8c4..000000000 --- a/server/src/domain/asset/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './asset.service'; -export * from './dto'; -export * from './response-dto'; diff --git a/server/src/domain/asset/response-dto/asset-ids-response.dto.ts b/server/src/domain/asset/response-dto/asset-ids-response.dto.ts index 9bb6a5b36..3a7e8129a 100644 --- a/server/src/domain/asset/response-dto/asset-ids-response.dto.ts +++ b/server/src/domain/asset/response-dto/asset-ids-response.dto.ts @@ -1,4 +1,4 @@ -import { ValidateUUID } from '../../domain.util'; +import { ValidateUUID } from 'src/domain/domain.util'; /** @deprecated Use `BulkIdResponseDto` instead */ export enum AssetIdErrorReason { diff --git a/server/src/domain/asset/response-dto/asset-response.dto.ts b/server/src/domain/asset/response-dto/asset-response.dto.ts index 2961a9dcc..a5c88b4cb 100644 --- a/server/src/domain/asset/response-dto/asset-response.dto.ts +++ b/server/src/domain/asset/response-dto/asset-response.dto.ts @@ -1,11 +1,12 @@ -import { AuthDto } from '@app/domain/auth/auth.dto'; -import { AssetEntity, AssetFaceEntity, AssetType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; -import { PersonWithFacesResponseDto, mapFacesWithoutPerson, mapPerson } from '../../person/person.dto'; -import { TagResponseDto, mapTag } from '../../tag'; -import { UserResponseDto, mapUser } from '../../user/response-dto/user-response.dto'; -import { ExifResponseDto, mapExif } from './exif-response.dto'; -import { SmartInfoResponseDto, mapSmartInfo } from './smart-info-response.dto'; +import { ExifResponseDto, mapExif } from 'src/domain/asset/response-dto/exif-response.dto'; +import { SmartInfoResponseDto, mapSmartInfo } from 'src/domain/asset/response-dto/smart-info-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { PersonWithFacesResponseDto, mapFacesWithoutPerson, mapPerson } from 'src/domain/person/person.dto'; +import { TagResponseDto, mapTag } from 'src/domain/tag/tag-response.dto'; +import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; export class SanitizedAssetResponseDto { id!: string; diff --git a/server/src/domain/asset/response-dto/exif-response.dto.ts b/server/src/domain/asset/response-dto/exif-response.dto.ts index f4d0226b4..fbef6cbbc 100644 --- a/server/src/domain/asset/response-dto/exif-response.dto.ts +++ b/server/src/domain/asset/response-dto/exif-response.dto.ts @@ -1,5 +1,5 @@ -import { ExifEntity } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; export class ExifResponseDto { make?: string | null = null; diff --git a/server/src/domain/asset/response-dto/index.ts b/server/src/domain/asset/response-dto/index.ts deleted file mode 100644 index 7ed99db13..000000000 --- a/server/src/domain/asset/response-dto/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -export * from './asset-ids-response.dto'; -export * from './asset-response.dto'; -export * from './exif-response.dto'; -export * from './map-marker-response.dto'; -export * from './smart-info-response.dto'; -export * from './time-bucket-response.dto'; diff --git a/server/src/domain/asset/response-dto/smart-info-response.dto.ts b/server/src/domain/asset/response-dto/smart-info-response.dto.ts index 72c336205..840fca8a7 100644 --- a/server/src/domain/asset/response-dto/smart-info-response.dto.ts +++ b/server/src/domain/asset/response-dto/smart-info-response.dto.ts @@ -1,4 +1,4 @@ -import { SmartInfoEntity } from '@app/infra/entities'; +import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; export class SmartInfoResponseDto { tags?: string[] | null; diff --git a/server/src/domain/audit/audit.dto.ts b/server/src/domain/audit/audit.dto.ts index 0f3f04dab..131ce147b 100644 --- a/server/src/domain/audit/audit.dto.ts +++ b/server/src/domain/audit/audit.dto.ts @@ -1,8 +1,9 @@ -import { AssetPathType, EntityType, PathType, PersonPathType, UserPathType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsEnum, IsString, IsUUID, ValidateNested } from 'class-validator'; -import { Optional, ValidateDate, ValidateUUID } from '../domain.util'; +import { Optional, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; +import { EntityType } from 'src/infra/entities/audit.entity'; +import { AssetPathType, PathType, PersonPathType, UserPathType } from 'src/infra/entities/move.entity'; const PathEnum = Object.values({ ...AssetPathType, ...PersonPathType, ...UserPathType }); diff --git a/server/src/domain/audit/audit.service.spec.ts b/server/src/domain/audit/audit.service.spec.ts index 82c6cc699..b8a4d2b2b 100644 --- a/server/src/domain/audit/audit.service.spec.ts +++ b/server/src/domain/audit/audit.service.spec.ts @@ -1,26 +1,21 @@ -import { DatabaseAction, EntityType } from '@app/infra/entities'; -import { - IAccessRepositoryMock, - auditStub, - authStub, - newAccessRepositoryMock, - newAssetRepositoryMock, - newAuditRepositoryMock, - newCryptoRepositoryMock, - newPersonRepositoryMock, - newStorageRepositoryMock, - newUserRepositoryMock, -} from '@test'; -import { - IAssetRepository, - IAuditRepository, - ICryptoRepository, - IPersonRepository, - IStorageRepository, - IUserRepository, - JobStatus, -} from '../repositories'; -import { AuditService } from './audit.service'; +import { AuditService } from 'src/domain/audit/audit.service'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IAuditRepository } from 'src/domain/repositories/audit.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { JobStatus } from 'src/domain/repositories/job.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; +import { auditStub } from 'test/fixtures/audit.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newAuditRepositoryMock } from 'test/repositories/audit.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newPersonRepositoryMock } from 'test/repositories/person.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; describe(AuditService.name, () => { let sut: AuditService; diff --git a/server/src/domain/audit/audit.service.ts b/server/src/domain/audit/audit.service.ts index c96f36d74..0bcb2ed15 100644 --- a/server/src/domain/audit/audit.service.ts +++ b/server/src/domain/audit/audit.service.ts @@ -1,24 +1,7 @@ -import { AssetPathType, DatabaseAction, PersonPathType, UserPathType } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; import { resolve } from 'node:path'; -import { AccessCore, Permission } from '../access'; -import { AuthDto } from '../auth'; -import { AUDIT_LOG_MAX_DURATION } from '../domain.constant'; -import { usePagination } from '../domain.util'; -import { JOBS_ASSET_PAGINATION_SIZE } from '../job'; -import { - IAccessRepository, - IAssetRepository, - IAuditRepository, - ICryptoRepository, - IPersonRepository, - IStorageRepository, - IUserRepository, - JobStatus, -} from '../repositories'; -import { StorageCore, StorageFolder } from '../storage'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; import { AuditDeletesDto, AuditDeletesResponseDto, @@ -26,7 +9,23 @@ import { FileChecksumResponseDto, FileReportItemDto, PathEntityType, -} from './audit.dto'; +} from 'src/domain/audit/audit.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AUDIT_LOG_MAX_DURATION } from 'src/domain/domain.constant'; +import { usePagination } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IAuditRepository } from 'src/domain/repositories/audit.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { JobStatus } from 'src/domain/repositories/job.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; +import { DatabaseAction } from 'src/infra/entities/audit.entity'; +import { AssetPathType, PersonPathType, UserPathType } from 'src/infra/entities/move.entity'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class AuditService { diff --git a/server/src/domain/audit/index.ts b/server/src/domain/audit/index.ts deleted file mode 100644 index febebf0f6..000000000 --- a/server/src/domain/audit/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './audit.dto'; -export * from './audit.service'; diff --git a/server/src/domain/auth/auth.dto.ts b/server/src/domain/auth/auth.dto.ts index 2f6f4b4b7..1694231ab 100644 --- a/server/src/domain/auth/auth.dto.ts +++ b/server/src/domain/auth/auth.dto.ts @@ -1,7 +1,10 @@ -import { APIKeyEntity, SharedLinkEntity, UserEntity, UserTokenEntity } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator'; +import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; export class AuthDto { user!: UserEntity; diff --git a/server/src/domain/auth/auth.service.spec.ts b/server/src/domain/auth/auth.service.spec.ts index 214b6748e..37941aa44 100644 --- a/server/src/domain/auth/auth.service.spec.ts +++ b/server/src/domain/auth/auth.service.spec.ts @@ -1,38 +1,32 @@ -import { UserEntity } from '@app/infra/entities'; import { BadRequestException, UnauthorizedException } from '@nestjs/common'; -import { - IAccessRepositoryMock, - authStub, - keyStub, - loginResponseStub, - newAccessRepositoryMock, - newCryptoRepositoryMock, - newKeyRepositoryMock, - newLibraryRepositoryMock, - newSharedLinkRepositoryMock, - newSystemConfigRepositoryMock, - newUserRepositoryMock, - newUserTokenRepositoryMock, - sharedLinkStub, - systemConfigStub, - userStub, - userTokenStub, -} from '@test'; import { IncomingHttpHeaders } from 'node:http'; import { Issuer, generators } from 'openid-client'; import { Socket } from 'socket.io'; -import { - ICryptoRepository, - IKeyRepository, - ILibraryRepository, - ISharedLinkRepository, - ISystemConfigRepository, - IUserRepository, - IUserTokenRepository, -} from '../repositories'; -import { AuthType } from './auth.constant'; -import { AuthDto, SignUpDto } from './auth.dto'; -import { AuthService } from './auth.service'; +import { AuthType } from 'src/domain/auth/auth.constant'; +import { AuthDto, SignUpDto } from 'src/domain/auth/auth.dto'; +import { AuthService } from 'src/domain/auth/auth.service'; +import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { UserEntity } from 'src/infra/entities/user.entity'; +import { keyStub } from 'test/fixtures/api-key.stub'; +import { authStub, loginResponseStub } from 'test/fixtures/auth.stub'; +import { sharedLinkStub } from 'test/fixtures/shared-link.stub'; +import { systemConfigStub } from 'test/fixtures/system-config.stub'; +import { userTokenStub } from 'test/fixtures/user-token.stub'; +import { userStub } from 'test/fixtures/user.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newKeyRepositoryMock } from 'test/repositories/api-key.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newLibraryRepositoryMock } from 'test/repositories/library.repository.mock'; +import { newSharedLinkRepositoryMock } from 'test/repositories/shared-link.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; +import { newUserTokenRepositoryMock } from 'test/repositories/user-token.repository.mock'; +import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; // const token = Buffer.from('my-api-key', 'utf8').toString('base64'); diff --git a/server/src/domain/auth/auth.service.ts b/server/src/domain/auth/auth.service.ts index fe01ef39b..bb01e1b3b 100644 --- a/server/src/domain/auth/auth.service.ts +++ b/server/src/domain/auth/auth.service.ts @@ -1,5 +1,3 @@ -import { SystemConfig, UserEntity } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, Inject, @@ -12,20 +10,7 @@ import cookieParser from 'cookie'; import { DateTime } from 'luxon'; import { IncomingHttpHeaders } from 'node:http'; import { ClientMetadata, Issuer, UserinfoResponse, custom, generators } from 'openid-client'; -import { AccessCore, Permission } from '../access'; -import { HumanReadableSize } from '../domain.util'; -import { - IAccessRepository, - ICryptoRepository, - IKeyRepository, - ILibraryRepository, - ISharedLinkRepository, - ISystemConfigRepository, - IUserRepository, - IUserTokenRepository, -} from '../repositories'; -import { SystemConfigCore } from '../system-config/system-config.core'; -import { UserCore, UserResponseDto, mapUser } from '../user'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; import { AuthType, IMMICH_ACCESS_COOKIE, @@ -34,7 +19,7 @@ import { IMMICH_IS_AUTHENTICATED, LOGIN_URL, MOBILE_REDIRECT, -} from './auth.constant'; +} from 'src/domain/auth/auth.constant'; import { AuthDeviceResponseDto, AuthDto, @@ -48,7 +33,22 @@ import { SignUpDto, mapLoginResponse, mapUserToken, -} from './auth.dto'; +} from 'src/domain/auth/auth.dto'; +import { HumanReadableSize } from 'src/domain/domain.util'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { UserCore } from 'src/domain/user/user.core'; +import { SystemConfig } from 'src/infra/entities/system-config.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; +import { ImmichLogger } from 'src/infra/logger'; export interface LoginDetails { isSecure: boolean; diff --git a/server/src/domain/auth/index.ts b/server/src/domain/auth/index.ts deleted file mode 100644 index 52e0463bc..000000000 --- a/server/src/domain/auth/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './auth.constant'; -export * from './auth.dto'; -export * from './auth.service'; diff --git a/server/src/domain/database/database.service.spec.ts b/server/src/domain/database/database.service.spec.ts index 14464c0cd..25ebe61af 100644 --- a/server/src/domain/database/database.service.spec.ts +++ b/server/src/domain/database/database.service.spec.ts @@ -1,13 +1,8 @@ -import { - DatabaseExtension, - DatabaseService, - IDatabaseRepository, - VectorIndex, - Version, - VersionType, -} from '@app/domain'; -import { ImmichLogger } from '@app/infra/logger'; -import { newDatabaseRepositoryMock } from '@test'; +import { DatabaseService } from 'src/domain/database/database.service'; +import { Version, VersionType } from 'src/domain/domain.constant'; +import { DatabaseExtension, IDatabaseRepository, VectorIndex } from 'src/domain/repositories/database.repository'; +import { ImmichLogger } from 'src/infra/logger'; +import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; describe(DatabaseService.name, () => { let sut: DatabaseService; diff --git a/server/src/domain/database/database.service.ts b/server/src/domain/database/database.service.ts index 946c6dac8..6e6ef98aa 100644 --- a/server/src/domain/database/database.service.ts +++ b/server/src/domain/database/database.service.ts @@ -1,6 +1,5 @@ -import { ImmichLogger } from '@app/infra/logger'; import { Inject, Injectable } from '@nestjs/common'; -import { Version, VersionType } from '../domain.constant'; +import { Version, VersionType } from 'src/domain/domain.constant'; import { DatabaseExtension, DatabaseLock, @@ -8,7 +7,8 @@ import { VectorExtension, VectorIndex, extName, -} from '../repositories'; +} from 'src/domain/repositories/database.repository'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class DatabaseService { diff --git a/server/src/domain/database/index.ts b/server/src/domain/database/index.ts deleted file mode 100644 index cd4e1d217..000000000 --- a/server/src/domain/database/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './database.service'; diff --git a/server/src/domain/domain.config.ts b/server/src/domain/domain.config.ts index b0471080d..40580b8e4 100644 --- a/server/src/domain/domain.config.ts +++ b/server/src/domain/domain.config.ts @@ -1,7 +1,7 @@ // TODO: remove nestjs references from domain -import { LogLevel } from '@app/infra/entities'; import { ConfigModuleOptions } from '@nestjs/config'; import Joi from 'joi'; +import { LogLevel } from 'src/infra/entities/system-config.entity'; const WHEN_DB_URL_SET = Joi.when('DB_URL', { is: Joi.exist(), diff --git a/server/src/domain/domain.constant.spec.ts b/server/src/domain/domain.constant.spec.ts index 70944328e..e8a1c7b72 100644 --- a/server/src/domain/domain.constant.spec.ts +++ b/server/src/domain/domain.constant.spec.ts @@ -1,4 +1,4 @@ -import { Version, VersionType, mimeTypes } from './domain.constant'; +import { mimeTypes, Version, VersionType } from 'src/domain/domain.constant'; describe('mimeTypes', () => { for (const { mimetype, extension } of [ diff --git a/server/src/domain/domain.constant.ts b/server/src/domain/domain.constant.ts index 56b455855..13c8fa532 100644 --- a/server/src/domain/domain.constant.ts +++ b/server/src/domain/domain.constant.ts @@ -1,7 +1,7 @@ -import { AssetType } from '@app/infra/entities'; import { Duration } from 'luxon'; import { readFileSync } from 'node:fs'; import { extname, join } from 'node:path'; +import { AssetType } from 'src/infra/entities/asset.entity'; export const AUDIT_LOG_MAX_DURATION = Duration.fromObject({ days: 100 }); export const ONE_HOUR = Duration.fromObject({ hours: 1 }); diff --git a/server/src/domain/domain.module.ts b/server/src/domain/domain.module.ts index c3e62edb5..04d7c51f4 100644 --- a/server/src/domain/domain.module.ts +++ b/server/src/domain/domain.module.ts @@ -1,29 +1,29 @@ -import { ImmichLogger } from '@app/infra/logger'; import { Global, Module, Provider } from '@nestjs/common'; -import { ActivityService } from './activity'; -import { AlbumService } from './album'; -import { APIKeyService } from './api-key'; -import { AssetService } from './asset'; -import { AuditService } from './audit'; -import { AuthService } from './auth'; -import { DatabaseService } from './database'; -import { DownloadService } from './download'; -import { JobService } from './job'; -import { LibraryService } from './library'; -import { MediaService } from './media'; -import { MetadataService } from './metadata'; -import { PartnerService } from './partner'; -import { PersonService } from './person'; -import { SearchService } from './search'; -import { ServerInfoService } from './server-info'; -import { SharedLinkService } from './shared-link'; -import { SmartInfoService } from './smart-info'; -import { StorageService } from './storage'; -import { StorageTemplateService } from './storage-template'; -import { SystemConfigService } from './system-config'; -import { TagService } from './tag'; -import { TrashService } from './trash'; -import { UserService } from './user'; +import { ActivityService } from 'src/domain/activity/activity.service'; +import { AlbumService } from 'src/domain/album/album.service'; +import { APIKeyService } from 'src/domain/api-key/api-key.service'; +import { AssetService } from 'src/domain/asset/asset.service'; +import { AuditService } from 'src/domain/audit/audit.service'; +import { AuthService } from 'src/domain/auth/auth.service'; +import { DatabaseService } from 'src/domain/database/database.service'; +import { DownloadService } from 'src/domain/download/download.service'; +import { JobService } from 'src/domain/job/job.service'; +import { LibraryService } from 'src/domain/library/library.service'; +import { MediaService } from 'src/domain/media/media.service'; +import { MetadataService } from 'src/domain/metadata/metadata.service'; +import { PartnerService } from 'src/domain/partner/partner.service'; +import { PersonService } from 'src/domain/person/person.service'; +import { SearchService } from 'src/domain/search/search.service'; +import { ServerInfoService } from 'src/domain/server-info/server-info.service'; +import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; +import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; +import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; +import { StorageService } from 'src/domain/storage/storage.service'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { TagService } from 'src/domain/tag/tag.service'; +import { TrashService } from 'src/domain/trash/trash.service'; +import { UserService } from 'src/domain/user/user.service'; +import { ImmichLogger } from 'src/infra/logger'; const providers: Provider[] = [ APIKeyService, diff --git a/server/src/domain/domain.util.ts b/server/src/domain/domain.util.ts index a079ff6bf..820c17f3f 100644 --- a/server/src/domain/domain.util.ts +++ b/server/src/domain/domain.util.ts @@ -1,4 +1,3 @@ -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, applyDecorators } from '@nestjs/common'; import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; @@ -18,6 +17,7 @@ import { CronJob } from 'cron'; import _ from 'lodash'; import { basename, extname } from 'node:path'; import sanitize from 'sanitize-filename'; +import { ImmichLogger } from 'src/infra/logger'; export enum CacheControl { PRIVATE_WITH_CACHE = 'private_with_cache', diff --git a/server/src/domain/download/download.dto.ts b/server/src/domain/download/download.dto.ts index 3785a9d43..e350d66ac 100644 --- a/server/src/domain/download/download.dto.ts +++ b/server/src/domain/download/download.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsInt, IsPositive } from 'class-validator'; -import { Optional, ValidateUUID } from '../domain.util'; +import { Optional, ValidateUUID } from 'src/domain/domain.util'; export class DownloadInfoDto { @ValidateUUID({ each: true, optional: true }) diff --git a/server/src/domain/download/download.service.spec.ts b/server/src/domain/download/download.service.spec.ts index 09161d8f6..d22ce69e8 100644 --- a/server/src/domain/download/download.service.spec.ts +++ b/server/src/domain/download/download.service.spec.ts @@ -1,18 +1,16 @@ import { BadRequestException } from '@nestjs/common'; -import { - IAccessRepositoryMock, - assetStub, - authStub, - newAccessRepositoryMock, - newAssetRepositoryMock, - newStorageRepositoryMock, -} from '@test'; import { when } from 'jest-when'; +import { CacheControl, ImmichFileResponse } from 'src/domain/domain.util'; +import { DownloadResponseDto } from 'src/domain/download/download.dto'; +import { DownloadService } from 'src/domain/download/download.service'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; import { Readable } from 'typeorm/platform/PlatformTools.js'; -import { CacheControl, ImmichFileResponse } from '../domain.util'; -import { IAssetRepository, IStorageRepository } from '../repositories'; -import { DownloadResponseDto } from './download.dto'; -import { DownloadService } from './download.service'; const downloadResponse: DownloadResponseDto = { totalSize: 105_000, diff --git a/server/src/domain/download/download.service.ts b/server/src/domain/download/download.service.ts index 1b4a19185..b069ac9b3 100644 --- a/server/src/domain/download/download.service.ts +++ b/server/src/domain/download/download.service.ts @@ -1,13 +1,15 @@ -import { AssetEntity } from '@app/infra/entities'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { parse } from 'node:path'; -import { AccessCore, Permission } from '../access'; -import { AssetIdsDto } from '../asset'; -import { AuthDto } from '../auth'; -import { mimeTypes } from '../domain.constant'; -import { CacheControl, HumanReadableSize, ImmichFileResponse, usePagination } from '../domain.util'; -import { IAccessRepository, IAssetRepository, IStorageRepository, ImmichReadStream } from '../repositories'; -import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from './download.dto'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { mimeTypes } from 'src/domain/domain.constant'; +import { CacheControl, HumanReadableSize, ImmichFileResponse, usePagination } from 'src/domain/domain.util'; +import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/download.dto'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IStorageRepository, ImmichReadStream } from 'src/domain/repositories/storage.repository'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; @Injectable() export class DownloadService { diff --git a/server/src/domain/download/index.ts b/server/src/domain/download/index.ts deleted file mode 100644 index ab5c91ec9..000000000 --- a/server/src/domain/download/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './download.dto'; -export * from './download.service'; diff --git a/server/src/domain/index.ts b/server/src/domain/index.ts deleted file mode 100644 index dce2fa696..000000000 --- a/server/src/domain/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -export * from './access'; -export * from './activity'; -export * from './album'; -export * from './api-key'; -export * from './asset'; -export * from './audit'; -export * from './auth'; -export * from './database'; -export * from './domain.config'; -export * from './domain.constant'; -export * from './domain.module'; -export * from './domain.util'; -export * from './download'; -export * from './job'; -export * from './library'; -export * from './media'; -export * from './metadata'; -export * from './partner'; -export * from './person'; -export * from './repositories'; -export * from './search'; -export * from './server-info'; -export * from './shared-link'; -export * from './smart-info'; -export * from './storage'; -export * from './storage-template'; -export * from './system-config'; -export * from './tag'; -export * from './trash'; -export * from './user'; diff --git a/server/src/domain/job/index.ts b/server/src/domain/job/index.ts deleted file mode 100644 index 44f617f0c..000000000 --- a/server/src/domain/job/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './job.constants'; -export * from './job.dto'; -export * from './job.interface'; -export * from './job.service'; diff --git a/server/src/domain/job/job.dto.ts b/server/src/domain/job/job.dto.ts index 87be1332f..f551ab961 100644 --- a/server/src/domain/job/job.dto.ts +++ b/server/src/domain/job/job.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty } from 'class-validator'; -import { ValidateBoolean } from '../domain.util'; -import { JobCommand, QueueName } from './job.constants'; +import { ValidateBoolean } from 'src/domain/domain.util'; +import { JobCommand, QueueName } from 'src/domain/job/job.constants'; export class JobIdParamDto { @IsNotEmpty() diff --git a/server/src/domain/job/job.service.spec.ts b/server/src/domain/job/job.service.spec.ts index c2133a623..7fc8cc86e 100644 --- a/server/src/domain/job/job.service.spec.ts +++ b/server/src/domain/job/job.service.spec.ts @@ -1,26 +1,19 @@ -import { SystemConfig, SystemConfigKey } from '@app/infra/entities'; import { BadRequestException } from '@nestjs/common'; -import { - assetStub, - newAssetRepositoryMock, - newCommunicationRepositoryMock, - newJobRepositoryMock, - newPersonRepositoryMock, - newSystemConfigRepositoryMock, -} from '@test'; -import { - IAssetRepository, - ICommunicationRepository, - IJobRepository, - IPersonRepository, - ISystemConfigRepository, - JobHandler, - JobItem, - JobStatus, -} from '../repositories'; -import { FeatureFlag, SystemConfigCore } from '../system-config/system-config.core'; -import { JobCommand, JobName, QueueName } from './job.constants'; -import { JobService } from './job.service'; +import { JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; +import { JobService } from 'src/domain/job/job.service'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { IJobRepository, JobHandler, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newPersonRepositoryMock } from 'test/repositories/person.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; const makeMockHandlers = (status: JobStatus) => { const mock = jest.fn().mockResolvedValue(status); diff --git a/server/src/domain/job/job.service.ts b/server/src/domain/job/job.service.ts index e00636ad6..bccb897d3 100644 --- a/server/src/domain/job/job.service.ts +++ b/server/src/domain/job/job.service.ts @@ -1,22 +1,15 @@ -import { AssetType } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { mapAsset } from '../asset'; -import { - ClientEvent, - IAssetRepository, - ICommunicationRepository, - IJobRepository, - IPersonRepository, - ISystemConfigRepository, - JobHandler, - JobItem, - JobStatus, - QueueCleanType, -} from '../repositories'; -import { FeatureFlag, SystemConfigCore } from '../system-config/system-config.core'; -import { ConcurrentQueueName, JobCommand, JobName, QueueName } from './job.constants'; -import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from './job.dto'; +import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { ConcurrentQueueName, JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; +import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/domain/job/job.dto'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { IJobRepository, JobHandler, JobItem, JobStatus, QueueCleanType } from 'src/domain/repositories/job.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetType } from 'src/infra/entities/asset.entity'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class JobService { diff --git a/server/src/domain/library/index.ts b/server/src/domain/library/index.ts deleted file mode 100644 index da0d981f2..000000000 --- a/server/src/domain/library/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './library.dto'; -export * from './library.service'; diff --git a/server/src/domain/library/library.dto.ts b/server/src/domain/library/library.dto.ts index fcce02f87..26faf4340 100644 --- a/server/src/domain/library/library.dto.ts +++ b/server/src/domain/library/library.dto.ts @@ -1,7 +1,7 @@ -import { LibraryEntity, LibraryType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { ArrayMaxSize, ArrayUnique, IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateUUID } from '../domain.util'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; +import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; export class CreateLibraryDto { @IsEnum(LibraryType) diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/domain/library/library.service.spec.ts index bd57a684d..bfa3102d9 100644 --- a/server/src/domain/library/library.service.spec.ts +++ b/server/src/domain/library/library.service.spec.ts @@ -1,45 +1,39 @@ -import { AssetType, LibraryType, SystemConfig, SystemConfigKey, UserEntity } from '@app/infra/entities'; import { BadRequestException } from '@nestjs/common'; -import { - IAccessRepositoryMock, - assetStub, - authStub, - libraryStub, - makeMockWatcher, - newAccessRepositoryMock, - newAssetRepositoryMock, - newCryptoRepositoryMock, - newDatabaseRepositoryMock, - newJobRepositoryMock, - newLibraryRepositoryMock, - newStorageRepositoryMock, - newSystemConfigRepositoryMock, - systemConfigStub, - userStub, -} from '@test'; import { when } from 'jest-when'; import { R_OK } from 'node:constants'; import { Stats } from 'node:fs'; -import { ILibraryFileJob, ILibraryRefreshJob, JobName } from '../job'; -import { - IAssetRepository, - ICryptoRepository, - IDatabaseRepository, - IJobRepository, - ILibraryRepository, - IStorageRepository, - ISystemConfigRepository, - JobStatus, - StorageEventType, -} from '../repositories'; -import { SystemConfigCore } from '../system-config/system-config.core'; -import { mapLibrary } from './library.dto'; -import { LibraryService } from './library.service'; +import { JobName } from 'src/domain/job/job.constants'; +import { ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; +import { mapLibrary } from 'src/domain/library/library.dto'; +import { LibraryService } from 'src/domain/library/library.service'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { IStorageRepository, StorageEventType } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetType } from 'src/infra/entities/asset.entity'; +import { LibraryType } from 'src/infra/entities/library.entity'; +import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { libraryStub } from 'test/fixtures/library.stub'; +import { systemConfigStub } from 'test/fixtures/system-config.stub'; +import { userStub } from 'test/fixtures/user.stub'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newLibraryRepositoryMock } from 'test/repositories/library.repository.mock'; +import { makeMockWatcher, newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; describe(LibraryService.name, () => { let sut: LibraryService; - let accessMock: IAccessRepositoryMock; let assetMock: jest.Mocked; let configMock: jest.Mocked; let cryptoMock: jest.Mocked; @@ -49,7 +43,6 @@ describe(LibraryService.name, () => { let databaseMock: jest.Mocked; beforeEach(() => { - accessMock = newAccessRepositoryMock(); configMock = newSystemConfigRepositoryMock(); libraryMock = newLibraryRepositoryMock(); assetMock = newAssetRepositoryMock(); @@ -58,19 +51,7 @@ describe(LibraryService.name, () => { storageMock = newStorageRepositoryMock(); databaseMock = newDatabaseRepositoryMock(); - // Always validate owner access for library. - accessMock.library.checkOwnerAccess.mockImplementation((_, libraryIds) => Promise.resolve(libraryIds)); - - sut = new LibraryService( - accessMock, - assetMock, - configMock, - cryptoMock, - jobMock, - libraryMock, - storageMock, - databaseMock, - ); + sut = new LibraryService(assetMock, configMock, cryptoMock, jobMock, libraryMock, storageMock, databaseMock); databaseMock.tryLock.mockResolvedValue(true); }); diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts index 00667539b..7ad781f28 100644 --- a/server/src/domain/library/library.service.ts +++ b/server/src/domain/library/library.service.ts @@ -1,5 +1,3 @@ -import { AssetType, LibraryEntity, LibraryType } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import { Trie } from 'mnemonist'; @@ -8,28 +6,10 @@ import { EventEmitter } from 'node:events'; import { Stats } from 'node:fs'; import path, { basename, parse } from 'node:path'; import picomatch from 'picomatch'; -import { AccessCore } from '../access'; -import { mimeTypes } from '../domain.constant'; -import { handlePromiseError, usePagination, validateCronExpression } from '../domain.util'; -import { IBaseJob, IEntityJob, ILibraryFileJob, ILibraryRefreshJob, JOBS_ASSET_PAGINATION_SIZE, JobName } from '../job'; -import { - DatabaseLock, - IAccessRepository, - IAssetRepository, - ICryptoRepository, - IDatabaseRepository, - IJobRepository, - ILibraryRepository, - IStorageRepository, - ISystemConfigRepository, - InternalEvent, - InternalEventMap, - JobStatus, - StorageEventType, - WithProperty, -} from '../repositories'; -import { StorageCore } from '../storage'; -import { SystemConfigCore } from '../system-config'; +import { mimeTypes } from 'src/domain/domain.constant'; +import { handlePromiseError, usePagination, validateCronExpression } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; +import { IBaseJob, IEntityJob, ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; import { CreateLibraryDto, LibraryResponseDto, @@ -41,21 +21,32 @@ import { ValidateLibraryImportPathResponseDto, ValidateLibraryResponseDto, mapLibrary, -} from './library.dto'; +} from 'src/domain/library/library.dto'; +import { IAssetRepository, WithProperty } from 'src/domain/repositories/asset.repository'; +import { InternalEvent, InternalEventMap } from 'src/domain/repositories/communication.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { DatabaseLock, IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { IStorageRepository, StorageEventType } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { StorageCore } from 'src/domain/storage/storage.core'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetType } from 'src/infra/entities/asset.entity'; +import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { ImmichLogger } from 'src/infra/logger'; const LIBRARY_SCAN_BATCH_SIZE = 5000; @Injectable() export class LibraryService extends EventEmitter { readonly logger = new ImmichLogger(LibraryService.name); - private access: AccessCore; private configCore: SystemConfigCore; private watchLibraries = false; private watchLock = false; private watchers: Record Promise> = {}; constructor( - @Inject(IAccessRepository) accessRepository: IAccessRepository, @Inject(IAssetRepository) private assetRepository: IAssetRepository, @Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository, @Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository, @@ -65,7 +56,6 @@ export class LibraryService extends EventEmitter { @Inject(IDatabaseRepository) private databaseRepository: IDatabaseRepository, ) { super(); - this.access = AccessCore.create(accessRepository); this.configCore = SystemConfigCore.create(configRepository); } diff --git a/server/src/domain/media/index.ts b/server/src/domain/media/index.ts deleted file mode 100644 index 83a31567b..000000000 --- a/server/src/domain/media/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './media.constant'; -export * from './media.service'; diff --git a/server/src/domain/media/media.service.spec.ts b/server/src/domain/media/media.service.spec.ts index 36d2cfdba..9a5727ef2 100644 --- a/server/src/domain/media/media.service.spec.ts +++ b/server/src/domain/media/media.service.spec.ts @@ -1,43 +1,37 @@ +import { Stats } from 'node:fs'; +import { JobName } from 'src/domain/job/job.constants'; +import { MediaService } from 'src/domain/media/media.service'; +import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; +import { IMediaRepository } from 'src/domain/repositories/media.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { AssetType } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; import { - AssetType, AudioCodec, Colorspace, - ExifEntity, SystemConfigKey, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec, -} from '@app/infra/entities'; -import { - assetStub, - faceStub, - newAssetRepositoryMock, - newCryptoRepositoryMock, - newJobRepositoryMock, - newMediaRepositoryMock, - newMoveRepositoryMock, - newPersonRepositoryMock, - newStorageRepositoryMock, - newSystemConfigRepositoryMock, - personStub, - probeStub, -} from '@test'; -import { Stats } from 'node:fs'; -import { JobName } from '../job'; -import { - IAssetRepository, - ICryptoRepository, - IJobRepository, - IMediaRepository, - IMoveRepository, - IPersonRepository, - IStorageRepository, - ISystemConfigRepository, - JobStatus, - WithoutProperty, -} from '../repositories'; -import { MediaService } from './media.service'; +} from 'src/infra/entities/system-config.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { faceStub } from 'test/fixtures/face.stub'; +import { probeStub } from 'test/fixtures/media.stub'; +import { personStub } from 'test/fixtures/person.stub'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newMediaRepositoryMock } from 'test/repositories/media.repository.mock'; +import { newMoveRepositoryMock } from 'test/repositories/move.repository.mock'; +import { newPersonRepositoryMock } from 'test/repositories/person.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; describe(MediaService.name, () => { let sut: MediaService; diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index 31eafcbcf..bb0c2503d 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -1,37 +1,7 @@ -import { - AssetEntity, - AssetPathType, - AssetType, - AudioCodec, - Colorspace, - TranscodeHWAccel, - TranscodePolicy, - TranscodeTarget, - VideoCodec, -} from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { Inject, Injectable, UnsupportedMediaTypeException } from '@nestjs/common'; -import { usePagination } from '../domain.util'; -import { IBaseJob, IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from '../job'; -import { - AudioStreamInfo, - IAssetRepository, - ICryptoRepository, - IJobRepository, - IMediaRepository, - IMoveRepository, - IPersonRepository, - IStorageRepository, - ISystemConfigRepository, - JobItem, - JobStatus, - VideoCodecHWConfig, - VideoStreamInfo, - WithoutProperty, -} from '../repositories'; -import { StorageCore, StorageFolder } from '../storage'; -import { SystemConfigFFmpegDto } from '../system-config'; -import { SystemConfigCore } from '../system-config/system-config.core'; +import { usePagination } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; +import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; import { H264Config, HEVCConfig, @@ -41,7 +11,34 @@ import { ThumbnailConfig, VAAPIConfig, VP9Config, -} from './media.util'; +} from 'src/domain/media/media.util'; +import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IJobRepository, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; +import { + AudioStreamInfo, + IMediaRepository, + VideoCodecHWConfig, + VideoStreamInfo, +} from 'src/domain/repositories/media.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; +import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { AssetPathType } from 'src/infra/entities/move.entity'; +import { + AudioCodec, + Colorspace, + TranscodeHWAccel, + TranscodePolicy, + TranscodeTarget, + VideoCodec, +} from 'src/infra/entities/system-config.entity'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class MediaService { @@ -58,7 +55,7 @@ export class MediaService { @Inject(IStorageRepository) private storageRepository: IStorageRepository, @Inject(ISystemConfigRepository) configRepository: ISystemConfigRepository, @Inject(IMoveRepository) moveRepository: IMoveRepository, - @Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository, + @Inject(ICryptoRepository) cryptoRepository: ICryptoRepository, ) { this.configCore = SystemConfigCore.create(configRepository); this.storageCore = StorageCore.create( diff --git a/server/src/domain/media/media.util.ts b/server/src/domain/media/media.util.ts index 3acabb435..224e55a21 100644 --- a/server/src/domain/media/media.util.ts +++ b/server/src/domain/media/media.util.ts @@ -1,4 +1,3 @@ -import { CQMode, ToneMapping, TranscodeHWAccel, TranscodeTarget, VideoCodec } from '@app/infra/entities'; import { AudioStreamInfo, BitrateDistribution, @@ -6,8 +5,16 @@ import { VideoCodecHWConfig, VideoCodecSWConfig, VideoStreamInfo, -} from '../repositories'; -import { SystemConfigFFmpegDto } from '../system-config/dto'; +} from 'src/domain/repositories/media.repository'; +import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; +import { + CQMode, + ToneMapping, + TranscodeHWAccel, + TranscodeTarget, + VideoCodec, +} from 'src/infra/entities/system-config.entity'; + class BaseConfig implements VideoCodecSWConfig { presets = ['veryslow', 'slower', 'slow', 'medium', 'fast', 'faster', 'veryfast', 'superfast', 'ultrafast']; constructor(protected config: SystemConfigFFmpegDto) {} diff --git a/server/src/domain/metadata/index.ts b/server/src/domain/metadata/index.ts deleted file mode 100644 index 92c69e450..000000000 --- a/server/src/domain/metadata/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './metadata.service'; diff --git a/server/src/domain/metadata/metadata.service.spec.ts b/server/src/domain/metadata/metadata.service.spec.ts index 69d31cbd5..e23da47ba 100644 --- a/server/src/domain/metadata/metadata.service.spec.ts +++ b/server/src/domain/metadata/metadata.service.spec.ts @@ -1,46 +1,40 @@ -import { AssetType, ExifEntity, SystemConfigKey } from '@app/infra/entities'; -import { - assetStub, - fileStub, - newAlbumRepositoryMock, - newAssetRepositoryMock, - newCommunicationRepositoryMock, - newCryptoRepositoryMock, - newDatabaseRepositoryMock, - newJobRepositoryMock, - newMediaRepositoryMock, - newMetadataRepositoryMock, - newMoveRepositoryMock, - newPersonRepositoryMock, - newStorageRepositoryMock, - newSystemConfigRepositoryMock, - probeStub, -} from '@test'; import { BinaryField } from 'exiftool-vendored'; import { when } from 'jest-when'; import { randomBytes } from 'node:crypto'; import { Stats } from 'node:fs'; import { constants } from 'node:fs/promises'; -import { JobName } from '../job'; -import { - ClientEvent, - IAlbumRepository, - IAssetRepository, - ICommunicationRepository, - ICryptoRepository, - IDatabaseRepository, - IJobRepository, - IMediaRepository, - IMetadataRepository, - IMoveRepository, - IPersonRepository, - IStorageRepository, - ISystemConfigRepository, - ImmichTags, - JobStatus, - WithoutProperty, -} from '../repositories'; -import { MetadataService, Orientation } from './metadata.service'; +import { JobName } from 'src/domain/job/job.constants'; +import { MetadataService, Orientation } from 'src/domain/metadata/metadata.service'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; +import { IMediaRepository } from 'src/domain/repositories/media.repository'; +import { IMetadataRepository, ImmichTags } from 'src/domain/repositories/metadata.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { AssetType } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { fileStub } from 'test/fixtures/file.stub'; +import { probeStub } from 'test/fixtures/media.stub'; +import { newAlbumRepositoryMock } from 'test/repositories/album.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newMediaRepositoryMock } from 'test/repositories/media.repository.mock'; +import { newMetadataRepositoryMock } from 'test/repositories/metadata.repository.mock'; +import { newMoveRepositoryMock } from 'test/repositories/move.repository.mock'; +import { newPersonRepositoryMock } from 'test/repositories/person.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; describe(MetadataService.name, () => { let albumMock: jest.Mocked; diff --git a/server/src/domain/metadata/metadata.service.ts b/server/src/domain/metadata/metadata.service.ts index 75838330d..4f45b9853 100644 --- a/server/src/domain/metadata/metadata.service.ts +++ b/server/src/domain/metadata/metadata.service.ts @@ -1,5 +1,3 @@ -import { AssetEntity, AssetType, ExifEntity } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { Inject, Injectable } from '@nestjs/common'; import { ExifDateTime, Tags } from 'exiftool-vendored'; import { firstDateTime } from 'exiftool-vendored/dist/FirstDateTime'; @@ -8,29 +6,26 @@ import { Duration } from 'luxon'; import { constants } from 'node:fs/promises'; import path from 'node:path'; import { Subscription } from 'rxjs'; -import { handlePromiseError, usePagination } from '../domain.util'; -import { IBaseJob, IEntityJob, ISidecarWriteJob, JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from '../job'; -import { - ClientEvent, - DatabaseLock, - IAlbumRepository, - IAssetRepository, - ICommunicationRepository, - ICryptoRepository, - IDatabaseRepository, - IJobRepository, - IMediaRepository, - IMetadataRepository, - IMoveRepository, - IPersonRepository, - IStorageRepository, - ISystemConfigRepository, - ImmichTags, - JobStatus, - WithoutProperty, -} from '../repositories'; -import { StorageCore } from '../storage'; -import { FeatureFlag, SystemConfigCore } from '../system-config'; +import { handlePromiseError, usePagination } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; +import { IBaseJob, IEntityJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { DatabaseLock, IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; +import { IMediaRepository } from 'src/domain/repositories/media.repository'; +import { IMetadataRepository, ImmichTags } from 'src/domain/repositories/metadata.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { StorageCore } from 'src/domain/storage/storage.core'; +import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { ImmichLogger } from 'src/infra/logger'; /** look for a date from these tags (in order) */ const EXIF_DATE_TAGS: Array = [ diff --git a/server/src/domain/partner/index.ts b/server/src/domain/partner/index.ts deleted file mode 100644 index b25925e89..000000000 --- a/server/src/domain/partner/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './partner.dto'; -export * from './partner.service'; diff --git a/server/src/domain/partner/partner.dto.ts b/server/src/domain/partner/partner.dto.ts index 17afcad5d..c197d2079 100644 --- a/server/src/domain/partner/partner.dto.ts +++ b/server/src/domain/partner/partner.dto.ts @@ -1,5 +1,5 @@ import { IsNotEmpty } from 'class-validator'; -import { UserResponseDto } from '../user'; +import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; export class UpdatePartnerDto { @IsNotEmpty() diff --git a/server/src/domain/partner/partner.service.spec.ts b/server/src/domain/partner/partner.service.spec.ts index 6e9c10c5c..b1b7fb097 100644 --- a/server/src/domain/partner/partner.service.spec.ts +++ b/server/src/domain/partner/partner.service.spec.ts @@ -1,9 +1,12 @@ -import { UserAvatarColor } from '@app/infra/entities'; import { BadRequestException } from '@nestjs/common'; -import { authStub, newPartnerRepositoryMock, partnerStub } from '@test'; -import { IAccessRepository, IPartnerRepository, PartnerDirection } from '../repositories'; -import { PartnerResponseDto } from './partner.dto'; -import { PartnerService } from './partner.service'; +import { PartnerResponseDto } from 'src/domain/partner/partner.dto'; +import { PartnerService } from 'src/domain/partner/partner.service'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IPartnerRepository, PartnerDirection } from 'src/domain/repositories/partner.repository'; +import { UserAvatarColor } from 'src/infra/entities/user.entity'; +import { authStub } from 'test/fixtures/auth.stub'; +import { partnerStub } from 'test/fixtures/partner.stub'; +import { newPartnerRepositoryMock } from 'test/repositories/partner.repository.mock'; const responseDto = { admin: { diff --git a/server/src/domain/partner/partner.service.ts b/server/src/domain/partner/partner.service.ts index a3f9a9f3d..74cafbcba 100644 --- a/server/src/domain/partner/partner.service.ts +++ b/server/src/domain/partner/partner.service.ts @@ -1,10 +1,11 @@ -import { PartnerEntity } from '@app/infra/entities'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { AccessCore, Permission } from '../access'; -import { AuthDto } from '../auth'; -import { IAccessRepository, IPartnerRepository, PartnerDirection, PartnerIds } from '../repositories'; -import { mapUser } from '../user'; -import { PartnerResponseDto, UpdatePartnerDto } from './partner.dto'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IPartnerRepository, PartnerDirection, PartnerIds } from 'src/domain/repositories/partner.repository'; +import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { PartnerEntity } from 'src/infra/entities/partner.entity'; @Injectable() export class PartnerService { diff --git a/server/src/domain/person/index.ts b/server/src/domain/person/index.ts deleted file mode 100644 index 14a960467..000000000 --- a/server/src/domain/person/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './person.dto'; -export * from './person.service'; diff --git a/server/src/domain/person/person.dto.ts b/server/src/domain/person/person.dto.ts index a00971c6b..9ac66332f 100644 --- a/server/src/domain/person/person.dto.ts +++ b/server/src/domain/person/person.dto.ts @@ -1,9 +1,10 @@ -import { AssetFaceEntity, PersonEntity } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsNotEmpty, IsString, MaxDate, ValidateNested } from 'class-validator'; -import { AuthDto } from '../auth'; -import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from '../domain.util'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; export class PersonCreateDto { /** diff --git a/server/src/domain/person/person.service.spec.ts b/server/src/domain/person/person.service.spec.ts index 08b5875a5..b0aa3c33a 100644 --- a/server/src/domain/person/person.service.spec.ts +++ b/server/src/domain/person/person.service.spec.ts @@ -1,44 +1,37 @@ -import { AssetFaceEntity, Colorspace, SystemConfigKey } from '@app/infra/entities'; import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { - IAccessRepositoryMock, - assetStub, - authStub, - faceStub, - newAccessRepositoryMock, - newAssetRepositoryMock, - newCryptoRepositoryMock, - newJobRepositoryMock, - newMachineLearningRepositoryMock, - newMediaRepositoryMock, - newMoveRepositoryMock, - newPersonRepositoryMock, - newSearchRepositoryMock, - newStorageRepositoryMock, - newSystemConfigRepositoryMock, - personStub, -} from '@test'; +import { BulkIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { CacheControl, ImmichFileResponse } from 'src/domain/domain.util'; +import { JobName } from 'src/domain/job/job.constants'; +import { PersonResponseDto, mapFaces, mapPerson } from 'src/domain/person/person.dto'; +import { PersonService } from 'src/domain/person/person.service'; +import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; +import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; +import { IMediaRepository } from 'src/domain/repositories/media.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { FaceSearchResult, ISearchRepository } from 'src/domain/repositories/search.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { Colorspace, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { faceStub } from 'test/fixtures/face.stub'; +import { personStub } from 'test/fixtures/person.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newMachineLearningRepositoryMock } from 'test/repositories/machine-learning.repository.mock'; +import { newMediaRepositoryMock } from 'test/repositories/media.repository.mock'; +import { newMoveRepositoryMock } from 'test/repositories/move.repository.mock'; +import { newPersonRepositoryMock } from 'test/repositories/person.repository.mock'; +import { newSearchRepositoryMock } from 'test/repositories/search.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; import { IsNull } from 'typeorm'; -import { BulkIdErrorReason } from '../asset'; -import { CacheControl, ImmichFileResponse } from '../domain.util'; -import { JobName } from '../job'; -import { - FaceSearchResult, - IAssetRepository, - ICryptoRepository, - IJobRepository, - IMachineLearningRepository, - IMediaRepository, - IMoveRepository, - IPersonRepository, - ISearchRepository, - IStorageRepository, - ISystemConfigRepository, - JobStatus, - WithoutProperty, -} from '../repositories'; -import { PersonResponseDto, mapFaces, mapPerson } from './person.dto'; -import { PersonService } from './person.service'; const responseDto: PersonResponseDto = { id: 'person-1', diff --git a/server/src/domain/person/person.service.ts b/server/src/domain/person/person.service.ts index 1a2233f3c..1928191a3 100644 --- a/server/src/domain/person/person.service.ts +++ b/server/src/domain/person/person.service.ts @@ -1,35 +1,13 @@ -import { PersonEntity } from '@app/infra/entities'; -import { PersonPathType } from '@app/infra/entities/move.entity'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common'; -import { IsNull } from 'typeorm'; -import { AccessCore, Permission } from '../access'; -import { AssetResponseDto, BulkIdErrorReason, BulkIdResponseDto, mapAsset } from '../asset'; -import { AuthDto } from '../auth'; -import { mimeTypes } from '../domain.constant'; -import { CacheControl, ImmichFileResponse, usePagination } from '../domain.util'; -import { IBaseJob, IDeferrableJob, IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from '../job'; -import { FACE_THUMBNAIL_SIZE } from '../media'; -import { - CropOptions, - IAccessRepository, - IAssetRepository, - ICryptoRepository, - IJobRepository, - IMachineLearningRepository, - IMediaRepository, - IMoveRepository, - IPersonRepository, - ISearchRepository, - IStorageRepository, - ISystemConfigRepository, - JobItem, - JobStatus, - UpdateFacesData, - WithoutProperty, -} from '../repositories'; -import { StorageCore } from '../storage'; -import { SystemConfigCore } from '../system-config'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { BulkIdErrorReason, BulkIdResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { mimeTypes } from 'src/domain/domain.constant'; +import { CacheControl, ImmichFileResponse, usePagination } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; +import { IBaseJob, IDeferrableJob, IEntityJob } from 'src/domain/job/job.interface'; +import { FACE_THUMBNAIL_SIZE } from 'src/domain/media/media.constant'; import { AssetFaceResponseDto, AssetFaceUpdateDto, @@ -44,7 +22,24 @@ import { PersonUpdateDto, mapFaces, mapPerson, -} from './person.dto'; +} from 'src/domain/person/person.dto'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IJobRepository, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; +import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; +import { CropOptions, IMediaRepository } from 'src/domain/repositories/media.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository, UpdateFacesData } from 'src/domain/repositories/person.repository'; +import { ISearchRepository } from 'src/domain/repositories/search.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { StorageCore } from 'src/domain/storage/storage.core'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { PersonPathType } from 'src/infra/entities/move.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; +import { ImmichLogger } from 'src/infra/logger'; +import { IsNull } from 'typeorm'; @Injectable() export class PersonService { @@ -64,7 +59,7 @@ export class PersonService { @Inject(IStorageRepository) private storageRepository: IStorageRepository, @Inject(IJobRepository) private jobRepository: IJobRepository, @Inject(ISearchRepository) private smartInfoRepository: ISearchRepository, - @Inject(ICryptoRepository) private cryptoRepository: ICryptoRepository, + @Inject(ICryptoRepository) cryptoRepository: ICryptoRepository, ) { this.access = AccessCore.create(accessRepository); this.configCore = SystemConfigCore.create(configRepository); diff --git a/server/src/domain/repositories/activity.repository.ts b/server/src/domain/repositories/activity.repository.ts index 6f5476a28..39eb5da6b 100644 --- a/server/src/domain/repositories/activity.repository.ts +++ b/server/src/domain/repositories/activity.repository.ts @@ -1,5 +1,5 @@ -import { ActivityEntity } from '@app/infra/entities/activity.entity'; -import { ActivitySearch } from '@app/infra/repositories'; +import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { ActivitySearch } from 'src/infra/repositories/activity.repository'; export const IActivityRepository = 'IActivityRepository'; diff --git a/server/src/domain/repositories/album.repository.ts b/server/src/domain/repositories/album.repository.ts index eb4d4bf3d..213309412 100644 --- a/server/src/domain/repositories/album.repository.ts +++ b/server/src/domain/repositories/album.repository.ts @@ -1,4 +1,4 @@ -import { AlbumEntity } from '@app/infra/entities'; +import { AlbumEntity } from 'src/infra/entities/album.entity'; export const IAlbumRepository = 'IAlbumRepository'; diff --git a/server/src/domain/repositories/api-key.repository.ts b/server/src/domain/repositories/api-key.repository.ts index 60f26f235..ff6d97dd5 100644 --- a/server/src/domain/repositories/api-key.repository.ts +++ b/server/src/domain/repositories/api-key.repository.ts @@ -1,4 +1,4 @@ -import { APIKeyEntity } from '@app/infra/entities'; +import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; export const IKeyRepository = 'IKeyRepository'; diff --git a/server/src/domain/repositories/asset-stack.repository.ts b/server/src/domain/repositories/asset-stack.repository.ts index 66201ea3a..32c45b0d1 100644 --- a/server/src/domain/repositories/asset-stack.repository.ts +++ b/server/src/domain/repositories/asset-stack.repository.ts @@ -1,4 +1,4 @@ -import { AssetStackEntity } from '@app/infra/entities/asset-stack.entity'; +import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; export const IAssetStackRepository = 'IAssetStackRepository'; diff --git a/server/src/domain/repositories/asset.repository.ts b/server/src/domain/repositories/asset.repository.ts index c504bbb7f..e8bbdeb38 100644 --- a/server/src/domain/repositories/asset.repository.ts +++ b/server/src/domain/repositories/asset.repository.ts @@ -1,7 +1,11 @@ -import { AssetSearchOptions, ReverseGeocodeResult, SearchExploreItem } from '@app/domain'; -import { AssetEntity, AssetJobStatusEntity, AssetOrder, AssetType, ExifEntity } from '@app/infra/entities'; +import { Paginated, PaginationOptions } from 'src/domain/domain.util'; +import { ReverseGeocodeResult } from 'src/domain/repositories/metadata.repository'; +import { AssetSearchOptions, SearchExploreItem } from 'src/domain/repositories/search.repository'; +import { AssetOrder } from 'src/infra/entities/album.entity'; +import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; import { FindOptionsRelations, FindOptionsSelect } from 'typeorm'; -import { Paginated, PaginationOptions } from '../domain.util'; export type AssetStats = Record; diff --git a/server/src/domain/repositories/audit.repository.ts b/server/src/domain/repositories/audit.repository.ts index 774ab1e42..36112bfb8 100644 --- a/server/src/domain/repositories/audit.repository.ts +++ b/server/src/domain/repositories/audit.repository.ts @@ -1,4 +1,4 @@ -import { AuditEntity, DatabaseAction, EntityType } from '@app/infra/entities'; +import { AuditEntity, DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; export const IAuditRepository = 'IAuditRepository'; diff --git a/server/src/domain/repositories/communication.repository.ts b/server/src/domain/repositories/communication.repository.ts index 3efbbcb5e..38315a9bb 100644 --- a/server/src/domain/repositories/communication.repository.ts +++ b/server/src/domain/repositories/communication.repository.ts @@ -1,5 +1,6 @@ -import { AssetResponseDto, ReleaseNotification, ServerVersionResponseDto } from '@app/domain'; -import { SystemConfig } from '@app/infra/entities'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; +import { ReleaseNotification, ServerVersionResponseDto } from 'src/domain/server-info/server-info.dto'; +import { SystemConfig } from 'src/infra/entities/system-config.entity'; export const ICommunicationRepository = 'ICommunicationRepository'; diff --git a/server/src/domain/repositories/database.repository.ts b/server/src/domain/repositories/database.repository.ts index 55911e7ce..e87775c3e 100644 --- a/server/src/domain/repositories/database.repository.ts +++ b/server/src/domain/repositories/database.repository.ts @@ -1,4 +1,4 @@ -import { Version } from '../domain.constant'; +import { Version } from 'src/domain/domain.constant'; export enum DatabaseExtension { CUBE = 'cube', diff --git a/server/src/domain/repositories/index.ts b/server/src/domain/repositories/index.ts deleted file mode 100644 index 636abd2be..000000000 --- a/server/src/domain/repositories/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -export * from './access.repository'; -export * from './activity.repository'; -export * from './album.repository'; -export * from './api-key.repository'; -export * from './asset-stack.repository'; -export * from './asset.repository'; -export * from './audit.repository'; -export * from './communication.repository'; -export * from './crypto.repository'; -export * from './database.repository'; -export * from './job.repository'; -export * from './library.repository'; -export * from './machine-learning.repository'; -export * from './media.repository'; -export * from './metadata.repository'; -export * from './move.repository'; -export * from './partner.repository'; -export * from './person.repository'; -export * from './search.repository'; -export * from './server-info.repository'; -export * from './shared-link.repository'; -export * from './storage.repository'; -export * from './system-config.repository'; -export * from './system-metadata.repository'; -export * from './tag.repository'; -export * from './user-token.repository'; -export * from './user.repository'; diff --git a/server/src/domain/repositories/job.repository.ts b/server/src/domain/repositories/job.repository.ts index 3d31dd16b..023f6a8e9 100644 --- a/server/src/domain/repositories/job.repository.ts +++ b/server/src/domain/repositories/job.repository.ts @@ -1,5 +1,4 @@ -import { JobName, QueueName } from '../job/job.constants'; - +import { JobName, QueueName } from 'src/domain/job/job.constants'; import { IAssetDeletionJob, IBaseJob, @@ -9,7 +8,7 @@ import { ILibraryFileJob, ILibraryRefreshJob, ISidecarWriteJob, -} from '../job/job.interface'; +} from 'src/domain/job/job.interface'; export interface JobCounts { active: number; diff --git a/server/src/domain/repositories/library.repository.ts b/server/src/domain/repositories/library.repository.ts index 395373bcc..39b94f87c 100644 --- a/server/src/domain/repositories/library.repository.ts +++ b/server/src/domain/repositories/library.repository.ts @@ -1,5 +1,5 @@ -import { LibraryEntity, LibraryType } from '@app/infra/entities'; -import { LibraryStatsResponseDto } from '../library/library.dto'; +import { LibraryStatsResponseDto } from 'src/domain/library/library.dto'; +import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; export const ILibraryRepository = 'ILibraryRepository'; diff --git a/server/src/domain/repositories/machine-learning.repository.ts b/server/src/domain/repositories/machine-learning.repository.ts index f327a7a70..d11e2e8f7 100644 --- a/server/src/domain/repositories/machine-learning.repository.ts +++ b/server/src/domain/repositories/machine-learning.repository.ts @@ -1,4 +1,4 @@ -import { CLIPConfig, RecognitionConfig } from '../smart-info/dto'; +import { CLIPConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; export const IMachineLearningRepository = 'IMachineLearningRepository'; diff --git a/server/src/domain/repositories/media.repository.ts b/server/src/domain/repositories/media.repository.ts index ed6f88449..09bcd7eef 100644 --- a/server/src/domain/repositories/media.repository.ts +++ b/server/src/domain/repositories/media.repository.ts @@ -1,5 +1,5 @@ -import { TranscodeTarget, VideoCodec } from '@app/infra/entities'; import { Writable } from 'node:stream'; +import { TranscodeTarget, VideoCodec } from 'src/infra/entities/system-config.entity'; export const IMediaRepository = 'IMediaRepository'; diff --git a/server/src/domain/repositories/move.repository.ts b/server/src/domain/repositories/move.repository.ts index 20caa117f..eb191021f 100644 --- a/server/src/domain/repositories/move.repository.ts +++ b/server/src/domain/repositories/move.repository.ts @@ -1,4 +1,4 @@ -import { MoveEntity, PathType } from '@app/infra/entities'; +import { MoveEntity, PathType } from 'src/infra/entities/move.entity'; export const IMoveRepository = 'IMoveRepository'; diff --git a/server/src/domain/repositories/partner.repository.ts b/server/src/domain/repositories/partner.repository.ts index f0409b67a..5606fc495 100644 --- a/server/src/domain/repositories/partner.repository.ts +++ b/server/src/domain/repositories/partner.repository.ts @@ -1,4 +1,4 @@ -import { PartnerEntity } from '@app/infra/entities'; +import { PartnerEntity } from 'src/infra/entities/partner.entity'; export interface PartnerIds { sharedById: string; diff --git a/server/src/domain/repositories/person.repository.ts b/server/src/domain/repositories/person.repository.ts index 85c11fe92..93787f7b9 100644 --- a/server/src/domain/repositories/person.repository.ts +++ b/server/src/domain/repositories/person.repository.ts @@ -1,6 +1,8 @@ -import { AssetEntity, AssetFaceEntity, PersonEntity } from '@app/infra/entities'; +import { Paginated, PaginationOptions } from 'src/domain/domain.util'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; import { FindManyOptions, FindOptionsRelations, FindOptionsSelect } from 'typeorm'; -import { Paginated, PaginationOptions } from '../domain.util'; export const IPersonRepository = 'IPersonRepository'; diff --git a/server/src/domain/repositories/search.repository.ts b/server/src/domain/repositories/search.repository.ts index bd4face86..3dc9c1ea5 100644 --- a/server/src/domain/repositories/search.repository.ts +++ b/server/src/domain/repositories/search.repository.ts @@ -1,5 +1,8 @@ -import { AssetEntity, AssetFaceEntity, AssetType, GeodataPlacesEntity, SmartInfoEntity } from '@app/infra/entities'; -import { Paginated } from '../domain.util'; +import { Paginated } from 'src/domain/domain.util'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; +import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; export const ISearchRepository = 'ISearchRepository'; diff --git a/server/src/domain/repositories/shared-link.repository.ts b/server/src/domain/repositories/shared-link.repository.ts index 0f0255d0a..0d5e8eca7 100644 --- a/server/src/domain/repositories/shared-link.repository.ts +++ b/server/src/domain/repositories/shared-link.repository.ts @@ -1,4 +1,4 @@ -import { SharedLinkEntity } from '@app/infra/entities'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; export const ISharedLinkRepository = 'ISharedLinkRepository'; diff --git a/server/src/domain/repositories/storage.repository.ts b/server/src/domain/repositories/storage.repository.ts index a052596c0..505e535b0 100644 --- a/server/src/domain/repositories/storage.repository.ts +++ b/server/src/domain/repositories/storage.repository.ts @@ -2,7 +2,7 @@ import { WatchOptions } from 'chokidar'; import { Stats } from 'node:fs'; import { FileReadOptions } from 'node:fs/promises'; import { Readable } from 'node:stream'; -import { CrawlOptionsDto } from '../library'; +import { CrawlOptionsDto } from 'src/domain/library/library.dto'; export interface ImmichReadStream { stream: Readable; diff --git a/server/src/domain/repositories/system-config.repository.ts b/server/src/domain/repositories/system-config.repository.ts index d154f6eff..86b311485 100644 --- a/server/src/domain/repositories/system-config.repository.ts +++ b/server/src/domain/repositories/system-config.repository.ts @@ -1,4 +1,4 @@ -import { SystemConfigEntity } from '@app/infra/entities'; +import { SystemConfigEntity } from 'src/infra/entities/system-config.entity'; export const ISystemConfigRepository = 'ISystemConfigRepository'; diff --git a/server/src/domain/repositories/system-metadata.repository.ts b/server/src/domain/repositories/system-metadata.repository.ts index 4d571953b..d28713226 100644 --- a/server/src/domain/repositories/system-metadata.repository.ts +++ b/server/src/domain/repositories/system-metadata.repository.ts @@ -1,4 +1,4 @@ -import { SystemMetadata } from '@app/infra/entities'; +import { SystemMetadata } from 'src/infra/entities/system-metadata.entity'; export const ISystemMetadataRepository = 'ISystemMetadataRepository'; diff --git a/server/src/domain/repositories/tag.repository.ts b/server/src/domain/repositories/tag.repository.ts index 4e6f583b4..47c3f40fa 100644 --- a/server/src/domain/repositories/tag.repository.ts +++ b/server/src/domain/repositories/tag.repository.ts @@ -1,4 +1,5 @@ -import { AssetEntity, TagEntity } from '@app/infra/entities'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { TagEntity } from 'src/infra/entities/tag.entity'; export const ITagRepository = 'ITagRepository'; diff --git a/server/src/domain/repositories/user-token.repository.ts b/server/src/domain/repositories/user-token.repository.ts index 713b3f1ef..2d342a2fc 100644 --- a/server/src/domain/repositories/user-token.repository.ts +++ b/server/src/domain/repositories/user-token.repository.ts @@ -1,4 +1,4 @@ -import { UserTokenEntity } from '@app/infra/entities'; +import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; export const IUserTokenRepository = 'IUserTokenRepository'; diff --git a/server/src/domain/repositories/user.repository.ts b/server/src/domain/repositories/user.repository.ts index efd950318..be5ef165d 100644 --- a/server/src/domain/repositories/user.repository.ts +++ b/server/src/domain/repositories/user.repository.ts @@ -1,4 +1,4 @@ -import { UserEntity } from '@app/infra/entities'; +import { UserEntity } from 'src/infra/entities/user.entity'; export interface UserListFilter { withDeleted?: boolean; diff --git a/server/src/domain/search/dto/index.ts b/server/src/domain/search/dto/index.ts deleted file mode 100644 index cd914d0ea..000000000 --- a/server/src/domain/search/dto/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './search.dto'; diff --git a/server/src/domain/search/dto/search-suggestion.dto.ts b/server/src/domain/search/dto/search-suggestion.dto.ts index 824a1066c..f2f70062a 100644 --- a/server/src/domain/search/dto/search-suggestion.dto.ts +++ b/server/src/domain/search/dto/search-suggestion.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional } from '../../domain.util'; +import { Optional } from 'src/domain/domain.util'; export enum SearchSuggestionType { COUNTRY = 'country', diff --git a/server/src/domain/search/dto/search.dto.ts b/server/src/domain/search/dto/search.dto.ts index 1bc67266a..0dcaa22fb 100644 --- a/server/src/domain/search/dto/search.dto.ts +++ b/server/src/domain/search/dto/search.dto.ts @@ -1,8 +1,10 @@ -import { AssetOrder, AssetType, GeodataPlacesEntity } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsInt, IsNotEmpty, IsString, Max, Min } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from '../../domain.util'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; +import { AssetOrder } from 'src/infra/entities/album.entity'; +import { AssetType } from 'src/infra/entities/asset.entity'; +import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; class BaseSearchDto { @ValidateUUID({ optional: true }) diff --git a/server/src/domain/search/index.ts b/server/src/domain/search/index.ts deleted file mode 100644 index 717439d3c..000000000 --- a/server/src/domain/search/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './dto'; -export * from './response-dto'; -export * from './search.service'; diff --git a/server/src/domain/search/response-dto/index.ts b/server/src/domain/search/response-dto/index.ts deleted file mode 100644 index f48856bca..000000000 --- a/server/src/domain/search/response-dto/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './search-explore.response.dto'; -export * from './search-response.dto'; diff --git a/server/src/domain/search/response-dto/search-explore.response.dto.ts b/server/src/domain/search/response-dto/search-explore.response.dto.ts index 37398d9de..33689b979 100644 --- a/server/src/domain/search/response-dto/search-explore.response.dto.ts +++ b/server/src/domain/search/response-dto/search-explore.response.dto.ts @@ -1,4 +1,4 @@ -import { AssetResponseDto } from '../../asset'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; class SearchExploreItem { value!: string; diff --git a/server/src/domain/search/response-dto/search-response.dto.ts b/server/src/domain/search/response-dto/search-response.dto.ts index 9dd65e7cc..53563a9ac 100644 --- a/server/src/domain/search/response-dto/search-response.dto.ts +++ b/server/src/domain/search/response-dto/search-response.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import { AlbumResponseDto } from '../../album'; -import { AssetResponseDto } from '../../asset'; +import { AlbumResponseDto } from 'src/domain/album/album-response.dto'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; class SearchFacetCountResponseDto { @ApiProperty({ type: 'integer' }) diff --git a/server/src/domain/search/search.service.spec.ts b/server/src/domain/search/search.service.spec.ts index b6edf1ece..ae5e94a76 100644 --- a/server/src/domain/search/search.service.spec.ts +++ b/server/src/domain/search/search.service.spec.ts @@ -1,28 +1,24 @@ -import { SystemConfigKey } from '@app/infra/entities'; -import { - assetStub, - authStub, - newAssetRepositoryMock, - newMachineLearningRepositoryMock, - newMetadataRepositoryMock, - newPartnerRepositoryMock, - newPersonRepositoryMock, - newSearchRepositoryMock, - newSystemConfigRepositoryMock, - personStub, -} from '@test'; -import { mapAsset } from '../asset'; -import { - IAssetRepository, - IMachineLearningRepository, - IMetadataRepository, - IPartnerRepository, - IPersonRepository, - ISearchRepository, - ISystemConfigRepository, -} from '../repositories'; -import { SearchDto } from './dto'; -import { SearchService } from './search.service'; +import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; +import { IMetadataRepository } from 'src/domain/repositories/metadata.repository'; +import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { ISearchRepository } from 'src/domain/repositories/search.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SearchDto } from 'src/domain/search/dto/search.dto'; +import { SearchService } from 'src/domain/search/search.service'; +import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { personStub } from 'test/fixtures/person.stub'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newMachineLearningRepositoryMock } from 'test/repositories/machine-learning.repository.mock'; +import { newMetadataRepositoryMock } from 'test/repositories/metadata.repository.mock'; +import { newPartnerRepositoryMock } from 'test/repositories/partner.repository.mock'; +import { newPersonRepositoryMock } from 'test/repositories/person.repository.mock'; +import { newSearchRepositoryMock } from 'test/repositories/search.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; jest.useFakeTimers(); diff --git a/server/src/domain/search/search.service.ts b/server/src/domain/search/search.service.ts index 4b15dfd51..bb7e31bfa 100644 --- a/server/src/domain/search/search.service.ts +++ b/server/src/domain/search/search.service.ts @@ -1,20 +1,15 @@ -import { AssetEntity, AssetOrder } from '@app/infra/entities'; import { Inject, Injectable } from '@nestjs/common'; -import { AssetResponseDto, mapAsset } from '../asset'; -import { AuthDto } from '../auth'; -import { PersonResponseDto } from '../person'; -import { - IAssetRepository, - IMachineLearningRepository, - IMetadataRepository, - IPartnerRepository, - IPersonRepository, - ISearchRepository, - ISystemConfigRepository, - SearchExploreItem, - SearchStrategy, -} from '../repositories'; -import { FeatureFlag, SystemConfigCore } from '../system-config'; +import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { PersonResponseDto } from 'src/domain/person/person.dto'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; +import { IMetadataRepository } from 'src/domain/repositories/metadata.repository'; +import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { ISearchRepository, SearchExploreItem, SearchStrategy } from 'src/domain/repositories/search.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SearchSuggestionRequestDto, SearchSuggestionType } from 'src/domain/search/dto/search-suggestion.dto'; import { MetadataSearchDto, PlacesResponseDto, @@ -23,9 +18,11 @@ import { SearchPlacesDto, SmartSearchDto, mapPlaces, -} from './dto'; -import { SearchSuggestionRequestDto, SearchSuggestionType } from './dto/search-suggestion.dto'; -import { SearchResponseDto } from './response-dto'; +} from 'src/domain/search/dto/search.dto'; +import { SearchResponseDto } from 'src/domain/search/response-dto/search-response.dto'; +import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetOrder } from 'src/infra/entities/album.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; @Injectable() export class SearchService { diff --git a/server/src/domain/server-info/index.ts b/server/src/domain/server-info/index.ts deleted file mode 100644 index 74a46a52b..000000000 --- a/server/src/domain/server-info/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './server-info.dto'; -export * from './server-info.service'; diff --git a/server/src/domain/server-info/server-info.dto.ts b/server/src/domain/server-info/server-info.dto.ts index 99d4f1566..07f99a874 100644 --- a/server/src/domain/server-info/server-info.dto.ts +++ b/server/src/domain/server-info/server-info.dto.ts @@ -1,7 +1,8 @@ -import { FeatureFlags, IVersion, type VersionType } from '@app/domain'; import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger'; import type { DateTime } from 'luxon'; -import { SystemConfigThemeDto } from '../system-config/dto/system-config-theme.dto'; +import { IVersion, VersionType } from 'src/domain/domain.constant'; +import { SystemConfigThemeDto } from 'src/domain/system-config/dto/system-config-theme.dto'; +import { FeatureFlags } from 'src/domain/system-config/system-config.core'; export class ServerPingResponse { @ApiResponseProperty({ type: String, example: 'pong' }) diff --git a/server/src/domain/server-info/server-info.service.spec.ts b/server/src/domain/server-info/server-info.service.spec.ts index 8c90f8107..41bc8fb6f 100644 --- a/server/src/domain/server-info/server-info.service.spec.ts +++ b/server/src/domain/server-info/server-info.service.spec.ts @@ -1,22 +1,18 @@ -import { SystemMetadataKey } from '@app/infra/entities'; -import { - newCommunicationRepositoryMock, - newServerInfoRepositoryMock, - newStorageRepositoryMock, - newSystemConfigRepositoryMock, - newSystemMetadataRepositoryMock, - newUserRepositoryMock, -} from '@test'; -import { serverVersion } from '../domain.constant'; -import { - ICommunicationRepository, - IServerInfoRepository, - IStorageRepository, - ISystemConfigRepository, - ISystemMetadataRepository, - IUserRepository, -} from '../repositories'; -import { ServerInfoService } from './server-info.service'; +import { serverVersion } from 'src/domain/domain.constant'; +import { ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { ServerInfoService } from 'src/domain/server-info/server-info.service'; +import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; +import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; +import { newServerInfoRepositoryMock } from 'test/repositories/system-info.repository.mock'; +import { newSystemMetadataRepositoryMock } from 'test/repositories/system-metadata.repository.mock'; +import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; describe(ServerInfoService.name, () => { let sut: ServerInfoService; diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index 04b3c4b6e..77c675b87 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -1,21 +1,13 @@ -import { SystemMetadataKey } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { Inject, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; -import { Version, isDev, mimeTypes, serverVersion } from '../domain.constant'; -import { asHumanReadable } from '../domain.util'; -import { - ClientEvent, - ICommunicationRepository, - IServerInfoRepository, - IStorageRepository, - ISystemConfigRepository, - ISystemMetadataRepository, - IUserRepository, - UserStatsQueryResponse, -} from '../repositories'; -import { StorageCore, StorageFolder } from '../storage'; -import { SystemConfigCore } from '../system-config'; +import { Version, isDev, mimeTypes, serverVersion } from 'src/domain/domain.constant'; +import { asHumanReadable } from 'src/domain/domain.util'; +import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; +import { IUserRepository, UserStatsQueryResponse } from 'src/domain/repositories/user.repository'; import { ServerConfigDto, ServerFeaturesDto, @@ -24,7 +16,11 @@ import { ServerPingResponse, ServerStatsResponseDto, UsageByUserDto, -} from './server-info.dto'; +} from 'src/domain/server-info/server-info.dto'; +import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class ServerInfoService { diff --git a/server/src/domain/shared-link/index.ts b/server/src/domain/shared-link/index.ts deleted file mode 100644 index 0b4720850..000000000 --- a/server/src/domain/shared-link/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './shared-link-response.dto'; -export * from './shared-link.dto'; -export * from './shared-link.service'; diff --git a/server/src/domain/shared-link/shared-link-response.dto.ts b/server/src/domain/shared-link/shared-link-response.dto.ts index b16a578f4..034b45f1c 100644 --- a/server/src/domain/shared-link/shared-link-response.dto.ts +++ b/server/src/domain/shared-link/shared-link-response.dto.ts @@ -1,8 +1,8 @@ -import { SharedLinkEntity, SharedLinkType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import _ from 'lodash'; -import { AlbumResponseDto, mapAlbumWithoutAssets } from '../album'; -import { AssetResponseDto, mapAsset } from '../asset'; +import { AlbumResponseDto, mapAlbumWithoutAssets } from 'src/domain/album/album-response.dto'; +import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { SharedLinkEntity, SharedLinkType } from 'src/infra/entities/shared-link.entity'; export class SharedLinkResponseDto { id!: string; diff --git a/server/src/domain/shared-link/shared-link.dto.ts b/server/src/domain/shared-link/shared-link.dto.ts index 550ed70ea..ea529979c 100644 --- a/server/src/domain/shared-link/shared-link.dto.ts +++ b/server/src/domain/shared-link/shared-link.dto.ts @@ -1,7 +1,7 @@ -import { SharedLinkType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from '../domain.util'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; +import { SharedLinkType } from 'src/infra/entities/shared-link.entity'; export class SharedLinkCreateDto { @IsEnum(SharedLinkType) diff --git a/server/src/domain/shared-link/shared-link.service.spec.ts b/server/src/domain/shared-link/shared-link.service.spec.ts index f0d0715a3..6e2da5a64 100644 --- a/server/src/domain/shared-link/shared-link.service.spec.ts +++ b/server/src/domain/shared-link/shared-link.service.spec.ts @@ -1,20 +1,17 @@ -import { SharedLinkType } from '@app/infra/entities'; import { BadRequestException, ForbiddenException, UnauthorizedException } from '@nestjs/common'; -import { - IAccessRepositoryMock, - albumStub, - assetStub, - authStub, - newAccessRepositoryMock, - newCryptoRepositoryMock, - newSharedLinkRepositoryMock, - sharedLinkResponseStub, - sharedLinkStub, -} from '@test'; import _ from 'lodash'; -import { AssetIdErrorReason } from '../asset'; -import { ICryptoRepository, ISharedLinkRepository } from '../repositories'; -import { SharedLinkService } from './shared-link.service'; +import { AssetIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; +import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; +import { SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { albumStub } from 'test/fixtures/album.stub'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { sharedLinkResponseStub, sharedLinkStub } from 'test/fixtures/shared-link.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newSharedLinkRepositoryMock } from 'test/repositories/shared-link.repository.mock'; describe(SharedLinkService.name, () => { let sut: SharedLinkService; diff --git a/server/src/domain/shared-link/shared-link.service.ts b/server/src/domain/shared-link/shared-link.service.ts index 54e6f6052..a5a28b374 100644 --- a/server/src/domain/shared-link/shared-link.service.ts +++ b/server/src/domain/shared-link/shared-link.service.ts @@ -1,12 +1,20 @@ -import { AssetEntity, SharedLinkEntity, SharedLinkType } from '@app/infra/entities'; import { BadRequestException, ForbiddenException, Inject, Injectable, UnauthorizedException } from '@nestjs/common'; -import { AccessCore, Permission } from '../access'; -import { AssetIdErrorReason, AssetIdsDto, AssetIdsResponseDto } from '../asset'; -import { AuthDto } from '../auth'; -import { OpenGraphTags } from '../domain.util'; -import { IAccessRepository, ICryptoRepository, ISharedLinkRepository } from '../repositories'; -import { SharedLinkResponseDto, mapSharedLink, mapSharedLinkWithoutMetadata } from './shared-link-response.dto'; -import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from './shared-link.dto'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; +import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { OpenGraphTags } from 'src/domain/domain.util'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; +import { + SharedLinkResponseDto, + mapSharedLink, + mapSharedLinkWithoutMetadata, +} from 'src/domain/shared-link/shared-link-response.dto'; +import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { SharedLinkEntity, SharedLinkType } from 'src/infra/entities/shared-link.entity'; @Injectable() export class SharedLinkService { diff --git a/server/src/domain/smart-info/dto/index.ts b/server/src/domain/smart-info/dto/index.ts deleted file mode 100644 index aa672a787..000000000 --- a/server/src/domain/smart-info/dto/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './model-config.dto'; diff --git a/server/src/domain/smart-info/dto/model-config.dto.ts b/server/src/domain/smart-info/dto/model-config.dto.ts index b9e27669f..0b12e1cc6 100644 --- a/server/src/domain/smart-info/dto/model-config.dto.ts +++ b/server/src/domain/smart-info/dto/model-config.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsNotEmpty, IsNumber, IsString, Max, Min } from 'class-validator'; -import { Optional, ValidateBoolean } from '../../domain.util'; -import { CLIPMode, ModelType } from '../../repositories'; +import { Optional, ValidateBoolean } from 'src/domain/domain.util'; +import { CLIPMode, ModelType } from 'src/domain/repositories/machine-learning.repository'; export class ModelConfig { @ValidateBoolean() diff --git a/server/src/domain/smart-info/index.ts b/server/src/domain/smart-info/index.ts deleted file mode 100644 index a0cbeecf4..000000000 --- a/server/src/domain/smart-info/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './dto'; -export * from './smart-info.service'; diff --git a/server/src/domain/smart-info/smart-info.service.spec.ts b/server/src/domain/smart-info/smart-info.service.spec.ts index 712c2b6a7..e83e823db 100644 --- a/server/src/domain/smart-info/smart-info.service.spec.ts +++ b/server/src/domain/smart-info/smart-info.service.spec.ts @@ -1,25 +1,21 @@ -import { AssetEntity, SystemConfigKey } from '@app/infra/entities'; -import { - assetStub, - newAssetRepositoryMock, - newDatabaseRepositoryMock, - newJobRepositoryMock, - newMachineLearningRepositoryMock, - newSearchRepositoryMock, - newSystemConfigRepositoryMock, -} from '@test'; -import { JobName } from '../job'; -import { - IAssetRepository, - IDatabaseRepository, - IJobRepository, - IMachineLearningRepository, - ISearchRepository, - ISystemConfigRepository, - WithoutProperty, -} from '../repositories'; -import { cleanModelName, getCLIPModelInfo } from './smart-info.constant'; -import { SmartInfoService } from './smart-info.service'; +import { JobName } from 'src/domain/job/job.constants'; +import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; +import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; +import { ISearchRepository } from 'src/domain/repositories/search.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { cleanModelName, getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; +import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newMachineLearningRepositoryMock } from 'test/repositories/machine-learning.repository.mock'; +import { newSearchRepositoryMock } from 'test/repositories/search.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; const asset = { id: 'asset-1', diff --git a/server/src/domain/smart-info/smart-info.service.ts b/server/src/domain/smart-info/smart-info.service.ts index b7dd1a91f..8f20f56d5 100644 --- a/server/src/domain/smart-info/smart-info.service.ts +++ b/server/src/domain/smart-info/smart-info.service.ts @@ -1,19 +1,15 @@ -import { ImmichLogger } from '@app/infra/logger'; import { Inject, Injectable } from '@nestjs/common'; -import { usePagination } from '../domain.util'; -import { IBaseJob, IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from '../job'; -import { - DatabaseLock, - IAssetRepository, - IDatabaseRepository, - IJobRepository, - IMachineLearningRepository, - ISearchRepository, - ISystemConfigRepository, - JobStatus, - WithoutProperty, -} from '../repositories'; -import { SystemConfigCore } from '../system-config'; +import { usePagination } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; +import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; +import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; +import { DatabaseLock, IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; +import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; +import { ISearchRepository } from 'src/domain/repositories/search.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class SmartInfoService { diff --git a/server/src/domain/storage-template/index.ts b/server/src/domain/storage-template/index.ts deleted file mode 100644 index f90e36389..000000000 --- a/server/src/domain/storage-template/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './storage-template.service'; diff --git a/server/src/domain/storage-template/storage-template.service.spec.ts b/server/src/domain/storage-template/storage-template.service.spec.ts index a81e27c8f..f73709035 100644 --- a/server/src/domain/storage-template/storage-template.service.spec.ts +++ b/server/src/domain/storage-template/storage-template.service.spec.ts @@ -1,34 +1,30 @@ -import { - IAlbumRepository, - IAssetRepository, - ICryptoRepository, - IDatabaseRepository, - IMoveRepository, - IPersonRepository, - IStorageRepository, - ISystemConfigRepository, - IUserRepository, - JobStatus, - StorageTemplateService, - defaults, -} from '@app/domain'; -import { AssetPathType, SystemConfig, SystemConfigKey } from '@app/infra/entities'; -import { - assetStub, - newAlbumRepositoryMock, - newAssetRepositoryMock, - newCryptoRepositoryMock, - newDatabaseRepositoryMock, - newMoveRepositoryMock, - newPersonRepositoryMock, - newStorageRepositoryMock, - newSystemConfigRepositoryMock, - newUserRepositoryMock, - userStub, -} from '@test'; import { when } from 'jest-when'; import { Stats } from 'node:fs'; -import { SystemConfigCore } from '../system-config'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { JobStatus } from 'src/domain/repositories/job.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; +import { SystemConfigCore, defaults } from 'src/domain/system-config/system-config.core'; +import { AssetPathType } from 'src/infra/entities/move.entity'; +import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { userStub } from 'test/fixtures/user.stub'; +import { newAlbumRepositoryMock } from 'test/repositories/album.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; +import { newMoveRepositoryMock } from 'test/repositories/move.repository.mock'; +import { newPersonRepositoryMock } from 'test/repositories/person.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; +import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; describe(StorageTemplateService.name, () => { let sut: StorageTemplateService; diff --git a/server/src/domain/storage-template/storage-template.service.ts b/server/src/domain/storage-template/storage-template.service.ts index ffdbfbefb..8028eb359 100644 --- a/server/src/domain/storage-template/storage-template.service.ts +++ b/server/src/domain/storage-template/storage-template.service.ts @@ -1,29 +1,24 @@ -import { AssetEntity, AssetPathType, AssetType, SystemConfig } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { Inject, Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import handlebar from 'handlebars'; -import * as luxon from 'luxon'; +import { DateTime } from 'luxon'; import path from 'node:path'; import sanitize from 'sanitize-filename'; -import { getLivePhotoMotionFilename, usePagination } from '../domain.util'; -import { IEntityJob, JOBS_ASSET_PAGINATION_SIZE } from '../job'; -import { - DatabaseLock, - IAlbumRepository, - IAssetRepository, - ICryptoRepository, - IDatabaseRepository, - IMoveRepository, - IPersonRepository, - IStorageRepository, - ISystemConfigRepository, - IUserRepository, - InternalEvent, - InternalEventMap, - JobStatus, -} from '../repositories'; -import { StorageCore, StorageFolder } from '../storage'; +import { getLivePhotoMotionFilename, usePagination } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; +import { IEntityJob } from 'src/domain/job/job.interface'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { InternalEvent, InternalEventMap } from 'src/domain/repositories/communication.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { DatabaseLock, IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { JobStatus } from 'src/domain/repositories/job.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; import { supportedDayTokens, supportedHourTokens, @@ -32,8 +27,12 @@ import { supportedSecondTokens, supportedWeekTokens, supportedYearTokens, -} from '../system-config'; -import { SystemConfigCore } from '../system-config/system-config.core'; +} from 'src/domain/system-config/system-config.constants'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { AssetPathType } from 'src/infra/entities/move.entity'; +import { SystemConfig } from 'src/infra/entities/system-config.entity'; +import { ImmichLogger } from 'src/infra/logger'; export interface MoveAssetMetadata { storageLabel: string | null; @@ -312,7 +311,7 @@ export class StorageTemplateService { const systemTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone; const zone = asset.exifInfo?.timeZone || systemTimeZone; - const dt = luxon.DateTime.fromJSDate(asset.fileCreatedAt, { zone }); + const dt = DateTime.fromJSDate(asset.fileCreatedAt, { zone }); const dateTokens = [ ...supportedYearTokens, diff --git a/server/src/domain/storage/index.ts b/server/src/domain/storage/index.ts deleted file mode 100644 index bdea086bd..000000000 --- a/server/src/domain/storage/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './storage.core'; -export * from './storage.service'; diff --git a/server/src/domain/storage/storage.core.ts b/server/src/domain/storage/storage.core.ts index 5cf65ad7c..1768227ea 100644 --- a/server/src/domain/storage/storage.core.ts +++ b/server/src/domain/storage/storage.core.ts @@ -1,16 +1,16 @@ -import { SystemConfigCore } from '@app/domain/system-config'; -import { AssetEntity, AssetPathType, PathType, PersonEntity, PersonPathType } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { dirname, join, resolve } from 'node:path'; -import { APP_MEDIA_LOCATION } from '../domain.constant'; -import { - IAssetRepository, - ICryptoRepository, - IMoveRepository, - IPersonRepository, - IStorageRepository, - ISystemConfigRepository, -} from '../repositories'; +import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetPathType, PathType, PersonPathType } from 'src/infra/entities/move.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; +import { ImmichLogger } from 'src/infra/logger'; export enum StorageFolder { ENCODED_VIDEO = 'encoded-video', @@ -46,8 +46,8 @@ export class StorageCore { private moveRepository: IMoveRepository, private personRepository: IPersonRepository, private cryptoRepository: ICryptoRepository, - private systemConfigRepository: ISystemConfigRepository, private repository: IStorageRepository, + systemConfigRepository: ISystemConfigRepository, ) { this.configCore = SystemConfigCore.create(systemConfigRepository); } @@ -66,8 +66,8 @@ export class StorageCore { moveRepository, personRepository, cryptoRepository, - configRepository, repository, + configRepository, ); } diff --git a/server/src/domain/storage/storage.service.spec.ts b/server/src/domain/storage/storage.service.spec.ts index 785891086..9181af76e 100644 --- a/server/src/domain/storage/storage.service.spec.ts +++ b/server/src/domain/storage/storage.service.spec.ts @@ -1,6 +1,6 @@ -import { newStorageRepositoryMock } from '@test'; -import { IStorageRepository } from '../repositories'; -import { StorageService } from './storage.service'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { StorageService } from 'src/domain/storage/storage.service'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; describe(StorageService.name, () => { let sut: StorageService; diff --git a/server/src/domain/storage/storage.service.ts b/server/src/domain/storage/storage.service.ts index 95c311881..08010231e 100644 --- a/server/src/domain/storage/storage.service.ts +++ b/server/src/domain/storage/storage.service.ts @@ -1,8 +1,9 @@ -import { ImmichLogger } from '@app/infra/logger'; import { Inject, Injectable } from '@nestjs/common'; -import { IDeleteFilesJob } from '../job'; -import { IStorageRepository, JobStatus } from '../repositories'; -import { StorageCore, StorageFolder } from './storage.core'; +import { IDeleteFilesJob } from 'src/domain/job/job.interface'; +import { JobStatus } from 'src/domain/repositories/job.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class StorageService { diff --git a/server/src/domain/system-config/dto/index.ts b/server/src/domain/system-config/dto/index.ts deleted file mode 100644 index 652e34cc5..000000000 --- a/server/src/domain/system-config/dto/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -export * from './system-config-ffmpeg.dto'; -export * from './system-config-library.dto'; -export * from './system-config-oauth.dto'; -export * from './system-config-password-login.dto'; -export * from './system-config-storage-template.dto'; -export * from './system-config-thumbnail.dto'; -export * from './system-config-trash.dto'; -export * from './system-config.dto'; diff --git a/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts b/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts index 3a219888f..99077176b 100644 --- a/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts +++ b/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts @@ -1,8 +1,15 @@ -import { AudioCodec, CQMode, ToneMapping, TranscodeHWAccel, TranscodePolicy, VideoCodec } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsInt, IsString, Max, Min } from 'class-validator'; -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; +import { + AudioCodec, + CQMode, + ToneMapping, + TranscodeHWAccel, + TranscodePolicy, + VideoCodec, +} from 'src/infra/entities/system-config.entity'; export class SystemConfigFFmpegDto { @IsInt() diff --git a/server/src/domain/system-config/dto/system-config-job.dto.ts b/server/src/domain/system-config/dto/system-config-job.dto.ts index 3307811d7..2769da327 100644 --- a/server/src/domain/system-config/dto/system-config-job.dto.ts +++ b/server/src/domain/system-config/dto/system-config-job.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsInt, IsObject, IsPositive, ValidateNested } from 'class-validator'; -import { ConcurrentQueueName, QueueName } from '../../job'; +import { ConcurrentQueueName, QueueName } from 'src/domain/job/job.constants'; export class JobSettingsDto { @IsInt() diff --git a/server/src/domain/system-config/dto/system-config-library.dto.ts b/server/src/domain/system-config/dto/system-config-library.dto.ts index 85ab62634..f322423df 100644 --- a/server/src/domain/system-config/dto/system-config-library.dto.ts +++ b/server/src/domain/system-config/dto/system-config-library.dto.ts @@ -9,7 +9,7 @@ import { ValidatorConstraint, ValidatorConstraintInterface, } from 'class-validator'; -import { ValidateBoolean, validateCronExpression } from '../../domain.util'; +import { ValidateBoolean, validateCronExpression } from 'src/domain/domain.util'; const isEnabled = (config: SystemConfigLibraryScanDto) => config.enabled; diff --git a/server/src/domain/system-config/dto/system-config-logging.dto.ts b/server/src/domain/system-config/dto/system-config-logging.dto.ts index 09f78fc86..0f1664ee3 100644 --- a/server/src/domain/system-config/dto/system-config-logging.dto.ts +++ b/server/src/domain/system-config/dto/system-config-logging.dto.ts @@ -1,7 +1,7 @@ -import { LogLevel } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; +import { LogLevel } from 'src/infra/entities/system-config.entity'; export class SystemConfigLoggingDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts b/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts index 435e68826..1b33d5920 100644 --- a/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts +++ b/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts @@ -1,7 +1,7 @@ import { Type } from 'class-transformer'; import { IsObject, IsUrl, ValidateIf, ValidateNested } from 'class-validator'; -import { ValidateBoolean } from '../../domain.util'; -import { CLIPConfig, RecognitionConfig } from '../../smart-info/dto/model-config.dto'; +import { ValidateBoolean } from 'src/domain/domain.util'; +import { CLIPConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; export class SystemConfigMachineLearningDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-map.dto.ts b/server/src/domain/system-config/dto/system-config-map.dto.ts index 9e21e2d5d..fb8aac593 100644 --- a/server/src/domain/system-config/dto/system-config-map.dto.ts +++ b/server/src/domain/system-config/dto/system-config-map.dto.ts @@ -1,5 +1,5 @@ import { IsString } from 'class-validator'; -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class SystemConfigMapDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts b/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts index 379f5643d..27afe1e68 100644 --- a/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts +++ b/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class SystemConfigNewVersionCheckDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-oauth.dto.ts b/server/src/domain/system-config/dto/system-config-oauth.dto.ts index 99779bdfe..13465b772 100644 --- a/server/src/domain/system-config/dto/system-config-oauth.dto.ts +++ b/server/src/domain/system-config/dto/system-config-oauth.dto.ts @@ -1,5 +1,5 @@ import { IsNotEmpty, IsNumber, IsString, IsUrl, Min, ValidateIf } from 'class-validator'; -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; const isEnabled = (config: SystemConfigOAuthDto) => config.enabled; const isOverrideEnabled = (config: SystemConfigOAuthDto) => config.mobileOverrideEnabled; diff --git a/server/src/domain/system-config/dto/system-config-password-login.dto.ts b/server/src/domain/system-config/dto/system-config-password-login.dto.ts index 279bcc5a6..3d98ae045 100644 --- a/server/src/domain/system-config/dto/system-config-password-login.dto.ts +++ b/server/src/domain/system-config/dto/system-config-password-login.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class SystemConfigPasswordLoginDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts b/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts index 11e0ae289..ad4bcaab6 100644 --- a/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts +++ b/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class SystemConfigReverseGeocodingDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-storage-template.dto.ts b/server/src/domain/system-config/dto/system-config-storage-template.dto.ts index 615fd8521..c35dcd476 100644 --- a/server/src/domain/system-config/dto/system-config-storage-template.dto.ts +++ b/server/src/domain/system-config/dto/system-config-storage-template.dto.ts @@ -1,5 +1,5 @@ import { IsNotEmpty, IsString } from 'class-validator'; -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class SystemConfigStorageTemplateDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts b/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts index c389ef77a..2f156894f 100644 --- a/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts +++ b/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts @@ -1,7 +1,7 @@ -import { Colorspace } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsInt, Max, Min } from 'class-validator'; +import { Colorspace } from 'src/infra/entities/system-config.entity'; export class SystemConfigThumbnailDto { @IsInt() diff --git a/server/src/domain/system-config/dto/system-config-trash.dto.ts b/server/src/domain/system-config/dto/system-config-trash.dto.ts index 482410703..8765b4ff1 100644 --- a/server/src/domain/system-config/dto/system-config-trash.dto.ts +++ b/server/src/domain/system-config/dto/system-config-trash.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsInt, Min } from 'class-validator'; -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class SystemConfigTrashDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config.dto.ts b/server/src/domain/system-config/dto/system-config.dto.ts index 4906e293e..4f97975bc 100644 --- a/server/src/domain/system-config/dto/system-config.dto.ts +++ b/server/src/domain/system-config/dto/system-config.dto.ts @@ -1,22 +1,22 @@ -import { SystemConfig } from '@app/infra/entities'; import { Type } from 'class-transformer'; import { IsObject, ValidateNested } from 'class-validator'; -import { SystemConfigFFmpegDto } from './system-config-ffmpeg.dto'; -import { SystemConfigJobDto } from './system-config-job.dto'; -import { SystemConfigLibraryDto } from './system-config-library.dto'; -import { SystemConfigLoggingDto } from './system-config-logging.dto'; -import { SystemConfigMachineLearningDto } from './system-config-machine-learning.dto'; -import { SystemConfigMapDto } from './system-config-map.dto'; -import { SystemConfigNewVersionCheckDto } from './system-config-new-version-check.dto'; -import { SystemConfigOAuthDto } from './system-config-oauth.dto'; -import { SystemConfigPasswordLoginDto } from './system-config-password-login.dto'; -import { SystemConfigReverseGeocodingDto } from './system-config-reverse-geocoding.dto'; -import { SystemConfigServerDto } from './system-config-server.dto'; -import { SystemConfigStorageTemplateDto } from './system-config-storage-template.dto'; -import { SystemConfigThemeDto } from './system-config-theme.dto'; -import { SystemConfigThumbnailDto } from './system-config-thumbnail.dto'; -import { SystemConfigTrashDto } from './system-config-trash.dto'; -import { SystemConfigUserDto } from './system-config-user.dto'; +import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; +import { SystemConfigJobDto } from 'src/domain/system-config/dto/system-config-job.dto'; +import { SystemConfigLibraryDto } from 'src/domain/system-config/dto/system-config-library.dto'; +import { SystemConfigLoggingDto } from 'src/domain/system-config/dto/system-config-logging.dto'; +import { SystemConfigMachineLearningDto } from 'src/domain/system-config/dto/system-config-machine-learning.dto'; +import { SystemConfigMapDto } from 'src/domain/system-config/dto/system-config-map.dto'; +import { SystemConfigNewVersionCheckDto } from 'src/domain/system-config/dto/system-config-new-version-check.dto'; +import { SystemConfigOAuthDto } from 'src/domain/system-config/dto/system-config-oauth.dto'; +import { SystemConfigPasswordLoginDto } from 'src/domain/system-config/dto/system-config-password-login.dto'; +import { SystemConfigReverseGeocodingDto } from 'src/domain/system-config/dto/system-config-reverse-geocoding.dto'; +import { SystemConfigServerDto } from 'src/domain/system-config/dto/system-config-server.dto'; +import { SystemConfigStorageTemplateDto } from 'src/domain/system-config/dto/system-config-storage-template.dto'; +import { SystemConfigThemeDto } from 'src/domain/system-config/dto/system-config-theme.dto'; +import { SystemConfigThumbnailDto } from 'src/domain/system-config/dto/system-config-thumbnail.dto'; +import { SystemConfigTrashDto } from 'src/domain/system-config/dto/system-config-trash.dto'; +import { SystemConfigUserDto } from 'src/domain/system-config/dto/system-config-user.dto'; +import { SystemConfig } from 'src/infra/entities/system-config.entity'; export class SystemConfigDto implements SystemConfig { @Type(() => SystemConfigFFmpegDto) diff --git a/server/src/domain/system-config/index.ts b/server/src/domain/system-config/index.ts deleted file mode 100644 index fb71613dd..000000000 --- a/server/src/domain/system-config/index.ts +++ /dev/null @@ -1,5 +0,0 @@ -export * from './dto'; -export * from './response-dto'; -export * from './system-config.constants'; -export * from './system-config.core'; -export * from './system-config.service'; diff --git a/server/src/domain/system-config/response-dto/index.ts b/server/src/domain/system-config/response-dto/index.ts deleted file mode 100644 index 9cb60bece..000000000 --- a/server/src/domain/system-config/response-dto/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './system-config-template-storage-option.dto'; diff --git a/server/src/domain/system-config/system-config.core.ts b/server/src/domain/system-config/system-config.core.ts index 93a4937cb..999ca3e5b 100644 --- a/server/src/domain/system-config/system-config.core.ts +++ b/server/src/domain/system-config/system-config.core.ts @@ -1,7 +1,17 @@ +import { BadRequestException, ForbiddenException, Injectable } from '@nestjs/common'; +import { CronExpression } from '@nestjs/schedule'; +import { plainToInstance } from 'class-transformer'; +import { validate } from 'class-validator'; +import { load as loadYaml } from 'js-yaml'; +import * as _ from 'lodash'; +import { Subject } from 'rxjs'; +import { QueueName } from 'src/domain/job/job.constants'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SystemConfigDto } from 'src/domain/system-config/dto/system-config.dto'; import { AudioCodec, - Colorspace, CQMode, + Colorspace, LogLevel, SystemConfig, SystemConfigEntity, @@ -11,18 +21,8 @@ import { TranscodeHWAccel, TranscodePolicy, VideoCodec, -} from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; -import { BadRequestException, ForbiddenException, Injectable } from '@nestjs/common'; -import { CronExpression } from '@nestjs/schedule'; -import { plainToInstance } from 'class-transformer'; -import { validate } from 'class-validator'; -import { load as loadYaml } from 'js-yaml'; -import * as _ from 'lodash'; -import { Subject } from 'rxjs'; -import { QueueName } from '../job/job.constants'; -import { ISystemConfigRepository } from '../repositories'; -import { SystemConfigDto } from './dto'; +} from 'src/infra/entities/system-config.entity'; +import { ImmichLogger } from 'src/infra/logger'; export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConfig) => void | Promise; diff --git a/server/src/domain/system-config/system-config.service.spec.ts b/server/src/domain/system-config/system-config.service.spec.ts index fd9c16463..ccaea8421 100644 --- a/server/src/domain/system-config/system-config.service.spec.ts +++ b/server/src/domain/system-config/system-config.service.spec.ts @@ -1,7 +1,14 @@ +import { BadRequestException } from '@nestjs/common'; +import { QueueName } from 'src/domain/job/job.constants'; +import { ICommunicationRepository, ServerEvent } from 'src/domain/repositories/communication.repository'; +import { ISearchRepository } from 'src/domain/repositories/search.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { defaults } from 'src/domain/system-config/system-config.core'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; import { AudioCodec, - Colorspace, CQMode, + Colorspace, LogLevel, SystemConfig, SystemConfigEntity, @@ -10,14 +17,10 @@ import { TranscodeHWAccel, TranscodePolicy, VideoCodec, -} from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; -import { BadRequestException } from '@nestjs/common'; -import { newCommunicationRepositoryMock, newSystemConfigRepositoryMock } from '@test'; -import { QueueName } from '../job'; -import { ICommunicationRepository, ISearchRepository, ISystemConfigRepository, ServerEvent } from '../repositories'; -import { defaults } from './system-config.core'; -import { SystemConfigService } from './system-config.service'; +} from 'src/infra/entities/system-config.entity'; +import { ImmichLogger } from 'src/infra/logger'; +import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; const updates: SystemConfigEntity[] = [ { key: SystemConfigKey.FFMPEG_CRF, value: 30 }, diff --git a/server/src/domain/system-config/system-config.service.ts b/server/src/domain/system-config/system-config.service.ts index 7e68cf0b9..2c4e1eacc 100644 --- a/server/src/domain/system-config/system-config.service.ts +++ b/server/src/domain/system-config/system-config.service.ts @@ -1,5 +1,3 @@ -import { LogLevel, SystemConfig } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import { instanceToPlain } from 'class-transformer'; @@ -7,14 +5,14 @@ import _ from 'lodash'; import { ClientEvent, ICommunicationRepository, - ISearchRepository, - ISystemConfigRepository, InternalEvent, InternalEventMap, ServerEvent, -} from '../repositories'; -import { SystemConfigDto, mapConfig } from './dto/system-config.dto'; -import { SystemConfigTemplateStorageOptionDto } from './response-dto/system-config-template-storage-option.dto'; +} from 'src/domain/repositories/communication.repository'; +import { ISearchRepository } from 'src/domain/repositories/search.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SystemConfigDto, mapConfig } from 'src/domain/system-config/dto/system-config.dto'; +import { SystemConfigTemplateStorageOptionDto } from 'src/domain/system-config/response-dto/system-config-template-storage-option.dto'; import { supportedDayTokens, supportedHourTokens, @@ -24,8 +22,10 @@ import { supportedSecondTokens, supportedWeekTokens, supportedYearTokens, -} from './system-config.constants'; -import { SystemConfigCore } from './system-config.core'; +} from 'src/domain/system-config/system-config.constants'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { LogLevel, SystemConfig } from 'src/infra/entities/system-config.entity'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class SystemConfigService { diff --git a/server/src/domain/tag/index.ts b/server/src/domain/tag/index.ts deleted file mode 100644 index 38e9b389f..000000000 --- a/server/src/domain/tag/index.ts +++ /dev/null @@ -1,3 +0,0 @@ -export * from './tag-response.dto'; -export * from './tag.dto'; -export * from './tag.service'; diff --git a/server/src/domain/tag/tag-response.dto.ts b/server/src/domain/tag/tag-response.dto.ts index a533b15c9..04ee9540b 100644 --- a/server/src/domain/tag/tag-response.dto.ts +++ b/server/src/domain/tag/tag-response.dto.ts @@ -1,5 +1,5 @@ -import { TagEntity, TagType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; +import { TagEntity, TagType } from 'src/infra/entities/tag.entity'; export class TagResponseDto { id!: string; diff --git a/server/src/domain/tag/tag.dto.ts b/server/src/domain/tag/tag.dto.ts index 900aac9bd..e0c27294a 100644 --- a/server/src/domain/tag/tag.dto.ts +++ b/server/src/domain/tag/tag.dto.ts @@ -1,7 +1,7 @@ -import { TagType } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional } from '../domain.util'; +import { Optional } from 'src/domain/domain.util'; +import { TagType } from 'src/infra/entities/tag.entity'; export class CreateTagDto { @IsString() diff --git a/server/src/domain/tag/tag.service.spec.ts b/server/src/domain/tag/tag.service.spec.ts index e987beb6a..ae578068a 100644 --- a/server/src/domain/tag/tag.service.spec.ts +++ b/server/src/domain/tag/tag.service.spec.ts @@ -1,10 +1,13 @@ -import { TagType } from '@app/infra/entities'; import { BadRequestException } from '@nestjs/common'; -import { assetStub, authStub, newTagRepositoryMock, tagResponseStub, tagStub } from '@test'; import { when } from 'jest-when'; -import { AssetIdErrorReason } from '../asset'; -import { ITagRepository } from '../repositories'; -import { TagService } from './tag.service'; +import { AssetIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { ITagRepository } from 'src/domain/repositories/tag.repository'; +import { TagService } from 'src/domain/tag/tag.service'; +import { TagType } from 'src/infra/entities/tag.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { tagResponseStub, tagStub } from 'test/fixtures/tag.stub'; +import { newTagRepositoryMock } from 'test/repositories/tag.repository.mock'; describe(TagService.name, () => { let sut: TagService; diff --git a/server/src/domain/tag/tag.service.ts b/server/src/domain/tag/tag.service.ts index 38f1de1bc..3a7a5b579 100644 --- a/server/src/domain/tag/tag.service.ts +++ b/server/src/domain/tag/tag.service.ts @@ -1,9 +1,11 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { AssetIdErrorReason, AssetIdsDto, AssetIdsResponseDto, AssetResponseDto, mapAsset } from '../asset'; -import { AuthDto } from '../auth'; -import { ITagRepository } from '../repositories'; -import { TagResponseDto, mapTag } from './tag-response.dto'; -import { CreateTagDto, UpdateTagDto } from './tag.dto'; +import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; +import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { ITagRepository } from 'src/domain/repositories/tag.repository'; +import { TagResponseDto, mapTag } from 'src/domain/tag/tag-response.dto'; +import { CreateTagDto, UpdateTagDto } from 'src/domain/tag/tag.dto'; @Injectable() export class TagService { diff --git a/server/src/domain/trash/index.ts b/server/src/domain/trash/index.ts deleted file mode 100644 index 3cd00e191..000000000 --- a/server/src/domain/trash/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './trash.service'; diff --git a/server/src/domain/trash/trash.service.spec.ts b/server/src/domain/trash/trash.service.spec.ts index 81f4186e8..90320326f 100644 --- a/server/src/domain/trash/trash.service.spec.ts +++ b/server/src/domain/trash/trash.service.spec.ts @@ -1,16 +1,15 @@ import { BadRequestException } from '@nestjs/common'; -import { - IAccessRepositoryMock, - assetStub, - authStub, - newAccessRepositoryMock, - newAssetRepositoryMock, - newCommunicationRepositoryMock, - newJobRepositoryMock, -} from '@test'; -import { JobName } from '..'; -import { ClientEvent, IAssetRepository, ICommunicationRepository, IJobRepository } from '../repositories'; -import { TrashService } from './trash.service'; +import { JobName } from 'src/domain/job/job.constants'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { TrashService } from 'src/domain/trash/trash.service'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; describe(TrashService.name, () => { let sut: TrashService; diff --git a/server/src/domain/trash/trash.service.ts b/server/src/domain/trash/trash.service.ts index 30fd6843e..230ce77f3 100644 --- a/server/src/domain/trash/trash.service.ts +++ b/server/src/domain/trash/trash.service.ts @@ -1,17 +1,14 @@ import { Inject } from '@nestjs/common'; import { DateTime } from 'luxon'; -import { AccessCore, Permission } from '../access'; -import { BulkIdsDto } from '../asset'; -import { AuthDto } from '../auth'; -import { usePagination } from '../domain.util'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName } from '../job'; -import { - ClientEvent, - IAccessRepository, - IAssetRepository, - ICommunicationRepository, - IJobRepository, -} from '../repositories'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { usePagination } from 'src/domain/domain.util'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { IJobRepository } from 'src/domain/repositories/job.repository'; export class TrashService { private access: AccessCore; diff --git a/server/src/domain/user/dto/create-profile-image.dto.ts b/server/src/domain/user/dto/create-profile-image.dto.ts index c7a1dc68b..37a7d1340 100644 --- a/server/src/domain/user/dto/create-profile-image.dto.ts +++ b/server/src/domain/user/dto/create-profile-image.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { UploadFieldName } from '../../asset/asset.service'; +import { UploadFieldName } from 'src/domain/asset/asset.service'; export class CreateProfileImageDto { @ApiProperty({ type: 'string', format: 'binary' }) diff --git a/server/src/domain/user/dto/create-user.dto.spec.ts b/server/src/domain/user/dto/create-user.dto.spec.ts index 4e571d38a..28abc44ad 100644 --- a/server/src/domain/user/dto/create-user.dto.spec.ts +++ b/server/src/domain/user/dto/create-user.dto.spec.ts @@ -1,6 +1,6 @@ import { plainToInstance } from 'class-transformer'; import { validate } from 'class-validator'; -import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto } from './create-user.dto'; +import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto } from 'src/domain/user/dto/create-user.dto'; describe('create user DTO', () => { it('validates the email', async () => { diff --git a/server/src/domain/user/dto/create-user.dto.ts b/server/src/domain/user/dto/create-user.dto.ts index f0cc7938c..aa295cb2b 100644 --- a/server/src/domain/user/dto/create-user.dto.ts +++ b/server/src/domain/user/dto/create-user.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsEmail, IsNotEmpty, IsNumber, IsPositive, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, toEmail, toSanitized } from '../../domain.util'; +import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/domain/domain.util'; export class CreateUserDto { @IsEmail({ require_tld: false }) diff --git a/server/src/domain/user/dto/delete-user.dto.ts b/server/src/domain/user/dto/delete-user.dto.ts index 88f55f4af..09b1c5bf3 100644 --- a/server/src/domain/user/dto/delete-user.dto.ts +++ b/server/src/domain/user/dto/delete-user.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from '../../domain.util'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class DeleteUserDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/user/dto/index.ts b/server/src/domain/user/dto/index.ts deleted file mode 100644 index 2d166de36..000000000 --- a/server/src/domain/user/dto/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './create-profile-image.dto'; -export * from './create-user.dto'; -export * from './delete-user.dto'; -export * from './update-user.dto'; diff --git a/server/src/domain/user/dto/update-user.dto.spec.ts b/server/src/domain/user/dto/update-user.dto.spec.ts index 8e9013f29..0ad407be3 100644 --- a/server/src/domain/user/dto/update-user.dto.spec.ts +++ b/server/src/domain/user/dto/update-user.dto.spec.ts @@ -1,6 +1,6 @@ import { plainToInstance } from 'class-transformer'; import { validate } from 'class-validator'; -import { UpdateUserDto } from './update-user.dto'; +import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; describe('update user DTO', () => { it('should allow emails without a tld', async () => { diff --git a/server/src/domain/user/dto/update-user.dto.ts b/server/src/domain/user/dto/update-user.dto.ts index e8cce2214..605017e54 100644 --- a/server/src/domain/user/dto/update-user.dto.ts +++ b/server/src/domain/user/dto/update-user.dto.ts @@ -1,8 +1,8 @@ -import { UserAvatarColor } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator'; -import { Optional, ValidateBoolean, toEmail, toSanitized } from '../../domain.util'; +import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/domain/domain.util'; +import { UserAvatarColor } from 'src/infra/entities/user.entity'; export class UpdateUserDto { @Optional() diff --git a/server/src/domain/user/index.ts b/server/src/domain/user/index.ts deleted file mode 100644 index 724859197..000000000 --- a/server/src/domain/user/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './dto'; -export * from './response-dto'; -export * from './user.core'; -export * from './user.service'; diff --git a/server/src/domain/user/response-dto/index.ts b/server/src/domain/user/response-dto/index.ts deleted file mode 100644 index 8c550a4ff..000000000 --- a/server/src/domain/user/response-dto/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './create-profile-image-response.dto'; -export * from './user-response.dto'; diff --git a/server/src/domain/user/response-dto/user-response.dto.ts b/server/src/domain/user/response-dto/user-response.dto.ts index bd437ea34..b2a5d12cf 100644 --- a/server/src/domain/user/response-dto/user-response.dto.ts +++ b/server/src/domain/user/response-dto/user-response.dto.ts @@ -1,6 +1,6 @@ -import { UserAvatarColor, UserEntity, UserStatus } from '@app/infra/entities'; import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; +import { UserAvatarColor, UserEntity, UserStatus } from 'src/infra/entities/user.entity'; export const getRandomAvatarColor = (user: UserEntity): UserAvatarColor => { const values = Object.values(UserAvatarColor); diff --git a/server/src/domain/user/user.core.ts b/server/src/domain/user/user.core.ts index 6134e97ce..0f9022a42 100644 --- a/server/src/domain/user/user.core.ts +++ b/server/src/domain/user/user.core.ts @@ -1,8 +1,11 @@ -import { LibraryType, UserEntity } from '@app/infra/entities'; import { BadRequestException, ForbiddenException } from '@nestjs/common'; import sanitize from 'sanitize-filename'; -import { ICryptoRepository, ILibraryRepository, IUserRepository } from '../repositories'; -import { UserResponseDto } from './response-dto'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; +import { LibraryType } from 'src/infra/entities/library.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; const SALT_ROUNDS = 10; diff --git a/server/src/domain/user/user.service.spec.ts b/server/src/domain/user/user.service.spec.ts index d0e56e4cd..8fed91c71 100644 --- a/server/src/domain/user/user.service.spec.ts +++ b/server/src/domain/user/user.service.spec.ts @@ -1,37 +1,33 @@ -import { UserEntity, UserStatus } from '@app/infra/entities'; import { BadRequestException, ForbiddenException, InternalServerErrorException, NotFoundException, } from '@nestjs/common'; -import { - authStub, - newAlbumRepositoryMock, - newCryptoRepositoryMock, - newJobRepositoryMock, - newLibraryRepositoryMock, - newStorageRepositoryMock, - newSystemConfigRepositoryMock, - newUserRepositoryMock, - systemConfigStub, - userStub, -} from '@test'; import { when } from 'jest-when'; -import { CacheControl, ImmichFileResponse } from '../domain.util'; -import { JobName } from '../job'; -import { - IAlbumRepository, - ICryptoRepository, - IJobRepository, - ILibraryRepository, - IStorageRepository, - ISystemConfigRepository, - IUserRepository, -} from '../repositories'; -import { UpdateUserDto } from './dto/update-user.dto'; -import { mapUser } from './response-dto'; -import { UserService } from './user.service'; +import { CacheControl, ImmichFileResponse } from 'src/domain/domain.util'; +import { JobName } from 'src/domain/job/job.constants'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; +import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { UserService } from 'src/domain/user/user.service'; +import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; +import { authStub } from 'test/fixtures/auth.stub'; +import { systemConfigStub } from 'test/fixtures/system-config.stub'; +import { userStub } from 'test/fixtures/user.stub'; +import { newAlbumRepositoryMock } from 'test/repositories/album.repository.mock'; +import { newCryptoRepositoryMock } from 'test/repositories/crypto.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newLibraryRepositoryMock } from 'test/repositories/library.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; +import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; const makeDeletedAt = (daysAgo: number) => { const deletedAt = new Date(); diff --git a/server/src/domain/user/user.service.ts b/server/src/domain/user/user.service.ts index a1db1fb04..18f485b00 100644 --- a/server/src/domain/user/user.service.ts +++ b/server/src/domain/user/user.service.ts @@ -1,27 +1,30 @@ -import { UserEntity, UserStatus } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, ForbiddenException, Inject, Injectable, NotFoundException } from '@nestjs/common'; import { DateTime } from 'luxon'; import { randomBytes } from 'node:crypto'; -import { AuthDto } from '../auth'; -import { CacheControl, ImmichFileResponse } from '../domain.util'; -import { IEntityJob, JobName } from '../job'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { CacheControl, ImmichFileResponse } from 'src/domain/domain.util'; +import { JobName } from 'src/domain/job/job.constants'; +import { IEntityJob } from 'src/domain/job/job.interface'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { IUserRepository, UserFindOptions } from 'src/domain/repositories/user.repository'; +import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; +import { CreateUserDto } from 'src/domain/user/dto/create-user.dto'; +import { DeleteUserDto } from 'src/domain/user/dto/delete-user.dto'; +import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; import { - IAlbumRepository, - ICryptoRepository, - IJobRepository, - ILibraryRepository, - IStorageRepository, - ISystemConfigRepository, - IUserRepository, - JobStatus, - UserFindOptions, -} from '../repositories'; -import { StorageCore, StorageFolder } from '../storage'; -import { SystemConfigCore } from '../system-config/system-config.core'; -import { CreateUserDto, DeleteUserDto, UpdateUserDto } from './dto'; -import { CreateProfileImageResponseDto, UserResponseDto, mapCreateProfileImageResponse, mapUser } from './response-dto'; -import { UserCore } from './user.core'; + CreateProfileImageResponseDto, + mapCreateProfileImageResponse, +} from 'src/domain/user/response-dto/create-profile-image-response.dto'; +import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { UserCore } from 'src/domain/user/user.core'; +import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class UserService { diff --git a/server/src/immich-admin/app.module.ts b/server/src/immich-admin/app.module.ts index b350aec83..277b39a90 100644 --- a/server/src/immich-admin/app.module.ts +++ b/server/src/immich-admin/app.module.ts @@ -1,10 +1,13 @@ -import { DomainModule } from '@app/domain'; -import { InfraModule } from '@app/infra'; import { Module } from '@nestjs/common'; -import { ListUsersCommand } from './commands/list-users.command'; -import { DisableOAuthLogin, EnableOAuthLogin } from './commands/oauth-login'; -import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from './commands/password-login'; -import { PromptPasswordQuestions, ResetAdminPasswordCommand } from './commands/reset-admin-password.command'; +import { DomainModule } from 'src/domain/domain.module'; +import { ListUsersCommand } from 'src/immich-admin/commands/list-users.command'; +import { DisableOAuthLogin, EnableOAuthLogin } from 'src/immich-admin/commands/oauth-login'; +import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from 'src/immich-admin/commands/password-login'; +import { + PromptPasswordQuestions, + ResetAdminPasswordCommand, +} from 'src/immich-admin/commands/reset-admin-password.command'; +import { InfraModule } from 'src/infra/infra.module'; @Module({ imports: [InfraModule, DomainModule], diff --git a/server/src/immich-admin/commands/list-users.command.ts b/server/src/immich-admin/commands/list-users.command.ts index 15ab0a240..8ab882396 100644 --- a/server/src/immich-admin/commands/list-users.command.ts +++ b/server/src/immich-admin/commands/list-users.command.ts @@ -1,6 +1,6 @@ -import { UserService } from '@app/domain'; import { Command, CommandRunner } from 'nest-commander'; -import { CLI_USER } from '../constants'; +import { UserService } from 'src/domain/user/user.service'; +import { CLI_USER } from 'src/immich-admin/constants'; @Command({ name: 'list-users', diff --git a/server/src/immich-admin/commands/oauth-login.ts b/server/src/immich-admin/commands/oauth-login.ts index 23747bf03..12562fae1 100644 --- a/server/src/immich-admin/commands/oauth-login.ts +++ b/server/src/immich-admin/commands/oauth-login.ts @@ -1,5 +1,5 @@ -import { SystemConfigService } from '@app/domain'; import { Command, CommandRunner } from 'nest-commander'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; @Command({ name: 'enable-oauth-login', diff --git a/server/src/immich-admin/commands/password-login.ts b/server/src/immich-admin/commands/password-login.ts index e6eea2c72..953a1293a 100644 --- a/server/src/immich-admin/commands/password-login.ts +++ b/server/src/immich-admin/commands/password-login.ts @@ -1,5 +1,5 @@ -import { SystemConfigService } from '@app/domain'; import { Command, CommandRunner } from 'nest-commander'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; @Command({ name: 'enable-password-login', diff --git a/server/src/immich-admin/commands/reset-admin-password.command.ts b/server/src/immich-admin/commands/reset-admin-password.command.ts index d19ddf433..ce0a897a8 100644 --- a/server/src/immich-admin/commands/reset-admin-password.command.ts +++ b/server/src/immich-admin/commands/reset-admin-password.command.ts @@ -1,5 +1,6 @@ -import { UserResponseDto, UserService } from '@app/domain'; import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander'; +import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; +import { UserService } from 'src/domain/user/user.service'; @Command({ name: 'reset-admin-password', diff --git a/server/src/immich-admin/constants.ts b/server/src/immich-admin/constants.ts index 44fbfdf77..237f66e63 100644 --- a/server/src/immich-admin/constants.ts +++ b/server/src/immich-admin/constants.ts @@ -1,5 +1,5 @@ -import { AuthDto } from '@app/domain'; -import { UserEntity } from '@app/infra/entities'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { UserEntity } from 'src/infra/entities/user.entity'; export const CLI_USER: AuthDto = { user: { diff --git a/server/src/immich-admin/main.ts b/server/src/immich-admin/main.ts index f14aac20f..0b569dd9a 100755 --- a/server/src/immich-admin/main.ts +++ b/server/src/immich-admin/main.ts @@ -1,6 +1,6 @@ -import { LogLevel } from '@app/infra/entities'; import { CommandFactory } from 'nest-commander'; -import { AppModule } from './app.module'; +import { AppModule } from 'src/immich-admin/app.module'; +import { LogLevel } from 'src/infra/entities/system-config.entity'; export async function bootstrap() { process.env.LOG_LEVEL = LogLevel.WARN; diff --git a/server/src/immich/api-v1/asset/asset-repository.ts b/server/src/immich/api-v1/asset/asset-repository.ts index 18feb65dc..12a627875 100644 --- a/server/src/immich/api-v1/asset/asset-repository.ts +++ b/server/src/immich/api-v1/asset/asset-repository.ts @@ -1,14 +1,15 @@ -import { AssetEntity, ExifEntity } from '@app/infra/entities'; -import { OptionalBetween } from '@app/infra/infra.utils'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { AssetSearchDto } from 'src/immich/api-v1/asset/dto/asset-search.dto'; +import { CheckExistingAssetsDto } from 'src/immich/api-v1/asset/dto/check-existing-assets.dto'; +import { SearchPropertiesDto } from 'src/immich/api-v1/asset/dto/search-properties.dto'; +import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; +import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { OptionalBetween } from 'src/infra/infra.utils'; import { In } from 'typeorm/find-options/operator/In.js'; import { Repository } from 'typeorm/repository/Repository.js'; -import { AssetSearchDto } from './dto/asset-search.dto'; -import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto'; -import { SearchPropertiesDto } from './dto/search-properties.dto'; -import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto'; -import { CuratedObjectsResponseDto } from './response-dto/curated-objects-response.dto'; export interface AssetCheck { id: string; checksum: Buffer; diff --git a/server/src/immich/api-v1/asset/asset.controller.ts b/server/src/immich/api-v1/asset/asset.controller.ts index 37b561490..3faf33641 100644 --- a/server/src/immich/api-v1/asset/asset.controller.ts +++ b/server/src/immich/api-v1/asset/asset.controller.ts @@ -1,4 +1,3 @@ -import { AssetResponseDto, AuthDto } from '@app/domain'; import { Body, Controller, @@ -16,23 +15,30 @@ import { } from '@nestjs/common'; import { ApiBody, ApiConsumes, ApiHeader, ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { Auth, Authenticated, FileResponse, SharedLinkRoute } from '../../app.guard'; -import { sendFile } from '../../app.utils'; -import { UUIDParamDto } from '../../controllers/dto/uuid-param.dto'; -import { FileUploadInterceptor, ImmichFile, Route, mapToUploadFile } from '../../interceptors'; -import FileNotEmptyValidator from '../validation/file-not-empty-validator'; -import { AssetService as AssetServiceV1 } from './asset.service'; -import { AssetBulkUploadCheckDto } from './dto/asset-check.dto'; -import { AssetSearchDto } from './dto/asset-search.dto'; -import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto'; -import { CreateAssetDto } from './dto/create-asset.dto'; -import { GetAssetThumbnailDto } from './dto/get-asset-thumbnail.dto'; -import { ServeFileDto } from './dto/serve-file.dto'; -import { AssetBulkUploadCheckResponseDto } from './response-dto/asset-check-response.dto'; -import { AssetFileUploadResponseDto } from './response-dto/asset-file-upload-response.dto'; -import { CheckExistingAssetsResponseDto } from './response-dto/check-existing-assets-response.dto'; -import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto'; -import { CuratedObjectsResponseDto } from './response-dto/curated-objects-response.dto'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AssetService as AssetServiceV1 } from 'src/immich/api-v1/asset/asset.service'; +import { AssetBulkUploadCheckDto } from 'src/immich/api-v1/asset/dto/asset-check.dto'; +import { AssetSearchDto } from 'src/immich/api-v1/asset/dto/asset-search.dto'; +import { CheckExistingAssetsDto } from 'src/immich/api-v1/asset/dto/check-existing-assets.dto'; +import { CreateAssetDto } from 'src/immich/api-v1/asset/dto/create-asset.dto'; +import { GetAssetThumbnailDto } from 'src/immich/api-v1/asset/dto/get-asset-thumbnail.dto'; +import { ServeFileDto } from 'src/immich/api-v1/asset/dto/serve-file.dto'; +import { AssetBulkUploadCheckResponseDto } from 'src/immich/api-v1/asset/response-dto/asset-check-response.dto'; +import { AssetFileUploadResponseDto } from 'src/immich/api-v1/asset/response-dto/asset-file-upload-response.dto'; +import { CheckExistingAssetsResponseDto } from 'src/immich/api-v1/asset/response-dto/check-existing-assets-response.dto'; +import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; +import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; +import FileNotEmptyValidator from 'src/immich/api-v1/validation/file-not-empty-validator'; +import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/immich/app.guard'; +import { sendFile } from 'src/immich/app.utils'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { + FileUploadInterceptor, + ImmichFile, + Route, + mapToUploadFile, +} from 'src/immich/interceptors/file-upload.interceptor'; interface UploadFiles { assetData: ImmichFile[]; diff --git a/server/src/immich/api-v1/asset/asset.service.spec.ts b/server/src/immich/api-v1/asset/asset.service.spec.ts index 9f0aa371e..fff1c0e1e 100644 --- a/server/src/immich/api-v1/asset/asset.service.spec.ts +++ b/server/src/immich/api-v1/asset/asset.service.spec.ts @@ -1,30 +1,26 @@ -import { - IAssetRepository, - IJobRepository, - ILibraryRepository, - IStorageRepository, - IUserRepository, - JobName, -} from '@app/domain'; -import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType, ExifEntity } from '@app/infra/entities'; -import { - IAccessRepositoryMock, - assetStub, - authStub, - fileStub, - newAccessRepositoryMock, - newAssetRepositoryMock, - newJobRepositoryMock, - newLibraryRepositoryMock, - newStorageRepositoryMock, - newUserRepositoryMock, -} from '@test'; import { when } from 'jest-when'; +import { JobName } from 'src/domain/job/job.constants'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; +import { AssetService } from 'src/immich/api-v1/asset/asset.service'; +import { CreateAssetDto } from 'src/immich/api-v1/asset/dto/create-asset.dto'; +import { AssetRejectReason, AssetUploadAction } from 'src/immich/api-v1/asset/response-dto/asset-check-response.dto'; +import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { fileStub } from 'test/fixtures/file.stub'; +import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; +import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; +import { newJobRepositoryMock } from 'test/repositories/job.repository.mock'; +import { newLibraryRepositoryMock } from 'test/repositories/library.repository.mock'; +import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; +import { newUserRepositoryMock } from 'test/repositories/user.repository.mock'; import { QueryFailedError } from 'typeorm'; -import { IAssetRepositoryV1 } from './asset-repository'; -import { AssetService } from './asset.service'; -import { CreateAssetDto } from './dto/create-asset.dto'; -import { AssetRejectReason, AssetUploadAction } from './response-dto/asset-check-response.dto'; const _getCreateAssetDto = (): CreateAssetDto => { const createAssetDto = new CreateAssetDto(); diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 821a7de82..78f7fa24f 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -1,24 +1,3 @@ -import { - AccessCore, - AssetResponseDto, - AuthDto, - CacheControl, - IAccessRepository, - IAssetRepository, - IJobRepository, - ILibraryRepository, - IStorageRepository, - IUserRepository, - ImmichFileResponse, - JobName, - Permission, - UploadFile, - getLivePhotoMotionFilename, - mapAsset, - mimeTypes, -} from '@app/domain'; -import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType, LibraryType } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; import { BadRequestException, Inject, @@ -26,23 +5,39 @@ import { InternalServerErrorException, NotFoundException, } from '@nestjs/common'; -import { QueryFailedError } from 'typeorm'; -import { IAssetRepositoryV1 } from './asset-repository'; -import { AssetBulkUploadCheckDto } from './dto/asset-check.dto'; -import { AssetSearchDto } from './dto/asset-search.dto'; -import { CheckExistingAssetsDto } from './dto/check-existing-assets.dto'; -import { CreateAssetDto } from './dto/create-asset.dto'; -import { GetAssetThumbnailDto, GetAssetThumbnailFormatEnum } from './dto/get-asset-thumbnail.dto'; -import { ServeFileDto } from './dto/serve-file.dto'; +import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { UploadFile } from 'src/domain/asset/asset.service'; +import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { mimeTypes } from 'src/domain/domain.constant'; +import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/domain/domain.util'; +import { JobName } from 'src/domain/job/job.constants'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; +import { AssetBulkUploadCheckDto } from 'src/immich/api-v1/asset/dto/asset-check.dto'; +import { AssetSearchDto } from 'src/immich/api-v1/asset/dto/asset-search.dto'; +import { CheckExistingAssetsDto } from 'src/immich/api-v1/asset/dto/check-existing-assets.dto'; +import { CreateAssetDto } from 'src/immich/api-v1/asset/dto/create-asset.dto'; +import { GetAssetThumbnailDto, GetAssetThumbnailFormatEnum } from 'src/immich/api-v1/asset/dto/get-asset-thumbnail.dto'; +import { ServeFileDto } from 'src/immich/api-v1/asset/dto/serve-file.dto'; import { AssetBulkUploadCheckResponseDto, AssetRejectReason, AssetUploadAction, -} from './response-dto/asset-check-response.dto'; -import { AssetFileUploadResponseDto } from './response-dto/asset-file-upload-response.dto'; -import { CheckExistingAssetsResponseDto } from './response-dto/check-existing-assets-response.dto'; -import { CuratedLocationsResponseDto } from './response-dto/curated-locations-response.dto'; -import { CuratedObjectsResponseDto } from './response-dto/curated-objects-response.dto'; +} from 'src/immich/api-v1/asset/response-dto/asset-check-response.dto'; +import { AssetFileUploadResponseDto } from 'src/immich/api-v1/asset/response-dto/asset-file-upload-response.dto'; +import { CheckExistingAssetsResponseDto } from 'src/immich/api-v1/asset/response-dto/check-existing-assets-response.dto'; +import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; +import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; +import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { LibraryType } from 'src/infra/entities/library.entity'; +import { ImmichLogger } from 'src/infra/logger'; +import { QueryFailedError } from 'typeorm'; @Injectable() export class AssetService { diff --git a/server/src/immich/api-v1/asset/dto/asset-search.dto.ts b/server/src/immich/api-v1/asset/dto/asset-search.dto.ts index 719018488..499ec7499 100644 --- a/server/src/immich/api-v1/asset/dto/asset-search.dto.ts +++ b/server/src/immich/api-v1/asset/dto/asset-search.dto.ts @@ -1,7 +1,7 @@ -import { Optional, ValidateBoolean, ValidateDate } from '@app/domain'; import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsInt, IsUUID } from 'class-validator'; +import { Optional, ValidateBoolean, ValidateDate } from 'src/domain/domain.util'; export class AssetSearchDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/immich/api-v1/asset/dto/check-existing-assets.dto.spec.ts b/server/src/immich/api-v1/asset/dto/check-existing-assets.dto.spec.ts index dd0eca03f..a634ba42e 100644 --- a/server/src/immich/api-v1/asset/dto/check-existing-assets.dto.spec.ts +++ b/server/src/immich/api-v1/asset/dto/check-existing-assets.dto.spec.ts @@ -1,6 +1,6 @@ import { plainToInstance } from 'class-transformer'; import { validateSync } from 'class-validator'; -import { CheckExistingAssetsDto } from './check-existing-assets.dto'; +import { CheckExistingAssetsDto } from 'src/immich/api-v1/asset/dto/check-existing-assets.dto'; describe('CheckExistingAssetsDto', () => { it('should fail with an empty list', () => { diff --git a/server/src/immich/api-v1/asset/dto/create-asset.dto.ts b/server/src/immich/api-v1/asset/dto/create-asset.dto.ts index 1b140d69f..90b2d2245 100644 --- a/server/src/immich/api-v1/asset/dto/create-asset.dto.ts +++ b/server/src/immich/api-v1/asset/dto/create-asset.dto.ts @@ -1,6 +1,7 @@ -import { Optional, UploadFieldName, ValidateBoolean, ValidateDate, ValidateUUID } from '@app/domain'; import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsString } from 'class-validator'; +import { UploadFieldName } from 'src/domain/asset/asset.service'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; export class CreateAssetDto { @ValidateUUID({ optional: true }) diff --git a/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts b/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts index da5661e0d..65c6a7deb 100644 --- a/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts +++ b/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts @@ -1,6 +1,6 @@ -import { Optional } from '@app/domain'; import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; +import { Optional } from 'src/domain/domain.util'; export enum GetAssetThumbnailFormatEnum { JPEG = 'JPEG', diff --git a/server/src/immich/api-v1/asset/dto/serve-file.dto.ts b/server/src/immich/api-v1/asset/dto/serve-file.dto.ts index 72e228601..cc8d8fd15 100644 --- a/server/src/immich/api-v1/asset/dto/serve-file.dto.ts +++ b/server/src/immich/api-v1/asset/dto/serve-file.dto.ts @@ -1,5 +1,5 @@ -import { ValidateBoolean } from '@app/domain'; import { ApiProperty } from '@nestjs/swagger'; +import { ValidateBoolean } from 'src/domain/domain.util'; export class ServeFileDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/immich/app.guard.ts b/server/src/immich/app.guard.ts index bd07d107b..e465f1d40 100644 --- a/server/src/immich/app.guard.ts +++ b/server/src/immich/app.guard.ts @@ -1,5 +1,3 @@ -import { AuthDto, AuthService, IMMICH_API_KEY_NAME, LoginDetails } from '@app/domain'; -import { ImmichLogger } from '@app/infra/logger'; import { CanActivate, ExecutionContext, @@ -11,6 +9,10 @@ import { import { Reflector } from '@nestjs/core'; import { ApiBearerAuth, ApiCookieAuth, ApiOkResponse, ApiQuery, ApiSecurity } from '@nestjs/swagger'; import { Request } from 'express'; +import { IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; +import { ImmichLogger } from 'src/infra/logger'; import { UAParser } from 'ua-parser-js'; export enum Metadata { diff --git a/server/src/immich/app.module.ts b/server/src/immich/app.module.ts index 662f45f7c..ba263622f 100644 --- a/server/src/immich/app.module.ts +++ b/server/src/immich/app.module.ts @@ -1,40 +1,39 @@ -import { DomainModule } from '@app/domain'; -import { InfraModule } from '@app/infra'; -import { AssetEntity, ExifEntity } from '@app/infra/entities'; import { Module, OnModuleInit, ValidationPipe } from '@nestjs/common'; import { APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core'; import { ScheduleModule } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; -import { AssetRepositoryV1, IAssetRepositoryV1 } from './api-v1/asset/asset-repository'; -import { AssetController as AssetControllerV1 } from './api-v1/asset/asset.controller'; -import { AssetService } from './api-v1/asset/asset.service'; -import { AppGuard } from './app.guard'; -import { AppService } from './app.service'; -import { - APIKeyController, - ActivityController, - AlbumController, - AppController, - AssetController, - AssetsController, - AuditController, - AuthController, - DownloadController, - FaceController, - JobController, - LibraryController, - OAuthController, - PartnerController, - PersonController, - SearchController, - ServerInfoController, - SharedLinkController, - SystemConfigController, - TagController, - TrashController, - UserController, -} from './controllers'; -import { ErrorInterceptor, FileUploadInterceptor } from './interceptors'; +import { DomainModule } from 'src/domain/domain.module'; +import { AssetRepositoryV1, IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; +import { AssetController as AssetControllerV1 } from 'src/immich/api-v1/asset/asset.controller'; +import { AssetService as AssetServiceV1 } from 'src/immich/api-v1/asset/asset.service'; +import { AppGuard } from 'src/immich/app.guard'; +import { AppService } from 'src/immich/app.service'; +import { ActivityController } from 'src/immich/controllers/activity.controller'; +import { AlbumController } from 'src/immich/controllers/album.controller'; +import { APIKeyController } from 'src/immich/controllers/api-key.controller'; +import { AppController } from 'src/immich/controllers/app.controller'; +import { AssetController, AssetsController } from 'src/immich/controllers/asset.controller'; +import { AuditController } from 'src/immich/controllers/audit.controller'; +import { AuthController } from 'src/immich/controllers/auth.controller'; +import { DownloadController } from 'src/immich/controllers/download.controller'; +import { FaceController } from 'src/immich/controllers/face.controller'; +import { JobController } from 'src/immich/controllers/job.controller'; +import { LibraryController } from 'src/immich/controllers/library.controller'; +import { OAuthController } from 'src/immich/controllers/oauth.controller'; +import { PartnerController } from 'src/immich/controllers/partner.controller'; +import { PersonController } from 'src/immich/controllers/person.controller'; +import { SearchController } from 'src/immich/controllers/search.controller'; +import { ServerInfoController } from 'src/immich/controllers/server-info.controller'; +import { SharedLinkController } from 'src/immich/controllers/shared-link.controller'; +import { SystemConfigController } from 'src/immich/controllers/system-config.controller'; +import { TagController } from 'src/immich/controllers/tag.controller'; +import { TrashController } from 'src/immich/controllers/trash.controller'; +import { UserController } from 'src/immich/controllers/user.controller'; +import { ErrorInterceptor } from 'src/immich/interceptors/error.interceptor'; +import { FileUploadInterceptor } from 'src/immich/interceptors/file-upload.interceptor'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { InfraModule } from 'src/infra/infra.module'; @Module({ imports: [ @@ -75,7 +74,7 @@ import { ErrorInterceptor, FileUploadInterceptor } from './interceptors'; { provide: APP_GUARD, useClass: AppGuard }, { provide: IAssetRepositoryV1, useClass: AssetRepositoryV1 }, AppService, - AssetService, + AssetServiceV1, FileUploadInterceptor, ], }) diff --git a/server/src/immich/app.service.ts b/server/src/immich/app.service.ts index adfb9d878..8cbb6cf23 100644 --- a/server/src/immich/app.service.ts +++ b/server/src/immich/app.service.ts @@ -1,21 +1,18 @@ -import { - AuthService, - DatabaseService, - JobService, - ONE_HOUR, - OpenGraphTags, - ServerInfoService, - SharedLinkService, - StorageService, - SystemConfigService, - WEB_ROOT, -} from '@app/domain'; -import { ImmichLogger } from '@app/infra/logger'; import { Injectable } from '@nestjs/common'; import { Cron, CronExpression, Interval } from '@nestjs/schedule'; import { NextFunction, Request, Response } from 'express'; import { readFileSync } from 'node:fs'; import { join } from 'node:path'; +import { AuthService } from 'src/domain/auth/auth.service'; +import { DatabaseService } from 'src/domain/database/database.service'; +import { ONE_HOUR, WEB_ROOT } from 'src/domain/domain.constant'; +import { OpenGraphTags } from 'src/domain/domain.util'; +import { JobService } from 'src/domain/job/job.service'; +import { ServerInfoService } from 'src/domain/server-info/server-info.service'; +import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; +import { StorageService } from 'src/domain/storage/storage.service'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { ImmichLogger } from 'src/infra/logger'; const render = (index: string, meta: OpenGraphTags) => { const tags = ` diff --git a/server/src/immich/app.utils.ts b/server/src/immich/app.utils.ts index 26aca2a9b..4d78ffb24 100644 --- a/server/src/immich/app.utils.ts +++ b/server/src/immich/app.utils.ts @@ -1,14 +1,3 @@ -import { - CacheControl, - IMMICH_ACCESS_COOKIE, - IMMICH_API_KEY_HEADER, - IMMICH_API_KEY_NAME, - ImmichFileResponse, - ImmichReadStream, - isConnectionAborted, - serverVersion, -} from '@app/domain'; -import { ImmichLogger } from '@app/infra/logger'; import { HttpException, INestApplication, StreamableFile } from '@nestjs/common'; import { DocumentBuilder, @@ -24,7 +13,12 @@ import { writeFileSync } from 'node:fs'; import { access, constants } from 'node:fs/promises'; import path, { isAbsolute } from 'node:path'; import { promisify } from 'node:util'; -import { Metadata } from './app.guard'; +import { IMMICH_ACCESS_COOKIE, IMMICH_API_KEY_HEADER, IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; +import { serverVersion } from 'src/domain/domain.constant'; +import { CacheControl, ImmichFileResponse, isConnectionAborted } from 'src/domain/domain.util'; +import { ImmichReadStream } from 'src/domain/repositories/storage.repository'; +import { Metadata } from 'src/immich/app.guard'; +import { ImmichLogger } from 'src/infra/logger'; type SendFile = Parameters; type SendFileOptions = SendFile[1]; diff --git a/server/src/immich/controllers/activity.controller.ts b/server/src/immich/controllers/activity.controller.ts index 0808c7d4d..c79a56407 100644 --- a/server/src/immich/controllers/activity.controller.ts +++ b/server/src/immich/controllers/activity.controller.ts @@ -1,17 +1,17 @@ -import { AuthDto } from '@app/domain'; -import { - ActivityDto, - ActivitySearchDto, - ActivityService, - ActivityCreateDto as CreateDto, - ActivityResponseDto as ResponseDto, - ActivityStatisticsResponseDto as StatsResponseDto, -} from '@app/domain/activity'; import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Response } from 'express'; -import { Auth, Authenticated } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { + ActivityCreateDto, + ActivityDto, + ActivityResponseDto, + ActivitySearchDto, + ActivityStatisticsResponseDto, +} from 'src/domain/activity/activity.dto'; +import { ActivityService } from 'src/domain/activity/activity.service'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { Auth, Authenticated } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Activity') @Controller('activity') @@ -20,21 +20,21 @@ export class ActivityController { constructor(private service: ActivityService) {} @Get() - getActivities(@Auth() auth: AuthDto, @Query() dto: ActivitySearchDto): Promise { + getActivities(@Auth() auth: AuthDto, @Query() dto: ActivitySearchDto): Promise { return this.service.getAll(auth, dto); } @Get('statistics') - getActivityStatistics(@Auth() auth: AuthDto, @Query() dto: ActivityDto): Promise { + getActivityStatistics(@Auth() auth: AuthDto, @Query() dto: ActivityDto): Promise { return this.service.getStatistics(auth, dto); } @Post() async createActivity( @Auth() auth: AuthDto, - @Body() dto: CreateDto, + @Body() dto: ActivityCreateDto, @Res({ passthrough: true }) res: Response, - ): Promise { + ): Promise { const { duplicate, value } = await this.service.create(auth, dto); if (duplicate) { res.status(HttpStatus.OK); diff --git a/server/src/immich/controllers/album.controller.ts b/server/src/immich/controllers/album.controller.ts index ea1c5a428..8981de212 100644 --- a/server/src/immich/controllers/album.controller.ts +++ b/server/src/immich/controllers/album.controller.ts @@ -1,21 +1,17 @@ -import { - AddUsersDto, - AlbumCountResponseDto, - AlbumInfoDto, - AlbumResponseDto, - AlbumService, - AuthDto, - BulkIdResponseDto, - BulkIdsDto, - CreateAlbumDto as CreateDto, - GetAlbumsDto, - UpdateAlbumDto as UpdateDto, -} from '@app/domain'; import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { ParseMeUUIDPipe } from '../api-v1/validation/parse-me-uuid-pipe'; -import { Auth, Authenticated, SharedLinkRoute } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { AlbumCountResponseDto, AlbumResponseDto } from 'src/domain/album/album-response.dto'; +import { AlbumService } from 'src/domain/album/album.service'; +import { AddUsersDto } from 'src/domain/album/dto/album-add-users.dto'; +import { CreateAlbumDto } from 'src/domain/album/dto/album-create.dto'; +import { UpdateAlbumDto } from 'src/domain/album/dto/album-update.dto'; +import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; +import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; +import { BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { ParseMeUUIDPipe } from 'src/immich/api-v1/validation/parse-me-uuid-pipe'; +import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Album') @Controller('album') @@ -34,7 +30,7 @@ export class AlbumController { } @Post() - createAlbum(@Auth() auth: AuthDto, @Body() dto: CreateDto): Promise { + createAlbum(@Auth() auth: AuthDto, @Body() dto: CreateAlbumDto): Promise { return this.service.create(auth, dto); } @@ -52,7 +48,7 @@ export class AlbumController { updateAlbumInfo( @Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, - @Body() dto: UpdateDto, + @Body() dto: UpdateAlbumDto, ): Promise { return this.service.update(auth, id, dto); } diff --git a/server/src/immich/controllers/api-key.controller.ts b/server/src/immich/controllers/api-key.controller.ts index 5b5072533..b9b449610 100644 --- a/server/src/immich/controllers/api-key.controller.ts +++ b/server/src/immich/controllers/api-key.controller.ts @@ -1,15 +1,15 @@ +import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto, - APIKeyService, APIKeyUpdateDto, - AuthDto, -} from '@app/domain'; -import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; -import { Auth, Authenticated } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +} from 'src/domain/api-key/api-key.dto'; +import { APIKeyService } from 'src/domain/api-key/api-key.service'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { Auth, Authenticated } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('API Key') @Controller('api-key') diff --git a/server/src/immich/controllers/app.controller.ts b/server/src/immich/controllers/app.controller.ts index 68a61c34c..0e916cd25 100644 --- a/server/src/immich/controllers/app.controller.ts +++ b/server/src/immich/controllers/app.controller.ts @@ -1,7 +1,7 @@ -import { SystemConfigService } from '@app/domain'; import { Controller, Get, Header } from '@nestjs/common'; import { ApiExcludeEndpoint } from '@nestjs/swagger'; -import { PublicRoute } from '../app.guard'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { PublicRoute } from 'src/immich/app.guard'; @Controller() export class AppController { diff --git a/server/src/immich/controllers/asset.controller.ts b/server/src/immich/controllers/asset.controller.ts index 39a36b175..d085dbe57 100644 --- a/server/src/immich/controllers/asset.controller.ts +++ b/server/src/immich/controllers/asset.controller.ts @@ -1,31 +1,28 @@ +import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common'; +import { ApiOperation, ApiTags } from '@nestjs/swagger'; +import { AssetService } from 'src/domain/asset/asset.service'; +import { AssetJobsDto } from 'src/domain/asset/dto/asset-ids.dto'; +import { UpdateStackParentDto } from 'src/domain/asset/dto/asset-stack.dto'; +import { AssetStatsDto, AssetStatsResponseDto } from 'src/domain/asset/dto/asset-statistics.dto'; import { AssetBulkDeleteDto, AssetBulkUpdateDto, - AssetJobsDto, - AssetResponseDto, - AssetService, - AssetStatsDto, - AssetStatsResponseDto, - AuthDto, DeviceIdDto, - MapMarkerDto, - MapMarkerResponseDto, - MemoryLaneDto, - MemoryLaneResponseDto, - MetadataSearchDto, RandomAssetsDto, - SearchService, - TimeBucketAssetDto, - TimeBucketDto, - TimeBucketResponseDto, - UpdateAssetDto as UpdateDto, - UpdateStackParentDto, -} from '@app/domain'; -import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common'; -import { ApiOperation, ApiTags } from '@nestjs/swagger'; -import { Auth, Authenticated, SharedLinkRoute } from '../app.guard'; -import { Route } from '../interceptors'; -import { UUIDParamDto } from './dto/uuid-param.dto'; + UpdateAssetDto, +} from 'src/domain/asset/dto/asset.dto'; +import { MapMarkerDto } from 'src/domain/asset/dto/map-marker.dto'; +import { MemoryLaneDto } from 'src/domain/asset/dto/memory-lane.dto'; +import { TimeBucketAssetDto, TimeBucketDto } from 'src/domain/asset/dto/time-bucket.dto'; +import { AssetResponseDto, MemoryLaneResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; +import { MapMarkerResponseDto } from 'src/domain/asset/response-dto/map-marker-response.dto'; +import { TimeBucketResponseDto } from 'src/domain/asset/response-dto/time-bucket-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { MetadataSearchDto } from 'src/domain/search/dto/search.dto'; +import { SearchService } from 'src/domain/search/search.service'; +import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { Route } from 'src/immich/interceptors/file-upload.interceptor'; @ApiTags('Asset') @Controller('assets') @@ -120,7 +117,11 @@ export class AssetController { } @Put(':id') - updateAsset(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto, @Body() dto: UpdateDto): Promise { + updateAsset( + @Auth() auth: AuthDto, + @Param() { id }: UUIDParamDto, + @Body() dto: UpdateAssetDto, + ): Promise { return this.service.update(auth, id, dto); } } diff --git a/server/src/immich/controllers/audit.controller.ts b/server/src/immich/controllers/audit.controller.ts index 09b707b8a..468257d26 100644 --- a/server/src/immich/controllers/audit.controller.ts +++ b/server/src/immich/controllers/audit.controller.ts @@ -1,16 +1,16 @@ +import { Body, Controller, Get, Post, Query } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; import { AuditDeletesDto, AuditDeletesResponseDto, - AuditService, - AuthDto, FileChecksumDto, FileChecksumResponseDto, FileReportDto, FileReportFixDto, -} from '@app/domain'; -import { Body, Controller, Get, Post, Query } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; -import { AdminRoute, Auth, Authenticated } from '../app.guard'; +} from 'src/domain/audit/audit.dto'; +import { AuditService } from 'src/domain/audit/audit.service'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AdminRoute, Auth, Authenticated } from 'src/immich/app.guard'; @ApiTags('Audit') @Controller('audit') diff --git a/server/src/immich/controllers/auth.controller.ts b/server/src/immich/controllers/auth.controller.ts index ac1fea2bc..b2dece148 100644 --- a/server/src/immich/controllers/auth.controller.ts +++ b/server/src/immich/controllers/auth.controller.ts @@ -1,25 +1,21 @@ -import { - AuthDeviceResponseDto, - AuthDto, - AuthService, - ChangePasswordDto, - IMMICH_ACCESS_COOKIE, - IMMICH_AUTH_TYPE_COOKIE, - IMMICH_IS_AUTHENTICATED, - LoginCredentialDto, - LoginDetails, - LoginResponseDto, - LogoutResponseDto, - SignUpDto, - UserResponseDto, - ValidateAccessTokenResponseDto, - mapUser, -} from '@app/domain'; import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Req, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; -import { Auth, Authenticated, GetLoginDetails, PublicRoute } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { IMMICH_ACCESS_COOKIE, IMMICH_AUTH_TYPE_COOKIE, IMMICH_IS_AUTHENTICATED } from 'src/domain/auth/auth.constant'; +import { + AuthDeviceResponseDto, + AuthDto, + ChangePasswordDto, + LoginCredentialDto, + LoginResponseDto, + LogoutResponseDto, + SignUpDto, + ValidateAccessTokenResponseDto, +} from 'src/domain/auth/auth.dto'; +import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; +import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Authentication') @Controller('auth') diff --git a/server/src/immich/controllers/download.controller.ts b/server/src/immich/controllers/download.controller.ts index 743797f74..41849a41d 100644 --- a/server/src/immich/controllers/download.controller.ts +++ b/server/src/immich/controllers/download.controller.ts @@ -1,10 +1,13 @@ -import { AssetIdsDto, AuthDto, DownloadInfoDto, DownloadResponseDto, DownloadService } from '@app/domain'; import { Body, Controller, HttpCode, HttpStatus, Next, Param, Post, Res, StreamableFile } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { Auth, Authenticated, FileResponse, SharedLinkRoute } from '../app.guard'; -import { asStreamableFile, sendFile } from '../app.utils'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/download.dto'; +import { DownloadService } from 'src/domain/download/download.service'; +import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/immich/app.guard'; +import { asStreamableFile, sendFile } from 'src/immich/app.utils'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Download') @Controller('download') diff --git a/server/src/immich/controllers/face.controller.ts b/server/src/immich/controllers/face.controller.ts index f4014713b..0fab1bb91 100644 --- a/server/src/immich/controllers/face.controller.ts +++ b/server/src/immich/controllers/face.controller.ts @@ -1,8 +1,10 @@ -import { AssetFaceResponseDto, AuthDto, FaceDto, PersonResponseDto, PersonService } from '@app/domain'; import { Body, Controller, Get, Param, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { Auth, Authenticated } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AssetFaceResponseDto, FaceDto, PersonResponseDto } from 'src/domain/person/person.dto'; +import { PersonService } from 'src/domain/person/person.service'; +import { Auth, Authenticated } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Face') @Controller('face') diff --git a/server/src/immich/controllers/index.ts b/server/src/immich/controllers/index.ts deleted file mode 100644 index f4e473091..000000000 --- a/server/src/immich/controllers/index.ts +++ /dev/null @@ -1,21 +0,0 @@ -export * from './activity.controller'; -export * from './album.controller'; -export * from './api-key.controller'; -export * from './app.controller'; -export * from './asset.controller'; -export * from './audit.controller'; -export * from './auth.controller'; -export * from './download.controller'; -export * from './face.controller'; -export * from './job.controller'; -export * from './library.controller'; -export * from './oauth.controller'; -export * from './partner.controller'; -export * from './person.controller'; -export * from './search.controller'; -export * from './server-info.controller'; -export * from './shared-link.controller'; -export * from './system-config.controller'; -export * from './tag.controller'; -export * from './trash.controller'; -export * from './user.controller'; diff --git a/server/src/immich/controllers/job.controller.ts b/server/src/immich/controllers/job.controller.ts index 413af44de..e5a8aac54 100644 --- a/server/src/immich/controllers/job.controller.ts +++ b/server/src/immich/controllers/job.controller.ts @@ -1,7 +1,8 @@ -import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobService, JobStatusDto } from '@app/domain'; import { Body, Controller, Get, Param, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { Authenticated } from '../app.guard'; +import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobStatusDto } from 'src/domain/job/job.dto'; +import { JobService } from 'src/domain/job/job.service'; +import { Authenticated } from 'src/immich/app.guard'; @ApiTags('Job') @Controller('jobs') diff --git a/server/src/immich/controllers/library.controller.ts b/server/src/immich/controllers/library.controller.ts index 2b509645c..d72461988 100644 --- a/server/src/immich/controllers/library.controller.ts +++ b/server/src/immich/controllers/library.controller.ts @@ -1,18 +1,18 @@ -import { - CreateLibraryDto as CreateDto, - LibraryService, - LibraryStatsResponseDto, - LibraryResponseDto as ResponseDto, - ScanLibraryDto, - SearchLibraryDto, - UpdateLibraryDto as UpdateDto, - ValidateLibraryDto, - ValidateLibraryResponseDto, -} from '@app/domain'; import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AdminRoute, Authenticated } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { + CreateLibraryDto, + LibraryResponseDto, + LibraryStatsResponseDto, + ScanLibraryDto, + SearchLibraryDto, + UpdateLibraryDto, + ValidateLibraryDto, + ValidateLibraryResponseDto, +} from 'src/domain/library/library.dto'; +import { LibraryService } from 'src/domain/library/library.service'; +import { AdminRoute, Authenticated } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Library') @Controller('library') @@ -22,22 +22,22 @@ export class LibraryController { constructor(private service: LibraryService) {} @Get() - getAllLibraries(@Query() dto: SearchLibraryDto): Promise { + getAllLibraries(@Query() dto: SearchLibraryDto): Promise { return this.service.getAll(dto); } @Post() - createLibrary(@Body() dto: CreateDto): Promise { + createLibrary(@Body() dto: CreateLibraryDto): Promise { return this.service.create(dto); } @Put(':id') - updateLibrary(@Param() { id }: UUIDParamDto, @Body() dto: UpdateDto): Promise { + updateLibrary(@Param() { id }: UUIDParamDto, @Body() dto: UpdateLibraryDto): Promise { return this.service.update(id, dto); } @Get(':id') - getLibrary(@Param() { id }: UUIDParamDto): Promise { + getLibrary(@Param() { id }: UUIDParamDto): Promise { return this.service.get(id); } diff --git a/server/src/immich/controllers/oauth.controller.ts b/server/src/immich/controllers/oauth.controller.ts index c7a5717af..8d7ce9478 100644 --- a/server/src/immich/controllers/oauth.controller.ts +++ b/server/src/immich/controllers/oauth.controller.ts @@ -1,17 +1,16 @@ +import { Body, Controller, Get, HttpStatus, Post, Redirect, Req, Res } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; +import { Request, Response } from 'express'; import { AuthDto, - AuthService, - LoginDetails, LoginResponseDto, OAuthAuthorizeResponseDto, OAuthCallbackDto, OAuthConfigDto, - UserResponseDto, -} from '@app/domain'; -import { Body, Controller, Get, HttpStatus, Post, Redirect, Req, Res } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; -import { Request, Response } from 'express'; -import { Auth, Authenticated, GetLoginDetails, PublicRoute } from '../app.guard'; +} from 'src/domain/auth/auth.dto'; +import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; +import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; +import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/immich/app.guard'; @ApiTags('OAuth') @Controller('oauth') diff --git a/server/src/immich/controllers/partner.controller.ts b/server/src/immich/controllers/partner.controller.ts index 65d95438d..43c388e10 100644 --- a/server/src/immich/controllers/partner.controller.ts +++ b/server/src/immich/controllers/partner.controller.ts @@ -1,9 +1,11 @@ -import { AuthDto, PartnerDirection, PartnerService } from '@app/domain'; -import { PartnerResponseDto, UpdatePartnerDto } from '@app/domain/partner/partner.dto'; import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common'; import { ApiQuery, ApiTags } from '@nestjs/swagger'; -import { Auth, Authenticated } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; +import { PartnerService } from 'src/domain/partner/partner.service'; +import { PartnerDirection } from 'src/domain/repositories/partner.repository'; +import { Auth, Authenticated } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Partner') @Controller('partner') diff --git a/server/src/immich/controllers/person.controller.ts b/server/src/immich/controllers/person.controller.ts index 3408aa6ec..c2b789678 100644 --- a/server/src/immich/controllers/person.controller.ts +++ b/server/src/immich/controllers/person.controller.ts @@ -1,24 +1,24 @@ +import { Body, Controller, Get, Next, Param, Post, Put, Query, Res } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; +import { NextFunction, Response } from 'express'; +import { BulkIdResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; import { AssetFaceUpdateDto, - AssetResponseDto, - AuthDto, - BulkIdResponseDto, MergePersonDto, PeopleResponseDto, PeopleUpdateDto, PersonCreateDto, PersonResponseDto, PersonSearchDto, - PersonService, PersonStatisticsResponseDto, PersonUpdateDto, -} from '@app/domain'; -import { Body, Controller, Get, Next, Param, Post, Put, Query, Res } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; -import { NextFunction, Response } from 'express'; -import { Auth, Authenticated, FileResponse } from '../app.guard'; -import { sendFile } from '../app.utils'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +} from 'src/domain/person/person.dto'; +import { PersonService } from 'src/domain/person/person.service'; +import { Auth, Authenticated, FileResponse } from 'src/immich/app.guard'; +import { sendFile } from 'src/immich/app.utils'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Person') @Controller('person') diff --git a/server/src/immich/controllers/search.controller.ts b/server/src/immich/controllers/search.controller.ts index a3527a66a..4f8f19fd8 100644 --- a/server/src/immich/controllers/search.controller.ts +++ b/server/src/immich/controllers/search.controller.ts @@ -1,21 +1,21 @@ -import { - AssetResponseDto, - AuthDto, - MetadataSearchDto, - PersonResponseDto, - PlacesResponseDto, - SearchDto, - SearchExploreResponseDto, - SearchPeopleDto, - SearchPlacesDto, - SearchResponseDto, - SearchService, - SmartSearchDto, -} from '@app/domain'; -import { SearchSuggestionRequestDto } from '@app/domain/search/dto/search-suggestion.dto'; import { Body, Controller, Get, HttpCode, HttpStatus, Post, Query } from '@nestjs/common'; import { ApiOperation, ApiTags } from '@nestjs/swagger'; -import { Auth, Authenticated } from '../app.guard'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { PersonResponseDto } from 'src/domain/person/person.dto'; +import { SearchSuggestionRequestDto } from 'src/domain/search/dto/search-suggestion.dto'; +import { + MetadataSearchDto, + PlacesResponseDto, + SearchDto, + SearchPeopleDto, + SearchPlacesDto, + SmartSearchDto, +} from 'src/domain/search/dto/search.dto'; +import { SearchExploreResponseDto } from 'src/domain/search/response-dto/search-explore.response.dto'; +import { SearchResponseDto } from 'src/domain/search/response-dto/search-response.dto'; +import { SearchService } from 'src/domain/search/search.service'; +import { Auth, Authenticated } from 'src/immich/app.guard'; @ApiTags('Search') @Controller('search') diff --git a/server/src/immich/controllers/server-info.controller.ts b/server/src/immich/controllers/server-info.controller.ts index 4987a8984..5ff3de55e 100644 --- a/server/src/immich/controllers/server-info.controller.ts +++ b/server/src/immich/controllers/server-info.controller.ts @@ -1,17 +1,17 @@ +import { Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common'; +import { ApiTags } from '@nestjs/swagger'; import { ServerConfigDto, ServerFeaturesDto, ServerInfoResponseDto, - ServerInfoService, ServerMediaTypesResponseDto, ServerPingResponse, ServerStatsResponseDto, ServerThemeDto, ServerVersionResponseDto, -} from '@app/domain'; -import { Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common'; -import { ApiTags } from '@nestjs/swagger'; -import { AdminRoute, Authenticated, PublicRoute } from '../app.guard'; +} from 'src/domain/server-info/server-info.dto'; +import { ServerInfoService } from 'src/domain/server-info/server-info.service'; +import { AdminRoute, Authenticated, PublicRoute } from 'src/immich/app.guard'; @ApiTags('Server Info') @Controller('server-info') diff --git a/server/src/immich/controllers/shared-link.controller.ts b/server/src/immich/controllers/shared-link.controller.ts index d265d018d..39e4c084e 100644 --- a/server/src/immich/controllers/shared-link.controller.ts +++ b/server/src/immich/controllers/shared-link.controller.ts @@ -1,19 +1,15 @@ -import { - AssetIdsDto, - AssetIdsResponseDto, - AuthDto, - IMMICH_SHARED_LINK_ACCESS_COOKIE, - SharedLinkCreateDto, - SharedLinkEditDto, - SharedLinkPasswordDto, - SharedLinkResponseDto, - SharedLinkService, -} from '@app/domain'; import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query, Req, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; -import { Auth, Authenticated, SharedLinkRoute } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; +import { AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { IMMICH_SHARED_LINK_ACCESS_COOKIE } from 'src/domain/auth/auth.constant'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { SharedLinkResponseDto } from 'src/domain/shared-link/shared-link-response.dto'; +import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; +import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; +import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Shared Link') @Controller('shared-link') diff --git a/server/src/immich/controllers/system-config.controller.ts b/server/src/immich/controllers/system-config.controller.ts index 73cf2c3c0..6d1ea8f1d 100644 --- a/server/src/immich/controllers/system-config.controller.ts +++ b/server/src/immich/controllers/system-config.controller.ts @@ -1,8 +1,10 @@ -import { SystemConfigDto, SystemConfigService, SystemConfigTemplateStorageOptionDto } from '@app/domain'; -import { MapThemeDto } from '@app/domain/system-config/system-config-map-theme.dto'; import { Body, Controller, Get, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AdminRoute, Authenticated } from '../app.guard'; +import { SystemConfigDto } from 'src/domain/system-config/dto/system-config.dto'; +import { SystemConfigTemplateStorageOptionDto } from 'src/domain/system-config/response-dto/system-config-template-storage-option.dto'; +import { MapThemeDto } from 'src/domain/system-config/system-config-map-theme.dto'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { AdminRoute, Authenticated } from 'src/immich/app.guard'; @ApiTags('System Config') @Controller('system-config') diff --git a/server/src/immich/controllers/tag.controller.ts b/server/src/immich/controllers/tag.controller.ts index 0d0c563d4..511d7b1d1 100644 --- a/server/src/immich/controllers/tag.controller.ts +++ b/server/src/immich/controllers/tag.controller.ts @@ -1,17 +1,14 @@ -import { - AssetIdsDto, - AssetIdsResponseDto, - AssetResponseDto, - AuthDto, - CreateTagDto, - TagResponseDto, - TagService, - UpdateTagDto, -} from '@app/domain'; import { Body, Controller, Delete, Get, Param, Patch, Post, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { Auth, Authenticated } from '../app.guard'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; +import { AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { TagResponseDto } from 'src/domain/tag/tag-response.dto'; +import { CreateTagDto, UpdateTagDto } from 'src/domain/tag/tag.dto'; +import { TagService } from 'src/domain/tag/tag.service'; +import { Auth, Authenticated } from 'src/immich/app.guard'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; @ApiTags('Tag') @Controller('tag') diff --git a/server/src/immich/controllers/trash.controller.ts b/server/src/immich/controllers/trash.controller.ts index b61893817..44d68abbe 100644 --- a/server/src/immich/controllers/trash.controller.ts +++ b/server/src/immich/controllers/trash.controller.ts @@ -1,7 +1,9 @@ -import { AuthDto, BulkIdsDto, TrashService } from '@app/domain'; import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { Auth, Authenticated } from '../app.guard'; +import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { TrashService } from 'src/domain/trash/trash.service'; +import { Auth, Authenticated } from 'src/immich/app.guard'; @ApiTags('Trash') @Controller('trash') diff --git a/server/src/immich/controllers/user.controller.ts b/server/src/immich/controllers/user.controller.ts index 0b3828f5c..10b16859f 100644 --- a/server/src/immich/controllers/user.controller.ts +++ b/server/src/immich/controllers/user.controller.ts @@ -1,13 +1,3 @@ -import { - AuthDto, - CreateUserDto as CreateDto, - CreateProfileImageDto, - CreateProfileImageResponseDto, - DeleteUserDto, - UpdateUserDto as UpdateDto, - UserResponseDto, - UserService, -} from '@app/domain'; import { Body, Controller, @@ -26,10 +16,18 @@ import { } from '@nestjs/common'; import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { AdminRoute, Auth, Authenticated, FileResponse } from '../app.guard'; -import { sendFile } from '../app.utils'; -import { FileUploadInterceptor, Route } from '../interceptors'; -import { UUIDParamDto } from './dto/uuid-param.dto'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { CreateProfileImageDto } from 'src/domain/user/dto/create-profile-image.dto'; +import { CreateUserDto } from 'src/domain/user/dto/create-user.dto'; +import { DeleteUserDto } from 'src/domain/user/dto/delete-user.dto'; +import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; +import { CreateProfileImageResponseDto } from 'src/domain/user/response-dto/create-profile-image-response.dto'; +import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; +import { UserService } from 'src/domain/user/user.service'; +import { AdminRoute, Auth, Authenticated, FileResponse } from 'src/immich/app.guard'; +import { sendFile } from 'src/immich/app.utils'; +import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { FileUploadInterceptor, Route } from 'src/immich/interceptors/file-upload.interceptor'; @ApiTags('User') @Controller(Route.USER) @@ -54,7 +52,7 @@ export class UserController { @AdminRoute() @Post() - createUser(@Body() createUserDto: CreateDto): Promise { + createUser(@Body() createUserDto: CreateUserDto): Promise { return this.service.create(createUserDto); } @@ -82,7 +80,7 @@ export class UserController { // TODO: replace with @Put(':id') @Put() - updateUser(@Auth() auth: AuthDto, @Body() updateUserDto: UpdateDto): Promise { + updateUser(@Auth() auth: AuthDto, @Body() updateUserDto: UpdateUserDto): Promise { return this.service.update(auth, updateUserDto); } diff --git a/server/src/immich/index.ts b/server/src/immich/index.ts deleted file mode 100644 index c590fa83e..000000000 --- a/server/src/immich/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './app.module'; -export * from './controllers'; diff --git a/server/src/immich/interceptors/error.interceptor.ts b/server/src/immich/interceptors/error.interceptor.ts index 5fabdbe55..809464b37 100644 --- a/server/src/immich/interceptors/error.interceptor.ts +++ b/server/src/immich/interceptors/error.interceptor.ts @@ -1,4 +1,3 @@ -import { ImmichLogger } from '@app/infra/logger'; import { CallHandler, ExecutionContext, @@ -8,8 +7,9 @@ import { NestInterceptor, } from '@nestjs/common'; import { Observable, catchError, throwError } from 'rxjs'; -import { isConnectionAborted } from '../../domain'; -import { routeToErrorMessage } from '../app.utils'; +import { isConnectionAborted } from 'src/domain/domain.util'; +import { routeToErrorMessage } from 'src/immich/app.utils'; +import { ImmichLogger } from 'src/infra/logger'; @Injectable() export class ErrorInterceptor implements NestInterceptor { diff --git a/server/src/immich/interceptors/file-upload.interceptor.ts b/server/src/immich/interceptors/file-upload.interceptor.ts index a698dc8a6..9284ade39 100644 --- a/server/src/immich/interceptors/file-upload.interceptor.ts +++ b/server/src/immich/interceptors/file-upload.interceptor.ts @@ -1,5 +1,3 @@ -import { AssetService, UploadFieldName, UploadFile } from '@app/domain'; -import { ImmichLogger } from '@app/infra/logger'; import { CallHandler, ExecutionContext, Injectable, NestInterceptor } from '@nestjs/common'; import { PATH_METADATA } from '@nestjs/common/constants'; import { Reflector } from '@nestjs/core'; @@ -8,7 +6,9 @@ import { NextFunction, RequestHandler } from 'express'; import multer, { StorageEngine, diskStorage } from 'multer'; import { createHash, randomUUID } from 'node:crypto'; import { Observable } from 'rxjs'; -import { AuthRequest } from '../app.guard'; +import { AssetService, UploadFieldName, UploadFile } from 'src/domain/asset/asset.service'; +import { AuthRequest } from 'src/immich/app.guard'; +import { ImmichLogger } from 'src/infra/logger'; export enum Route { ASSET = 'asset', diff --git a/server/src/immich/interceptors/index.ts b/server/src/immich/interceptors/index.ts deleted file mode 100644 index 5811b3232..000000000 --- a/server/src/immich/interceptors/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './error.interceptor'; -export * from './file-upload.interceptor'; diff --git a/server/src/immich/main.ts b/server/src/immich/main.ts index 60e323e6a..adfe476a2 100644 --- a/server/src/immich/main.ts +++ b/server/src/immich/main.ts @@ -1,16 +1,17 @@ -import { WEB_ROOT, envName, isDev, serverVersion } from '@app/domain'; -import { WebSocketAdapter, excludePaths } from '@app/infra'; -import { otelSDK } from '@app/infra/instrumentation'; -import { ImmichLogger } from '@app/infra/logger'; import { NestFactory } from '@nestjs/core'; import { NestExpressApplication } from '@nestjs/platform-express'; import { json } from 'body-parser'; import cookieParser from 'cookie-parser'; import { existsSync } from 'node:fs'; import sirv from 'sirv'; -import { AppModule } from './app.module'; -import { AppService } from './app.service'; -import { useSwagger } from './app.utils'; +import { WEB_ROOT, envName, isDev, serverVersion } from 'src/domain/domain.constant'; +import { AppModule } from 'src/immich/app.module'; +import { AppService } from 'src/immich/app.service'; +import { useSwagger } from 'src/immich/app.utils'; +import { excludePaths } from 'src/infra/infra.config'; +import { otelSDK } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; +import { WebSocketAdapter } from 'src/infra/websocket.adapter'; const logger = new ImmichLogger('ImmichServer'); const port = Number(process.env.SERVER_PORT) || 3001; diff --git a/server/src/infra/database.config.ts b/server/src/infra/database.config.ts index 773e79f8a..ccb0f6a32 100644 --- a/server/src/infra/database.config.ts +++ b/server/src/infra/database.config.ts @@ -1,4 +1,4 @@ -import { DatabaseExtension } from '@app/domain/repositories/database.repository'; +import { DatabaseExtension } from 'src/domain/repositories/database.repository'; import { DataSource } from 'typeorm'; import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js'; diff --git a/server/src/infra/entities/activity.entity.ts b/server/src/infra/entities/activity.entity.ts index 255a3a708..478595556 100644 --- a/server/src/infra/entities/activity.entity.ts +++ b/server/src/infra/entities/activity.entity.ts @@ -1,3 +1,6 @@ +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; import { Check, Column, @@ -8,9 +11,6 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -import { AlbumEntity } from './album.entity'; -import { AssetEntity } from './asset.entity'; -import { UserEntity } from './user.entity'; @Entity('activity') @Index('IDX_activity_like', ['assetId', 'userId', 'albumId'], { unique: true, where: '("isLiked" = true)' }) diff --git a/server/src/infra/entities/album.entity.ts b/server/src/infra/entities/album.entity.ts index daa8fcbc3..ab15d401d 100644 --- a/server/src/infra/entities/album.entity.ts +++ b/server/src/infra/entities/album.entity.ts @@ -1,3 +1,6 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; import { Column, CreateDateColumn, @@ -10,9 +13,6 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -import { AssetEntity } from './asset.entity'; -import { SharedLinkEntity } from './shared-link.entity'; -import { UserEntity } from './user.entity'; // ran into issues when importing the enum from `asset.dto.ts` export enum AssetOrder { diff --git a/server/src/infra/entities/api-key.entity.ts b/server/src/infra/entities/api-key.entity.ts index 0c8252fe4..0d1893398 100644 --- a/server/src/infra/entities/api-key.entity.ts +++ b/server/src/infra/entities/api-key.entity.ts @@ -1,5 +1,5 @@ +import { UserEntity } from 'src/infra/entities/user.entity'; import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; -import { UserEntity } from './user.entity'; @Entity('api_keys') export class APIKeyEntity { diff --git a/server/src/infra/entities/asset-face.entity.ts b/server/src/infra/entities/asset-face.entity.ts index 1561f67d0..afd2a263a 100644 --- a/server/src/infra/entities/asset-face.entity.ts +++ b/server/src/infra/entities/asset-face.entity.ts @@ -1,6 +1,6 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; import { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; -import { AssetEntity } from './asset.entity'; -import { PersonEntity } from './person.entity'; @Entity('asset_faces', { synchronize: false }) @Index('IDX_asset_faces_assetId_personId', ['assetId', 'personId']) diff --git a/server/src/infra/entities/asset-job-status.entity.ts b/server/src/infra/entities/asset-job-status.entity.ts index f1965fbdb..22d98e367 100644 --- a/server/src/infra/entities/asset-job-status.entity.ts +++ b/server/src/infra/entities/asset-job-status.entity.ts @@ -1,5 +1,5 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; -import { AssetEntity } from './asset.entity'; @Entity('asset_job_status') export class AssetJobStatusEntity { diff --git a/server/src/infra/entities/asset-stack.entity.ts b/server/src/infra/entities/asset-stack.entity.ts index d005fc0a5..372fac1e4 100644 --- a/server/src/infra/entities/asset-stack.entity.ts +++ b/server/src/infra/entities/asset-stack.entity.ts @@ -1,5 +1,5 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; import { Column, Entity, JoinColumn, OneToMany, OneToOne, PrimaryGeneratedColumn } from 'typeorm'; -import { AssetEntity } from './asset.entity'; @Entity('asset_stack') export class AssetStackEntity { diff --git a/server/src/infra/entities/asset.entity.ts b/server/src/infra/entities/asset.entity.ts index 78a961757..e82bbfb00 100644 --- a/server/src/infra/entities/asset.entity.ts +++ b/server/src/infra/entities/asset.entity.ts @@ -1,3 +1,14 @@ +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; +import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { LibraryEntity } from 'src/infra/entities/library.entity'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { SmartSearchEntity } from 'src/infra/entities/smart-search.entity'; +import { TagEntity } from 'src/infra/entities/tag.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; import { Column, CreateDateColumn, @@ -13,17 +24,6 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -import { AlbumEntity } from './album.entity'; -import { AssetFaceEntity } from './asset-face.entity'; -import { AssetJobStatusEntity } from './asset-job-status.entity'; -import { AssetStackEntity } from './asset-stack.entity'; -import { ExifEntity } from './exif.entity'; -import { LibraryEntity } from './library.entity'; -import { SharedLinkEntity } from './shared-link.entity'; -import { SmartInfoEntity } from './smart-info.entity'; -import { SmartSearchEntity } from './smart-search.entity'; -import { TagEntity } from './tag.entity'; -import { UserEntity } from './user.entity'; export const ASSET_CHECKSUM_CONSTRAINT = 'UQ_assets_owner_library_checksum'; diff --git a/server/src/infra/entities/exif.entity.ts b/server/src/infra/entities/exif.entity.ts index 639e24a50..8ed645d11 100644 --- a/server/src/infra/entities/exif.entity.ts +++ b/server/src/infra/entities/exif.entity.ts @@ -1,7 +1,7 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; import { Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; import { Column } from 'typeorm/decorator/columns/Column.js'; import { Entity } from 'typeorm/decorator/entity/Entity.js'; -import { AssetEntity } from './asset.entity'; @Entity('exif') export class ExifEntity { diff --git a/server/src/infra/entities/index.ts b/server/src/infra/entities/index.ts index af620790e..47fc3c7f1 100644 --- a/server/src/infra/entities/index.ts +++ b/server/src/infra/entities/index.ts @@ -1,48 +1,25 @@ -import { ActivityEntity } from './activity.entity'; -import { AlbumEntity } from './album.entity'; -import { APIKeyEntity } from './api-key.entity'; -import { AssetFaceEntity } from './asset-face.entity'; -import { AssetJobStatusEntity } from './asset-job-status.entity'; -import { AssetStackEntity } from './asset-stack.entity'; -import { AssetEntity } from './asset.entity'; -import { AuditEntity } from './audit.entity'; -import { ExifEntity } from './exif.entity'; -import { GeodataPlacesEntity } from './geodata-places.entity'; -import { LibraryEntity } from './library.entity'; -import { MoveEntity } from './move.entity'; -import { PartnerEntity } from './partner.entity'; -import { PersonEntity } from './person.entity'; -import { SharedLinkEntity } from './shared-link.entity'; -import { SmartInfoEntity } from './smart-info.entity'; -import { SmartSearchEntity } from './smart-search.entity'; -import { SystemConfigEntity } from './system-config.entity'; -import { SystemMetadataEntity } from './system-metadata.entity'; -import { TagEntity } from './tag.entity'; -import { UserTokenEntity } from './user-token.entity'; -import { UserEntity } from './user.entity'; - -export * from './activity.entity'; -export * from './album.entity'; -export * from './api-key.entity'; -export * from './asset-face.entity'; -export * from './asset-job-status.entity'; -export * from './asset-stack.entity'; -export * from './asset.entity'; -export * from './audit.entity'; -export * from './exif.entity'; -export * from './geodata-places.entity'; -export * from './library.entity'; -export * from './move.entity'; -export * from './partner.entity'; -export * from './person.entity'; -export * from './shared-link.entity'; -export * from './smart-info.entity'; -export * from './smart-search.entity'; -export * from './system-config.entity'; -export * from './system-metadata.entity'; -export * from './tag.entity'; -export * from './user-token.entity'; -export * from './user.entity'; +import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; +import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AuditEntity } from 'src/infra/entities/audit.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; +import { LibraryEntity } from 'src/infra/entities/library.entity'; +import { MoveEntity } from 'src/infra/entities/move.entity'; +import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { SmartSearchEntity } from 'src/infra/entities/smart-search.entity'; +import { SystemConfigEntity } from 'src/infra/entities/system-config.entity'; +import { SystemMetadataEntity } from 'src/infra/entities/system-metadata.entity'; +import { TagEntity } from 'src/infra/entities/tag.entity'; +import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; export const databaseEntities = [ ActivityEntity, diff --git a/server/src/infra/entities/library.entity.ts b/server/src/infra/entities/library.entity.ts index bf5f444ab..f68a38095 100644 --- a/server/src/infra/entities/library.entity.ts +++ b/server/src/infra/entities/library.entity.ts @@ -1,3 +1,5 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; import { Column, CreateDateColumn, @@ -9,8 +11,6 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -import { AssetEntity } from './asset.entity'; -import { UserEntity } from './user.entity'; @Entity('libraries') export class LibraryEntity { diff --git a/server/src/infra/entities/partner.entity.ts b/server/src/infra/entities/partner.entity.ts index 35d32e4c9..abf0400da 100644 --- a/server/src/infra/entities/partner.entity.ts +++ b/server/src/infra/entities/partner.entity.ts @@ -1,7 +1,6 @@ +import { UserEntity } from 'src/infra/entities/user.entity'; import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm'; -import { UserEntity } from './user.entity'; - @Entity('partners') export class PartnerEntity { @PrimaryColumn('uuid') diff --git a/server/src/infra/entities/person.entity.ts b/server/src/infra/entities/person.entity.ts index ecba45dd2..046ac9d40 100644 --- a/server/src/infra/entities/person.entity.ts +++ b/server/src/infra/entities/person.entity.ts @@ -1,3 +1,5 @@ +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; import { Check, Column, @@ -8,8 +10,6 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -import { AssetFaceEntity } from './asset-face.entity'; -import { UserEntity } from './user.entity'; @Entity('person') @Check(`"birthDate" <= CURRENT_DATE`) diff --git a/server/src/infra/entities/shared-link.entity.ts b/server/src/infra/entities/shared-link.entity.ts index e7cd19e53..7370146df 100644 --- a/server/src/infra/entities/shared-link.entity.ts +++ b/server/src/infra/entities/shared-link.entity.ts @@ -1,3 +1,6 @@ +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; import { Column, CreateDateColumn, @@ -8,9 +11,6 @@ import { PrimaryGeneratedColumn, Unique, } from 'typeorm'; -import { AlbumEntity } from './album.entity'; -import { AssetEntity } from './asset.entity'; -import { UserEntity } from './user.entity'; @Entity('shared_links') @Unique('UQ_sharedlink_key', ['key']) diff --git a/server/src/infra/entities/smart-info.entity.ts b/server/src/infra/entities/smart-info.entity.ts index 2606de60e..5bd65e7fb 100644 --- a/server/src/infra/entities/smart-info.entity.ts +++ b/server/src/infra/entities/smart-info.entity.ts @@ -1,5 +1,5 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; -import { AssetEntity } from './asset.entity'; @Entity('smart_info', { synchronize: false }) export class SmartInfoEntity { diff --git a/server/src/infra/entities/smart-search.entity.ts b/server/src/infra/entities/smart-search.entity.ts index 2b295ac90..bbd966fd4 100644 --- a/server/src/infra/entities/smart-search.entity.ts +++ b/server/src/infra/entities/smart-search.entity.ts @@ -1,5 +1,5 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; -import { AssetEntity } from './asset.entity'; @Entity('smart_search', { synchronize: false }) export class SmartSearchEntity { diff --git a/server/src/infra/entities/system-config.entity.ts b/server/src/infra/entities/system-config.entity.ts index 1ba219429..cf7474417 100644 --- a/server/src/infra/entities/system-config.entity.ts +++ b/server/src/infra/entities/system-config.entity.ts @@ -1,4 +1,4 @@ -import { ConcurrentQueueName } from '@app/domain'; +import { ConcurrentQueueName } from 'src/domain/job/job.constants'; import { Column, Entity, PrimaryColumn } from 'typeorm'; @Entity('system_config') diff --git a/server/src/infra/entities/tag.entity.ts b/server/src/infra/entities/tag.entity.ts index a364529db..b159dcb2e 100644 --- a/server/src/infra/entities/tag.entity.ts +++ b/server/src/infra/entities/tag.entity.ts @@ -1,6 +1,6 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; import { Column, Entity, ManyToMany, ManyToOne, PrimaryGeneratedColumn, Unique } from 'typeorm'; -import { AssetEntity } from './asset.entity'; -import { UserEntity } from './user.entity'; @Entity('tags') @Unique('UQ_tag_name_userId', ['name', 'userId']) diff --git a/server/src/infra/entities/user-token.entity.ts b/server/src/infra/entities/user-token.entity.ts index a39e93a33..fd04c20dd 100644 --- a/server/src/infra/entities/user-token.entity.ts +++ b/server/src/infra/entities/user-token.entity.ts @@ -1,5 +1,5 @@ +import { UserEntity } from 'src/infra/entities/user.entity'; import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; -import { UserEntity } from './user.entity'; @Entity('user_token') export class UserTokenEntity { diff --git a/server/src/infra/entities/user.entity.ts b/server/src/infra/entities/user.entity.ts index 20c057d79..888655d3b 100644 --- a/server/src/infra/entities/user.entity.ts +++ b/server/src/infra/entities/user.entity.ts @@ -1,3 +1,5 @@ +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { TagEntity } from 'src/infra/entities/tag.entity'; import { Column, CreateDateColumn, @@ -7,8 +9,6 @@ import { PrimaryGeneratedColumn, UpdateDateColumn, } from 'typeorm'; -import { AssetEntity } from './asset.entity'; -import { TagEntity } from './tag.entity'; export enum UserAvatarColor { PRIMARY = 'primary', diff --git a/server/src/infra/index.ts b/server/src/infra/index.ts deleted file mode 100644 index 6a218d81c..000000000 --- a/server/src/infra/index.ts +++ /dev/null @@ -1,4 +0,0 @@ -export * from './database.config'; -export * from './infra.config'; -export * from './infra.module'; -export * from './websocket.adapter'; diff --git a/server/src/infra/infra.config.ts b/server/src/infra/infra.config.ts index 9ea570953..f521b96b7 100644 --- a/server/src/infra/infra.config.ts +++ b/server/src/infra/infra.config.ts @@ -1,7 +1,7 @@ -import { QueueName } from '@app/domain'; import { RegisterQueueOptions } from '@nestjs/bullmq'; import { QueueOptions } from 'bullmq'; import { RedisOptions } from 'ioredis'; +import { QueueName } from 'src/domain/job/job.constants'; function parseRedisConfig(): RedisOptions { const redisUrl = process.env.REDIS_URL; diff --git a/server/src/infra/infra.module.ts b/server/src/infra/infra.module.ts index df3773deb..7ac208c1f 100644 --- a/server/src/infra/infra.module.ts +++ b/server/src/infra/infra.module.ts @@ -1,33 +1,3 @@ -import { - IAccessRepository, - IActivityRepository, - IAlbumRepository, - IAssetRepository, - IAssetStackRepository, - IAuditRepository, - ICommunicationRepository, - ICryptoRepository, - IDatabaseRepository, - IJobRepository, - IKeyRepository, - ILibraryRepository, - IMachineLearningRepository, - IMediaRepository, - IMetadataRepository, - IMoveRepository, - IPartnerRepository, - IPersonRepository, - ISearchRepository, - IServerInfoRepository, - ISharedLinkRepository, - IStorageRepository, - ISystemConfigRepository, - ISystemMetadataRepository, - ITagRepository, - IUserRepository, - IUserTokenRepository, - immichAppConfig, -} from '@app/domain'; import { BullModule } from '@nestjs/bullmq'; import { Global, Module, Provider } from '@nestjs/common'; import { ConfigModule } from '@nestjs/config'; @@ -35,39 +5,65 @@ import { EventEmitterModule } from '@nestjs/event-emitter'; import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpenTelemetryModule } from 'nestjs-otel'; -import { databaseConfig } from './database.config'; -import { databaseEntities } from './entities'; -import { bullConfig, bullQueues } from './infra.config'; -import { otelConfig } from './instrumentation'; -import { - AccessRepository, - ActivityRepository, - AlbumRepository, - ApiKeyRepository, - AssetRepository, - AssetStackRepository, - AuditRepository, - CommunicationRepository, - CryptoRepository, - DatabaseRepository, - FilesystemProvider, - JobRepository, - LibraryRepository, - MachineLearningRepository, - MediaRepository, - MetadataRepository, - MoveRepository, - PartnerRepository, - PersonRepository, - SearchRepository, - ServerInfoRepository, - SharedLinkRepository, - SystemConfigRepository, - SystemMetadataRepository, - TagRepository, - UserRepository, - UserTokenRepository, -} from './repositories'; +import { immichAppConfig } from 'src/domain/domain.config'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IActivityRepository } from 'src/domain/repositories/activity.repository'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; +import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IAuditRepository } from 'src/domain/repositories/audit.repository'; +import { ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; +import { IMediaRepository } from 'src/domain/repositories/media.repository'; +import { IMetadataRepository } from 'src/domain/repositories/metadata.repository'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { ISearchRepository } from 'src/domain/repositories/search.repository'; +import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; +import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; +import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; +import { ITagRepository } from 'src/domain/repositories/tag.repository'; +import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { databaseConfig } from 'src/infra/database.config'; +import { databaseEntities } from 'src/infra/entities'; +import { bullConfig, bullQueues } from 'src/infra/infra.config'; +import { otelConfig } from 'src/infra/instrumentation'; +import { AccessRepository } from 'src/infra/repositories/access.repository'; +import { ActivityRepository } from 'src/infra/repositories/activity.repository'; +import { AlbumRepository } from 'src/infra/repositories/album.repository'; +import { ApiKeyRepository } from 'src/infra/repositories/api-key.repository'; +import { AssetStackRepository } from 'src/infra/repositories/asset-stack.repository'; +import { AssetRepository } from 'src/infra/repositories/asset.repository'; +import { AuditRepository } from 'src/infra/repositories/audit.repository'; +import { CommunicationRepository } from 'src/infra/repositories/communication.repository'; +import { CryptoRepository } from 'src/infra/repositories/crypto.repository'; +import { DatabaseRepository } from 'src/infra/repositories/database.repository'; +import { FilesystemProvider } from 'src/infra/repositories/filesystem.provider'; +import { JobRepository } from 'src/infra/repositories/job.repository'; +import { LibraryRepository } from 'src/infra/repositories/library.repository'; +import { MachineLearningRepository } from 'src/infra/repositories/machine-learning.repository'; +import { MediaRepository } from 'src/infra/repositories/media.repository'; +import { MetadataRepository } from 'src/infra/repositories/metadata.repository'; +import { MoveRepository } from 'src/infra/repositories/move.repository'; +import { PartnerRepository } from 'src/infra/repositories/partner.repository'; +import { PersonRepository } from 'src/infra/repositories/person.repository'; +import { SearchRepository } from 'src/infra/repositories/search.repository'; +import { ServerInfoRepository } from 'src/infra/repositories/server-info.repository'; +import { SharedLinkRepository } from 'src/infra/repositories/shared-link.repository'; +import { SystemConfigRepository } from 'src/infra/repositories/system-config.repository'; +import { SystemMetadataRepository } from 'src/infra/repositories/system-metadata.repository'; +import { TagRepository } from 'src/infra/repositories/tag.repository'; +import { UserTokenRepository } from 'src/infra/repositories/user-token.repository'; +import { UserRepository } from 'src/infra/repositories/user.repository'; const providers: Provider[] = [ { provide: IActivityRepository, useClass: ActivityRepository }, diff --git a/server/src/infra/infra.utils.ts b/server/src/infra/infra.utils.ts index 247244108..2cc5f629a 100644 --- a/server/src/infra/infra.utils.ts +++ b/server/src/infra/infra.utils.ts @@ -1,5 +1,16 @@ -import { AssetSearchBuilderOptions, Paginated, PaginationOptions } from '@app/domain'; import _ from 'lodash'; +import { + Paginated, + PaginatedBuilderOptions, + PaginationMode, + PaginationOptions, + PaginationResult, + chunks, + setUnion, +} from 'src/domain/domain.util'; +import { AssetSearchBuilderOptions } from 'src/domain/repositories/search.repository'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { DATABASE_PARAMETER_CHUNK_SIZE } from 'src/infra/infra.util'; import { Between, FindManyOptions, @@ -11,9 +22,6 @@ import { Repository, SelectQueryBuilder, } from 'typeorm'; -import { PaginatedBuilderOptions, PaginationMode, PaginationResult, chunks, setUnion } from '../domain/domain.util'; -import { AssetEntity } from './entities'; -import { DATABASE_PARAMETER_CHUNK_SIZE } from './infra.util'; /** * Allows optional values unlike the regular Between and uses MoreThanOrEqual diff --git a/server/src/infra/instrumentation.ts b/server/src/infra/instrumentation.ts index 130eaea3d..2c912660e 100644 --- a/server/src/infra/instrumentation.ts +++ b/server/src/infra/instrumentation.ts @@ -1,4 +1,3 @@ -import { serverVersion } from '@app/domain/domain.constant'; import { Histogram, MetricOptions, ValueType, metrics } from '@opentelemetry/api'; import { AsyncLocalStorageContextManager } from '@opentelemetry/context-async-hooks'; import { PrometheusExporter } from '@opentelemetry/exporter-prometheus'; @@ -14,8 +13,9 @@ import { snakeCase, startCase } from 'lodash'; import { OpenTelemetryModuleOptions } from 'nestjs-otel/lib/interfaces'; import { copyMetadataFromFunctionToFunction } from 'nestjs-otel/lib/opentelemetry.utils'; import { performance } from 'node:perf_hooks'; -import { excludePaths } from './infra.config'; -import { DecorateAll } from './infra.utils'; +import { serverVersion } from 'src/domain/domain.constant'; +import { excludePaths } from 'src/infra/infra.config'; +import { DecorateAll } from 'src/infra/infra.utils'; let metricsEnabled = process.env.IMMICH_METRICS === 'true'; const hostMetrics = diff --git a/server/src/infra/logger.ts b/server/src/infra/logger.ts index 8de149c40..dcc87a875 100644 --- a/server/src/infra/logger.ts +++ b/server/src/infra/logger.ts @@ -1,6 +1,6 @@ import { ConsoleLogger } from '@nestjs/common'; import { isLogLevelEnabled } from '@nestjs/common/services/utils/is-log-level-enabled.util'; -import { LogLevel } from './entities'; +import { LogLevel } from 'src/infra/entities/system-config.entity'; const LOG_LEVELS = [LogLevel.VERBOSE, LogLevel.DEBUG, LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; diff --git a/server/src/infra/migrations/1700713871511-UsePgVectors.ts b/server/src/infra/migrations/1700713871511-UsePgVectors.ts index 008d5eadc..46d5320ce 100644 --- a/server/src/infra/migrations/1700713871511-UsePgVectors.ts +++ b/server/src/infra/migrations/1700713871511-UsePgVectors.ts @@ -1,6 +1,6 @@ -import { getCLIPModelInfo } from '@app/domain/smart-info/smart-info.constant'; +import { getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; +import { vectorExt } from 'src/infra/database.config'; import { MigrationInterface, QueryRunner } from 'typeorm'; -import { vectorExt } from '@app/infra/database.config'; export class UsePgVectors1700713871511 implements MigrationInterface { name = 'UsePgVectors1700713871511'; @@ -14,12 +14,14 @@ export class UsePgVectors1700713871511 implements MigrationInterface { LIMIT 1`); const faceDimSize = faceDimQuery?.[0]?.['dimsize'] ?? 512; - const clipModelNameQuery = await queryRunner.query(`SELECT value FROM system_config WHERE key = 'machineLearning.clip.modelName'`); + const clipModelNameQuery = await queryRunner.query( + `SELECT value FROM system_config WHERE key = 'machineLearning.clip.modelName'`, + ); const clipModelName: string = clipModelNameQuery?.[0]?.['value'] ?? 'ViT-B-32__openai'; const clipDimSize = getCLIPModelInfo(clipModelName.replaceAll('"', '')).dimSize; await queryRunner.query(` - ALTER TABLE asset_faces + ALTER TABLE asset_faces ALTER COLUMN embedding SET NOT NULL, ALTER COLUMN embedding TYPE vector(${faceDimSize})`); @@ -37,7 +39,7 @@ export class UsePgVectors1700713871511 implements MigrationInterface { AND array_position(si."clipEmbedding", NULL) IS NULL`); await queryRunner.query(`ALTER TABLE smart_info DROP COLUMN IF EXISTS "clipEmbedding"`); - } + } public async down(queryRunner: QueryRunner): Promise { await queryRunner.query(`ALTER TABLE asset_faces ALTER COLUMN embedding TYPE real array`); diff --git a/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts b/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts index c3716cc19..505b4dbcb 100644 --- a/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts +++ b/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts @@ -1,6 +1,6 @@ +import { DatabaseExtension } from 'src/domain/repositories/database.repository'; +import { vectorExt } from 'src/infra/database.config'; import { MigrationInterface, QueryRunner } from 'typeorm'; -import { vectorExt } from '../database.config'; -import { DatabaseExtension } from '@app/domain/repositories/database.repository'; export class AddCLIPEmbeddingIndex1700713994428 implements MigrationInterface { name = 'AddCLIPEmbeddingIndex1700713994428'; diff --git a/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts b/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts index 066303530..e79c22045 100644 --- a/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts +++ b/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts @@ -1,6 +1,6 @@ +import { DatabaseExtension } from 'src/domain/repositories/database.repository'; +import { vectorExt } from 'src/infra/database.config'; import { MigrationInterface, QueryRunner } from 'typeorm'; -import { vectorExt } from '../database.config'; -import { DatabaseExtension } from '@app/domain/repositories/database.repository'; export class AddFaceEmbeddingIndex1700714033632 implements MigrationInterface { name = 'AddFaceEmbeddingIndex1700714033632'; diff --git a/server/src/infra/repositories/access.repository.ts b/server/src/infra/repositories/access.repository.ts index ad650bf0e..1f96226a6 100644 --- a/server/src/infra/repositories/access.repository.ts +++ b/server/src/infra/repositories/access.repository.ts @@ -1,20 +1,18 @@ -import { IAccessRepository } from '@app/domain'; import { InjectRepository } from '@nestjs/typeorm'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { LibraryEntity } from 'src/infra/entities/library.entity'; +import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { ChunkedSet } from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Brackets, In, Repository } from 'typeorm'; -import { - ActivityEntity, - AlbumEntity, - AssetEntity, - AssetFaceEntity, - LibraryEntity, - PartnerEntity, - PersonEntity, - SharedLinkEntity, - UserTokenEntity, -} from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { ChunkedSet } from '../infra.utils'; -import { Instrumentation } from '../instrumentation'; type IActivityAccess = IAccessRepository['activity']; type IAlbumAccess = IAccessRepository['album']; diff --git a/server/src/infra/repositories/activity.repository.ts b/server/src/infra/repositories/activity.repository.ts index c546056db..afa52ec3a 100644 --- a/server/src/infra/repositories/activity.repository.ts +++ b/server/src/infra/repositories/activity.repository.ts @@ -1,10 +1,10 @@ -import { IActivityRepository } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { IActivityRepository } from 'src/domain/repositories/activity.repository'; +import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Instrumentation } from 'src/infra/instrumentation'; import { IsNull, Repository } from 'typeorm'; -import { ActivityEntity } from '../entities/activity.entity'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Instrumentation } from '../instrumentation'; export interface ActivitySearch { albumId?: string; diff --git a/server/src/infra/repositories/album.repository.ts b/server/src/infra/repositories/album.repository.ts index 60ef6126c..86b73866f 100644 --- a/server/src/infra/repositories/album.repository.ts +++ b/server/src/infra/repositories/album.repository.ts @@ -1,14 +1,21 @@ -import { AlbumAsset, AlbumAssetCount, AlbumAssets, AlbumInfoOptions, IAlbumRepository } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import _ from 'lodash'; +import { setUnion } from 'src/domain/domain.util'; +import { + AlbumAsset, + AlbumAssetCount, + AlbumAssets, + AlbumInfoOptions, + IAlbumRepository, +} from 'src/domain/repositories/album.repository'; +import { dataSource } from 'src/infra/database.config'; +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Chunked, ChunkedArray } from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm'; -import { setUnion } from '../../domain/domain.util'; -import { dataSource } from '../database.config'; -import { AlbumEntity, AssetEntity } from '../entities'; -import { DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from '../infra.util'; -import { Chunked, ChunkedArray } from '../infra.utils'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/api-key.repository.ts b/server/src/infra/repositories/api-key.repository.ts index 3cafc22eb..bdc9e6d0b 100644 --- a/server/src/infra/repositories/api-key.repository.ts +++ b/server/src/infra/repositories/api-key.repository.ts @@ -1,10 +1,10 @@ -import { IKeyRepository } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; +import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; -import { APIKeyEntity } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/asset-stack.repository.ts b/server/src/infra/repositories/asset-stack.repository.ts index d769030bb..556098ff1 100644 --- a/server/src/infra/repositories/asset-stack.repository.ts +++ b/server/src/infra/repositories/asset-stack.repository.ts @@ -1,9 +1,9 @@ -import { IAssetStackRepository } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; +import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; -import { AssetStackEntity } from '../entities'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/asset.repository.ts b/server/src/infra/repositories/asset.repository.ts index 3af6eb150..93f2e42a1 100644 --- a/server/src/infra/repositories/asset.repository.ts +++ b/server/src/infra/repositories/asset.repository.ts @@ -1,9 +1,13 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { DateTime } from 'luxon'; +import path from 'node:path'; +import { Paginated, PaginationMode, PaginationOptions } from 'src/domain/domain.util'; import { AssetBuilderOptions, AssetCreate, AssetExploreFieldOptions, AssetPathEntity, - AssetSearchOptions, AssetStats, AssetStatsOptions, AssetUpdateAllOptions, @@ -14,20 +18,28 @@ import { MapMarkerSearchOptions, MetadataSearchOptions, MonthDay, - Paginated, - PaginationMode, - PaginationOptions, - SearchExploreItem, TimeBucketItem, TimeBucketOptions, TimeBucketSize, WithProperty, WithoutProperty, -} from '@app/domain'; -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; -import { DateTime } from 'luxon'; -import path from 'node:path'; +} from 'src/domain/repositories/asset.repository'; +import { AssetSearchOptions, SearchExploreItem } from 'src/domain/repositories/search.repository'; +import { AssetOrder } from 'src/infra/entities/album.entity'; +import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { + Chunked, + ChunkedArray, + OptionalBetween, + paginate, + paginatedBuilder, + searchAssetBuilder, +} from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Brackets, FindOptionsRelations, @@ -38,10 +50,6 @@ import { Not, Repository, } from 'typeorm'; -import { AssetEntity, AssetJobStatusEntity, AssetOrder, AssetType, ExifEntity, SmartInfoEntity } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Chunked, ChunkedArray, OptionalBetween, paginate, paginatedBuilder, searchAssetBuilder } from '../infra.utils'; -import { Instrumentation } from '../instrumentation'; const truncateMap: Record = { [TimeBucketSize.DAY]: 'day', diff --git a/server/src/infra/repositories/audit.repository.ts b/server/src/infra/repositories/audit.repository.ts index bc00cbe9a..71c89c8d0 100644 --- a/server/src/infra/repositories/audit.repository.ts +++ b/server/src/infra/repositories/audit.repository.ts @@ -1,8 +1,8 @@ -import { AuditSearch, IAuditRepository } from '@app/domain'; import { InjectRepository } from '@nestjs/typeorm'; +import { AuditSearch, IAuditRepository } from 'src/domain/repositories/audit.repository'; +import { AuditEntity } from 'src/infra/entities/audit.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; import { LessThan, MoreThan, Repository } from 'typeorm'; -import { AuditEntity } from '../entities'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() export class AuditRepository implements IAuditRepository { diff --git a/server/src/infra/repositories/communication.repository.ts b/server/src/infra/repositories/communication.repository.ts index 6429b6e19..854c6d1f3 100644 --- a/server/src/infra/repositories/communication.repository.ts +++ b/server/src/infra/repositories/communication.repository.ts @@ -1,13 +1,3 @@ -import { - AuthService, - ClientEvent, - ICommunicationRepository, - InternalEventMap, - OnConnectCallback, - OnServerEventCallback, - ServerEvent, -} from '@app/domain'; -import { ImmichLogger } from '@app/infra/logger'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { OnGatewayConnection, @@ -17,7 +7,17 @@ import { WebSocketServer, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; -import { Instrumentation } from '../instrumentation'; +import { AuthService } from 'src/domain/auth/auth.service'; +import { + ClientEvent, + ICommunicationRepository, + InternalEventMap, + OnConnectCallback, + OnServerEventCallback, + ServerEvent, +} from 'src/domain/repositories/communication.repository'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; @Instrumentation() @WebSocketGateway({ diff --git a/server/src/infra/repositories/crypto.repository.ts b/server/src/infra/repositories/crypto.repository.ts index f98fa9d87..f7bf63f2c 100644 --- a/server/src/infra/repositories/crypto.repository.ts +++ b/server/src/infra/repositories/crypto.repository.ts @@ -1,9 +1,9 @@ -import { ICryptoRepository } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { compareSync, hash } from 'bcrypt'; import { createHash, randomBytes, randomUUID } from 'node:crypto'; import { createReadStream } from 'node:fs'; -import { Instrumentation } from '../instrumentation'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { Instrumentation } from 'src/infra/instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/database.repository.ts b/server/src/infra/repositories/database.repository.ts index 8154e9122..a83bcf80f 100644 --- a/server/src/infra/repositories/database.repository.ts +++ b/server/src/infra/repositories/database.repository.ts @@ -1,3 +1,7 @@ +import { Injectable } from '@nestjs/common'; +import { InjectDataSource } from '@nestjs/typeorm'; +import AsyncLock from 'async-lock'; +import { Version, VersionType } from 'src/domain/domain.constant'; import { DatabaseExtension, DatabaseLock, @@ -5,18 +9,13 @@ import { VectorExtension, VectorIndex, VectorUpdateResult, - Version, - VersionType, extName, -} from '@app/domain'; -import { vectorExt } from '@app/infra/database.config'; -import { Injectable } from '@nestjs/common'; -import { InjectDataSource } from '@nestjs/typeorm'; -import AsyncLock from 'async-lock'; +} from 'src/domain/repositories/database.repository'; +import { vectorExt } from 'src/infra/database.config'; +import { isValidInteger } from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; import { DataSource, EntityManager, QueryRunner } from 'typeorm'; -import { isValidInteger } from '../infra.utils'; -import { Instrumentation } from '../instrumentation'; -import { ImmichLogger } from '../logger'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/filesystem.provider.spec.ts b/server/src/infra/repositories/filesystem.provider.spec.ts index 4c20b2a50..9b12187ed 100644 --- a/server/src/infra/repositories/filesystem.provider.spec.ts +++ b/server/src/infra/repositories/filesystem.provider.spec.ts @@ -1,6 +1,6 @@ -import { CrawlOptionsDto } from '@app/domain'; import mockfs from 'mock-fs'; -import { FilesystemProvider } from './filesystem.provider'; +import { CrawlOptionsDto } from 'src/domain/library/library.dto'; +import { FilesystemProvider } from 'src/infra/repositories/filesystem.provider'; interface Test { test: string; diff --git a/server/src/infra/repositories/filesystem.provider.ts b/server/src/infra/repositories/filesystem.provider.ts index c4f577ed2..c88b0c83a 100644 --- a/server/src/infra/repositories/filesystem.provider.ts +++ b/server/src/infra/repositories/filesystem.provider.ts @@ -1,21 +1,21 @@ -import { - CrawlOptionsDto, - DiskUsage, - IStorageRepository, - ImmichReadStream, - ImmichZipStream, - StorageEventType, - WatchEvents, - mimeTypes, -} from '@app/domain'; -import { ImmichLogger } from '@app/infra/logger'; import archiver from 'archiver'; import chokidar, { WatchOptions } from 'chokidar'; import { glob, globStream } from 'fast-glob'; import { constants, createReadStream, existsSync, mkdirSync } from 'node:fs'; import fs from 'node:fs/promises'; import path from 'node:path'; -import { Instrumentation } from '../instrumentation'; +import { mimeTypes } from 'src/domain/domain.constant'; +import { CrawlOptionsDto } from 'src/domain/library/library.dto'; +import { + DiskUsage, + IStorageRepository, + ImmichReadStream, + ImmichZipStream, + StorageEventType, + WatchEvents, +} from 'src/domain/repositories/storage.repository'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; @Instrumentation() export class FilesystemProvider implements IStorageRepository { diff --git a/server/src/infra/repositories/index.ts b/server/src/infra/repositories/index.ts deleted file mode 100644 index d684f6b00..000000000 --- a/server/src/infra/repositories/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -export * from './access.repository'; -export * from './activity.repository'; -export * from './album.repository'; -export * from './api-key.repository'; -export * from './asset-stack.repository'; -export * from './asset.repository'; -export * from './audit.repository'; -export * from './communication.repository'; -export * from './crypto.repository'; -export * from './database.repository'; -export * from './filesystem.provider'; -export * from './job.repository'; -export * from './library.repository'; -export * from './machine-learning.repository'; -export * from './media.repository'; -export * from './metadata.repository'; -export * from './move.repository'; -export * from './partner.repository'; -export * from './person.repository'; -export * from './search.repository'; -export * from './server-info.repository'; -export * from './shared-link.repository'; -export * from './system-config.repository'; -export * from './system-metadata.repository'; -export * from './tag.repository'; -export * from './user-token.repository'; -export * from './user.repository'; diff --git a/server/src/infra/repositories/job.repository.ts b/server/src/infra/repositories/job.repository.ts index 227967a07..eac535e36 100644 --- a/server/src/infra/repositories/job.repository.ts +++ b/server/src/infra/repositories/job.repository.ts @@ -1,14 +1,3 @@ -import { - IJobRepository, - JobCounts, - JobItem, - JobName, - JOBS_TO_QUEUE, - QueueCleanType, - QueueName, - QueueStatus, -} from '@app/domain'; -import { ImmichLogger } from '@app/infra/logger'; import { getQueueToken } from '@nestjs/bullmq'; import { Injectable } from '@nestjs/common'; import { ModuleRef } from '@nestjs/core'; @@ -16,8 +5,17 @@ import { SchedulerRegistry } from '@nestjs/schedule'; import { Job, JobsOptions, Processor, Queue, Worker, WorkerOptions } from 'bullmq'; import { CronJob, CronTime } from 'cron'; import { setTimeout } from 'node:timers/promises'; -import { bullConfig } from '../infra.config'; -import { Instrumentation } from '../instrumentation'; +import { JOBS_TO_QUEUE, JobName, QueueName } from 'src/domain/job/job.constants'; +import { + IJobRepository, + JobCounts, + JobItem, + QueueCleanType, + QueueStatus, +} from 'src/domain/repositories/job.repository'; +import { bullConfig } from 'src/infra/infra.config'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/library.repository.ts b/server/src/infra/repositories/library.repository.ts index 5ae3de96f..f61d4beb6 100644 --- a/server/src/infra/repositories/library.repository.ts +++ b/server/src/infra/repositories/library.repository.ts @@ -1,11 +1,12 @@ -import { ILibraryRepository, LibraryStatsResponseDto } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { LibraryStatsResponseDto } from 'src/domain/library/library.dto'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Instrumentation } from 'src/infra/instrumentation'; import { IsNull, Not } from 'typeorm'; import { Repository } from 'typeorm/repository/Repository.js'; -import { LibraryEntity, LibraryType } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/machine-learning.repository.ts b/server/src/infra/repositories/machine-learning.repository.ts index 767ca812b..edf067905 100644 --- a/server/src/infra/repositories/machine-learning.repository.ts +++ b/server/src/infra/repositories/machine-learning.repository.ts @@ -1,17 +1,15 @@ +import { Injectable } from '@nestjs/common'; +import { readFile } from 'node:fs/promises'; import { - CLIPConfig, CLIPMode, DetectFaceResult, IMachineLearningRepository, - ModelConfig, ModelType, - RecognitionConfig, TextModelInput, VisionModelInput, -} from '@app/domain'; -import { Injectable } from '@nestjs/common'; -import { readFile } from 'node:fs/promises'; -import { Instrumentation } from '../instrumentation'; +} from 'src/domain/repositories/machine-learning.repository'; +import { CLIPConfig, ModelConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; +import { Instrumentation } from 'src/infra/instrumentation'; const errorPrefix = 'Machine learning request'; diff --git a/server/src/infra/repositories/media.repository.ts b/server/src/infra/repositories/media.repository.ts index 39cec03af..0088e312f 100644 --- a/server/src/infra/repositories/media.repository.ts +++ b/server/src/infra/repositories/media.repository.ts @@ -1,19 +1,19 @@ +import ffmpeg, { FfprobeData } from 'fluent-ffmpeg'; +import fs from 'node:fs/promises'; +import { Writable } from 'node:stream'; +import { promisify } from 'node:util'; +import sharp from 'sharp'; +import { handlePromiseError } from 'src/domain/domain.util'; import { CropOptions, IMediaRepository, ResizeOptions, TranscodeOptions, VideoInfo, - handlePromiseError, -} from '@app/domain'; -import { Colorspace } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; -import ffmpeg, { FfprobeData } from 'fluent-ffmpeg'; -import fs from 'node:fs/promises'; -import { Writable } from 'node:stream'; -import { promisify } from 'node:util'; -import sharp from 'sharp'; -import { Instrumentation } from '../instrumentation'; +} from 'src/domain/repositories/media.repository'; +import { Colorspace } from 'src/infra/entities/system-config.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; const probe = promisify(ffmpeg.ffprobe); sharp.concurrency(0); diff --git a/server/src/infra/repositories/metadata.repository.ts b/server/src/infra/repositories/metadata.repository.ts index bf9bb8a46..e81ba8dcb 100644 --- a/server/src/infra/repositories/metadata.repository.ts +++ b/server/src/infra/repositories/metadata.repository.ts @@ -1,29 +1,33 @@ +import { Inject } from '@nestjs/common'; +import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; +import { DefaultReadTaskOptions, Tags, exiftool } from 'exiftool-vendored'; +import geotz from 'geo-tz'; +import { getName } from 'i18n-iso-countries'; +import { createReadStream, existsSync } from 'node:fs'; +import { readFile } from 'node:fs/promises'; +import readLine from 'node:readline'; import { citiesFile, geodataAdmin1Path, geodataAdmin2Path, geodataCities500Path, geodataDatePath, +} from 'src/domain/domain.constant'; +import { GeoPoint, IMetadataRepository, ImmichTags, - ISystemMetadataRepository, ReverseGeocodeResult, -} from '@app/domain'; -import { ExifEntity, GeodataPlacesEntity, SystemMetadataKey } from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; -import { Inject } from '@nestjs/common'; -import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; -import { DefaultReadTaskOptions, exiftool, Tags } from 'exiftool-vendored'; -import * as geotz from 'geo-tz'; -import { getName } from 'i18n-iso-countries'; -import { createReadStream, existsSync } from 'node:fs'; -import { readFile } from 'node:fs/promises'; -import * as readLine from 'node:readline'; +} from 'src/domain/repositories/metadata.repository'; +import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; +import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; import { DataSource, QueryRunner, Repository } from 'typeorm'; import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() export class MetadataRepository implements IMetadataRepository { diff --git a/server/src/infra/repositories/move.repository.ts b/server/src/infra/repositories/move.repository.ts index 205c67ad6..04807db24 100644 --- a/server/src/infra/repositories/move.repository.ts +++ b/server/src/infra/repositories/move.repository.ts @@ -1,10 +1,10 @@ -import { IMoveRepository, MoveCreate } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { IMoveRepository, MoveCreate } from 'src/domain/repositories/move.repository'; +import { MoveEntity, PathType } from 'src/infra/entities/move.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; -import { MoveEntity, PathType } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/partner.repository.ts b/server/src/infra/repositories/partner.repository.ts index eb07902dc..cd39a8f9d 100644 --- a/server/src/infra/repositories/partner.repository.ts +++ b/server/src/infra/repositories/partner.repository.ts @@ -1,9 +1,9 @@ -import { IPartnerRepository, PartnerIds } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { IPartnerRepository, PartnerIds } from 'src/domain/repositories/partner.repository'; +import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; import { DeepPartial, Repository } from 'typeorm'; -import { PartnerEntity } from '../entities'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/person.repository.ts b/server/src/infra/repositories/person.repository.ts index 562a56fb6..df76ad9d0 100644 --- a/server/src/infra/repositories/person.repository.ts +++ b/server/src/infra/repositories/person.repository.ts @@ -1,21 +1,22 @@ +import { InjectRepository } from '@nestjs/typeorm'; +import _ from 'lodash'; +import { Paginated, PaginationOptions } from 'src/domain/domain.util'; import { AssetFaceId, IPersonRepository, - Paginated, - PaginationOptions, PeopleStatistics, PersonNameSearchOptions, PersonSearchOptions, PersonStatistics, UpdateFacesData, -} from '@app/domain'; -import { InjectRepository } from '@nestjs/typeorm'; -import _ from 'lodash'; +} from 'src/domain/repositories/person.repository'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { ChunkedArray, asVector, paginate } from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; import { FindManyOptions, FindOptionsRelations, FindOptionsSelect, In, Repository } from 'typeorm'; -import { AssetEntity, AssetFaceEntity, PersonEntity } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { ChunkedArray, asVector, paginate } from '../infra.utils'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() export class PersonRepository implements IPersonRepository { diff --git a/server/src/infra/repositories/search.repository.ts b/server/src/infra/repositories/search.repository.ts index 0e29506d1..5676bd8b5 100644 --- a/server/src/infra/repositories/search.repository.ts +++ b/server/src/infra/repositories/search.repository.ts @@ -1,33 +1,28 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; +import { Paginated, PaginationMode, PaginationResult } from 'src/domain/domain.util'; +import { DatabaseExtension } from 'src/domain/repositories/database.repository'; import { AssetSearchOptions, - DatabaseExtension, Embedding, FaceEmbeddingSearch, FaceSearchResult, ISearchRepository, - Paginated, - PaginationMode, - PaginationResult, SearchPaginationOptions, SmartSearchOptions, -} from '@app/domain'; -import { getCLIPModelInfo } from '@app/domain/smart-info/smart-info.constant'; -import { - AssetEntity, - AssetFaceEntity, - AssetType, - GeodataPlacesEntity, - SmartInfoEntity, - SmartSearchEntity, -} from '@app/infra/entities'; -import { ImmichLogger } from '@app/infra/logger'; -import { Injectable } from '@nestjs/common'; -import { InjectRepository } from '@nestjs/typeorm'; +} from 'src/domain/repositories/search.repository'; +import { getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; +import { vectorExt } from 'src/infra/database.config'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; +import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { SmartSearchEntity } from 'src/infra/entities/smart-search.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { asVector, isValidInteger, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; import { Repository, SelectQueryBuilder } from 'typeorm'; -import { vectorExt } from '../database.config'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { asVector, isValidInteger, paginatedBuilder, searchAssetBuilder } from '../infra.utils'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() @@ -335,7 +330,7 @@ WITH RECURSIVE cte AS ( ) UNION ALL - + SELECT l.city, l."assetId" FROM cte c , LATERAL ( diff --git a/server/src/infra/repositories/server-info.repository.ts b/server/src/infra/repositories/server-info.repository.ts index bd56a58dd..50ee3bc8d 100644 --- a/server/src/infra/repositories/server-info.repository.ts +++ b/server/src/infra/repositories/server-info.repository.ts @@ -1,6 +1,6 @@ -import { GitHubRelease, IServerInfoRepository } from '@app/domain'; import { Injectable } from '@nestjs/common'; -import { Instrumentation } from '../instrumentation'; +import { GitHubRelease, IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; +import { Instrumentation } from 'src/infra/instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/shared-link.repository.ts b/server/src/infra/repositories/shared-link.repository.ts index 5e796a772..1b1ed7fe2 100644 --- a/server/src/infra/repositories/shared-link.repository.ts +++ b/server/src/infra/repositories/shared-link.repository.ts @@ -1,10 +1,10 @@ -import { ISharedLinkRepository } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; -import { SharedLinkEntity } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/system-config.repository.ts b/server/src/infra/repositories/system-config.repository.ts index 598333d9f..f354c87e6 100644 --- a/server/src/infra/repositories/system-config.repository.ts +++ b/server/src/infra/repositories/system-config.repository.ts @@ -1,11 +1,11 @@ -import { ISystemConfigRepository } from '@app/domain'; import { InjectRepository } from '@nestjs/typeorm'; import { readFile } from 'node:fs/promises'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SystemConfigEntity } from 'src/infra/entities/system-config.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Chunked } from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; import { In, Repository } from 'typeorm'; -import { SystemConfigEntity } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Chunked } from '../infra.utils'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() export class SystemConfigRepository implements ISystemConfigRepository { diff --git a/server/src/infra/repositories/system-metadata.repository.ts b/server/src/infra/repositories/system-metadata.repository.ts index 5b99cd1dd..b0ace1b91 100644 --- a/server/src/infra/repositories/system-metadata.repository.ts +++ b/server/src/infra/repositories/system-metadata.repository.ts @@ -1,8 +1,8 @@ -import { ISystemMetadataRepository } from '@app/domain/repositories/system-metadata.repository'; import { InjectRepository } from '@nestjs/typeorm'; +import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; +import { SystemMetadata, SystemMetadataEntity } from 'src/infra/entities/system-metadata.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; -import { SystemMetadata, SystemMetadataEntity } from '../entities'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() export class SystemMetadataRepository implements ISystemMetadataRepository { diff --git a/server/src/infra/repositories/tag.repository.ts b/server/src/infra/repositories/tag.repository.ts index 3ac5afd0e..3de70aa10 100644 --- a/server/src/infra/repositories/tag.repository.ts +++ b/server/src/infra/repositories/tag.repository.ts @@ -1,9 +1,10 @@ -import { ITagRepository } from '@app/domain'; -import { AssetEntity, TagEntity } from '@app/infra/entities'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { ITagRepository } from 'src/domain/repositories/tag.repository'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { TagEntity } from 'src/infra/entities/tag.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/user-token.repository.ts b/server/src/infra/repositories/user-token.repository.ts index 60eccb2e5..f2b79a05f 100644 --- a/server/src/infra/repositories/user-token.repository.ts +++ b/server/src/infra/repositories/user-token.repository.ts @@ -1,10 +1,10 @@ -import { IUserTokenRepository } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; +import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; -import { UserTokenEntity } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/user.repository.ts b/server/src/infra/repositories/user.repository.ts index 865a9c8cb..e71d62936 100644 --- a/server/src/infra/repositories/user.repository.ts +++ b/server/src/infra/repositories/user.repository.ts @@ -1,10 +1,16 @@ -import { IUserRepository, UserFindOptions, UserListFilter, UserStatsQueryResponse } from '@app/domain'; import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { + IUserRepository, + UserFindOptions, + UserListFilter, + UserStatsQueryResponse, +} from 'src/domain/repositories/user.repository'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; +import { DummyValue, GenerateSql } from 'src/infra/infra.util'; +import { Instrumentation } from 'src/infra/instrumentation'; import { IsNull, Not, Repository } from 'typeorm'; -import { AssetEntity, UserEntity } from '../entities'; -import { DummyValue, GenerateSql } from '../infra.util'; -import { Instrumentation } from '../instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/infra/sql-generator/index.ts b/server/src/infra/sql-generator/index.ts index 0b10c018c..c365587a9 100644 --- a/server/src/infra/sql-generator/index.ts +++ b/server/src/infra/sql-generator/index.ts @@ -1,33 +1,31 @@ #!/usr/bin/env node -import { ISystemConfigRepository } from '@app/domain'; import { INestApplication } from '@nestjs/common'; import { Reflector } from '@nestjs/core'; import { Test } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; import { mkdir, rm, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; -import { databaseConfig } from '../database.config'; -import { databaseEntities } from '../entities'; -import { GENERATE_SQL_KEY, GenerateSqlQueries } from '../infra.util'; -import { - AccessRepository, - AlbumRepository, - ApiKeyRepository, - AssetRepository, - AuditRepository, - LibraryRepository, - MoveRepository, - PartnerRepository, - PersonRepository, - SearchRepository, - SharedLinkRepository, - SystemConfigRepository, - SystemMetadataRepository, - TagRepository, - UserRepository, - UserTokenRepository, -} from '../repositories'; -import { SqlLogger } from './sql.logger'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { databaseConfig } from 'src/infra/database.config'; +import { databaseEntities } from 'src/infra/entities'; +import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/infra/infra.util'; +import { AccessRepository } from 'src/infra/repositories/access.repository'; +import { AlbumRepository } from 'src/infra/repositories/album.repository'; +import { ApiKeyRepository } from 'src/infra/repositories/api-key.repository'; +import { AssetRepository } from 'src/infra/repositories/asset.repository'; +import { AuditRepository } from 'src/infra/repositories/audit.repository'; +import { LibraryRepository } from 'src/infra/repositories/library.repository'; +import { MoveRepository } from 'src/infra/repositories/move.repository'; +import { PartnerRepository } from 'src/infra/repositories/partner.repository'; +import { PersonRepository } from 'src/infra/repositories/person.repository'; +import { SearchRepository } from 'src/infra/repositories/search.repository'; +import { SharedLinkRepository } from 'src/infra/repositories/shared-link.repository'; +import { SystemConfigRepository } from 'src/infra/repositories/system-config.repository'; +import { SystemMetadataRepository } from 'src/infra/repositories/system-metadata.repository'; +import { TagRepository } from 'src/infra/repositories/tag.repository'; +import { UserTokenRepository } from 'src/infra/repositories/user-token.repository'; +import { UserRepository } from 'src/infra/repositories/user.repository'; +import { SqlLogger } from 'src/infra/sql-generator/sql.logger'; const reflector = new Reflector(); const repositories = [ diff --git a/server/src/infra/subscribers/audit.subscriber.ts b/server/src/infra/subscribers/audit.subscriber.ts index 896f9ae5e..ddfc5d0d7 100644 --- a/server/src/infra/subscribers/audit.subscriber.ts +++ b/server/src/infra/subscribers/audit.subscriber.ts @@ -1,5 +1,7 @@ +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AuditEntity, DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; import { EntitySubscriberInterface, EventSubscriber, RemoveEvent } from 'typeorm'; -import { AlbumEntity, AssetEntity, AuditEntity, DatabaseAction, EntityType } from '../entities'; @EventSubscriber() export class AuditSubscriber implements EntitySubscriberInterface { diff --git a/server/src/main.ts b/server/src/main.ts index 198b0f087..d59875133 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,6 +1,6 @@ -import { bootstrap as admin } from './immich-admin/main'; -import { bootstrap as server } from './immich/main'; -import { bootstrap as microservices } from './microservices/main'; +import { bootstrap as admin } from 'src/immich-admin/main'; +import { bootstrap as server } from 'src/immich/main'; +import { bootstrap as microservices } from 'src/microservices/main'; const immichApp = process.argv[2] || process.env.IMMICH_APP; diff --git a/server/src/microservices/app.service.ts b/server/src/microservices/app.service.ts index 9fabd5855..043ee9f03 100644 --- a/server/src/microservices/app.service.ts +++ b/server/src/microservices/app.service.ts @@ -1,22 +1,20 @@ -import { - AssetService, - AuditService, - DatabaseService, - IDeleteFilesJob, - JobName, - JobService, - LibraryService, - MediaService, - MetadataService, - PersonService, - SmartInfoService, - StorageService, - StorageTemplateService, - SystemConfigService, - UserService, -} from '@app/domain'; -import { otelSDK } from '@app/infra/instrumentation'; import { Injectable } from '@nestjs/common'; +import { AssetService } from 'src/domain/asset/asset.service'; +import { AuditService } from 'src/domain/audit/audit.service'; +import { DatabaseService } from 'src/domain/database/database.service'; +import { JobName } from 'src/domain/job/job.constants'; +import { IDeleteFilesJob } from 'src/domain/job/job.interface'; +import { JobService } from 'src/domain/job/job.service'; +import { LibraryService } from 'src/domain/library/library.service'; +import { MediaService } from 'src/domain/media/media.service'; +import { MetadataService } from 'src/domain/metadata/metadata.service'; +import { PersonService } from 'src/domain/person/person.service'; +import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; +import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; +import { StorageService } from 'src/domain/storage/storage.service'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { UserService } from 'src/domain/user/user.service'; +import { otelSDK } from 'src/infra/instrumentation'; @Injectable() export class AppService { diff --git a/server/src/microservices/main.ts b/server/src/microservices/main.ts index f7dc64f57..01949dd02 100644 --- a/server/src/microservices/main.ts +++ b/server/src/microservices/main.ts @@ -1,9 +1,9 @@ -import { envName, serverVersion } from '@app/domain'; -import { WebSocketAdapter } from '@app/infra'; -import { otelSDK } from '@app/infra/instrumentation'; -import { ImmichLogger } from '@app/infra/logger'; import { NestFactory } from '@nestjs/core'; -import { MicroservicesModule } from './microservices.module'; +import { envName, serverVersion } from 'src/domain/domain.constant'; +import { otelSDK } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; +import { WebSocketAdapter } from 'src/infra/websocket.adapter'; +import { MicroservicesModule } from 'src/microservices/microservices.module'; const logger = new ImmichLogger('ImmichMicroservice'); const port = Number(process.env.MICROSERVICES_PORT) || 3002; diff --git a/server/src/microservices/microservices.module.ts b/server/src/microservices/microservices.module.ts index 4768d965f..6fc9f0890 100644 --- a/server/src/microservices/microservices.module.ts +++ b/server/src/microservices/microservices.module.ts @@ -1,7 +1,7 @@ -import { DomainModule } from '@app/domain'; -import { InfraModule } from '@app/infra'; import { Module, OnModuleInit } from '@nestjs/common'; -import { AppService } from './app.service'; +import { DomainModule } from 'src/domain/domain.module'; +import { InfraModule } from 'src/infra/infra.module'; +import { AppService } from 'src/microservices/app.service'; @Module({ imports: [InfraModule, DomainModule], diff --git a/server/src/microservices/utils/exif/coordinates.spec.ts b/server/src/microservices/utils/exif/coordinates.spec.ts index b9644fb49..083ea31bc 100644 --- a/server/src/microservices/utils/exif/coordinates.spec.ts +++ b/server/src/microservices/utils/exif/coordinates.spec.ts @@ -1,4 +1,4 @@ -import { parseLatitude, parseLongitude } from './coordinates'; +import { parseLatitude, parseLongitude } from 'src/microservices/utils/exif/coordinates'; describe('parsing latitude from string input', () => { it('returns null for invalid inputs', () => { diff --git a/server/src/microservices/utils/exif/coordinates.ts b/server/src/microservices/utils/exif/coordinates.ts index 03aeb17f0..7e0d81679 100644 --- a/server/src/microservices/utils/exif/coordinates.ts +++ b/server/src/microservices/utils/exif/coordinates.ts @@ -1,4 +1,4 @@ -import { isNumberInRange } from '../numbers'; +import { isNumberInRange } from 'src/microservices/utils/numbers'; export function parseLatitude(input: string | number | null): number | null { if (input === null) { diff --git a/server/src/microservices/utils/numbers.spec.ts b/server/src/microservices/utils/numbers.spec.ts index 47f95b8aa..633b8b1d4 100644 --- a/server/src/microservices/utils/numbers.spec.ts +++ b/server/src/microservices/utils/numbers.spec.ts @@ -1,4 +1,4 @@ -import { isDecimalNumber, isNumberInRange, toNumberOrNull } from './numbers'; +import { isDecimalNumber, isNumberInRange, toNumberOrNull } from 'src/microservices/utils/numbers'; describe('checks if a number is a decimal number', () => { it('returns false for non-decimal numbers', () => { diff --git a/server/src/test-utils/utils.ts b/server/src/test-utils/utils.ts index cf9822295..5b4f17baf 100644 --- a/server/src/test-utils/utils.ts +++ b/server/src/test-utils/utils.ts @@ -1,18 +1,22 @@ -import { IJobRepository, IMediaRepository, JobItem, JobItemHandler, QueueName, StorageEventType } from '@app/domain'; -import { AppModule } from '@app/immich'; -import { InfraModule, InfraTestModule, dataSource } from '@app/infra'; -import { MediaRepository } from '@app/infra/repositories'; import { INestApplication } from '@nestjs/common'; import { Test } from '@nestjs/testing'; import { DateTime } from 'luxon'; -import * as fs from 'node:fs'; +import fs from 'node:fs'; import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { EventEmitter } from 'node:stream'; import { Server } from 'node:tls'; +import { QueueName } from 'src/domain/job/job.constants'; +import { IJobRepository, JobItem, JobItemHandler } from 'src/domain/repositories/job.repository'; +import { IMediaRepository } from 'src/domain/repositories/media.repository'; +import { StorageEventType } from 'src/domain/repositories/storage.repository'; +import { AppModule } from 'src/immich/app.module'; +import { AppService } from 'src/immich/app.service'; +import { dataSource } from 'src/infra/database.config'; +import { InfraModule, InfraTestModule } from 'src/infra/infra.module'; +import { MediaRepository } from 'src/infra/repositories/media.repository'; +import { AppService as MicroAppService } from 'src/microservices/app.service'; import { EntityTarget, ObjectLiteral } from 'typeorm'; -import { AppService } from '../immich/app.service'; -import { AppService as MicroAppService } from '../microservices/app.service'; export const IMMICH_TEST_ASSET_PATH = process.env.IMMICH_TEST_ASSET_PATH as string; export const IMMICH_TEST_ASSET_TEMP_PATH = join(tmpdir(), 'immich'); diff --git a/server/test/fixtures/activity.stub.ts b/server/test/fixtures/activity.stub.ts index 7a3aae5ff..ae33699a0 100644 --- a/server/test/fixtures/activity.stub.ts +++ b/server/test/fixtures/activity.stub.ts @@ -1,8 +1,8 @@ -import { ActivityEntity } from '@app/infra/entities'; -import { albumStub } from './album.stub'; -import { assetStub } from './asset.stub'; -import { authStub } from './auth.stub'; -import { userStub } from './user.stub'; +import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { albumStub } from 'test/fixtures/album.stub'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { userStub } from 'test/fixtures/user.stub'; export const activityStub = { oneComment: Object.freeze({ diff --git a/server/test/fixtures/album.stub.ts b/server/test/fixtures/album.stub.ts index bfb6acb6d..18be7d4ff 100644 --- a/server/test/fixtures/album.stub.ts +++ b/server/test/fixtures/album.stub.ts @@ -1,7 +1,7 @@ -import { AlbumEntity, AssetOrder } from '@app/infra/entities'; -import { assetStub } from './asset.stub'; -import { authStub } from './auth.stub'; -import { userStub } from './user.stub'; +import { AlbumEntity, AssetOrder } from 'src/infra/entities/album.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { userStub } from 'test/fixtures/user.stub'; export const albumStub = { empty: Object.freeze({ diff --git a/server/test/fixtures/api-key.stub.ts b/server/test/fixtures/api-key.stub.ts index de1b8dc17..bc6f85c65 100644 --- a/server/test/fixtures/api-key.stub.ts +++ b/server/test/fixtures/api-key.stub.ts @@ -1,6 +1,6 @@ -import { APIKeyEntity } from '@app/infra/entities'; -import { authStub } from './auth.stub'; -import { userStub } from './user.stub'; +import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { authStub } from 'test/fixtures/auth.stub'; +import { userStub } from 'test/fixtures/user.stub'; export const keyStub = { admin: Object.freeze({ diff --git a/server/test/fixtures/asset.stub.ts b/server/test/fixtures/asset.stub.ts index d72a295d4..d2daeaaff 100644 --- a/server/test/fixtures/asset.stub.ts +++ b/server/test/fixtures/asset.stub.ts @@ -1,8 +1,10 @@ -import { AssetEntity, AssetStackEntity, AssetType, ExifEntity } from '@app/infra/entities'; -import { authStub } from './auth.stub'; -import { fileStub } from './file.stub'; -import { libraryStub } from './library.stub'; -import { userStub } from './user.stub'; +import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { authStub } from 'test/fixtures/auth.stub'; +import { fileStub } from 'test/fixtures/file.stub'; +import { libraryStub } from 'test/fixtures/library.stub'; +import { userStub } from 'test/fixtures/user.stub'; export const assetStackStub = (stackId: string, assets: AssetEntity[]): AssetStackEntity => { return { diff --git a/server/test/fixtures/audit.stub.ts b/server/test/fixtures/audit.stub.ts index ab1ca98b9..2c7ef6782 100644 --- a/server/test/fixtures/audit.stub.ts +++ b/server/test/fixtures/audit.stub.ts @@ -1,5 +1,5 @@ -import { AuditEntity, DatabaseAction, EntityType } from '@app/infra/entities'; -import { authStub } from './auth.stub'; +import { AuditEntity, DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; +import { authStub } from 'test/fixtures/auth.stub'; export const auditStub = { create: Object.freeze({ diff --git a/server/test/fixtures/auth.stub.ts b/server/test/fixtures/auth.stub.ts index 79993a4da..f05285fd6 100644 --- a/server/test/fixtures/auth.stub.ts +++ b/server/test/fixtures/auth.stub.ts @@ -1,5 +1,7 @@ -import { AuthDto } from '@app/domain'; -import { SharedLinkEntity, UserEntity, UserTokenEntity } from '../../src/infra/entities'; +import { AuthDto } from 'src/domain/auth/auth.dto'; +import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; export const adminSignupStub = { name: 'Immich Admin', diff --git a/server/test/fixtures/face.stub.ts b/server/test/fixtures/face.stub.ts index 0b988d59a..58a017927 100644 --- a/server/test/fixtures/face.stub.ts +++ b/server/test/fixtures/face.stub.ts @@ -1,6 +1,6 @@ -import { AssetFaceEntity } from '@app/infra/entities'; -import { assetStub } from './asset.stub'; -import { personStub } from './person.stub'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { personStub } from 'test/fixtures/person.stub'; type NonNullableProperty = { [P in keyof T]: NonNullable }; diff --git a/server/test/fixtures/index.ts b/server/test/fixtures/index.ts deleted file mode 100644 index 2217c9b1f..000000000 --- a/server/test/fixtures/index.ts +++ /dev/null @@ -1,18 +0,0 @@ -export * from './album.stub'; -export * from './api-key.stub'; -export * from './asset.stub'; -export * from './audit.stub'; -export * from './auth.stub'; -export * from './error.stub'; -export * from './face.stub'; -export * from './file.stub'; -export * from './library.stub'; -export * from './media.stub'; -export * from './partner.stub'; -export * from './person.stub'; -export * from './shared-link.stub'; -export * from './system-config.stub'; -export * from './tag.stub'; -export * from './user-token.stub'; -export * from './user.stub'; -export * from './uuid.stub'; diff --git a/server/test/fixtures/library.stub.ts b/server/test/fixtures/library.stub.ts index db7687f28..d112d0fb4 100644 --- a/server/test/fixtures/library.stub.ts +++ b/server/test/fixtures/library.stub.ts @@ -1,7 +1,8 @@ -import { APP_MEDIA_LOCATION, THUMBNAIL_DIR } from '@app/domain'; -import { LibraryEntity, LibraryType } from '@app/infra/entities'; import { join } from 'node:path'; -import { userStub } from './user.stub'; +import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; +import { THUMBNAIL_DIR } from 'src/domain/storage/storage.core'; +import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { userStub } from 'test/fixtures/user.stub'; export const libraryStub = { uploadLibrary1: Object.freeze({ diff --git a/server/test/fixtures/media.stub.ts b/server/test/fixtures/media.stub.ts index ad9a4baf7..b4c74b34d 100644 --- a/server/test/fixtures/media.stub.ts +++ b/server/test/fixtures/media.stub.ts @@ -1,4 +1,4 @@ -import { AudioStreamInfo, VideoFormat, VideoInfo, VideoStreamInfo } from '@app/domain'; +import { AudioStreamInfo, VideoFormat, VideoInfo, VideoStreamInfo } from 'src/domain/repositories/media.repository'; const probeStubDefaultFormat: VideoFormat = { formatName: 'mov,mp4,m4a,3gp,3g2,mj2', diff --git a/server/test/fixtures/partner.stub.ts b/server/test/fixtures/partner.stub.ts index 05c1c67d6..1277e2e21 100644 --- a/server/test/fixtures/partner.stub.ts +++ b/server/test/fixtures/partner.stub.ts @@ -1,5 +1,5 @@ -import { PartnerEntity } from '@app/infra/entities'; -import { userStub } from './user.stub'; +import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { userStub } from 'test/fixtures/user.stub'; export const partnerStub = { adminToUser1: Object.freeze({ diff --git a/server/test/fixtures/person.stub.ts b/server/test/fixtures/person.stub.ts index ad83d6800..a573d72e3 100644 --- a/server/test/fixtures/person.stub.ts +++ b/server/test/fixtures/person.stub.ts @@ -1,5 +1,5 @@ -import { PersonEntity } from '@app/infra/entities'; -import { userStub } from './user.stub'; +import { PersonEntity } from 'src/infra/entities/person.entity'; +import { userStub } from 'test/fixtures/user.stub'; export const personStub = { noName: Object.freeze({ diff --git a/server/test/fixtures/shared-link.stub.ts b/server/test/fixtures/shared-link.stub.ts index 109f05190..d3b3d5151 100644 --- a/server/test/fixtures/shared-link.stub.ts +++ b/server/test/fixtures/shared-link.stub.ts @@ -1,9 +1,16 @@ -import { AlbumResponseDto, AssetResponseDto, ExifResponseDto, mapUser, SharedLinkResponseDto } from '@app/domain'; -import { AssetOrder, AssetType, SharedLinkEntity, SharedLinkType, UserEntity } from '@app/infra/entities'; -import { assetStub } from './asset.stub'; -import { authStub } from './auth.stub'; -import { libraryStub } from './library.stub'; -import { userStub } from './user.stub'; +import { AlbumResponseDto } from 'src/domain/album/album-response.dto'; +import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; +import { ExifResponseDto } from 'src/domain/asset/response-dto/exif-response.dto'; +import { SharedLinkResponseDto } from 'src/domain/shared-link/shared-link-response.dto'; +import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { AssetOrder } from 'src/infra/entities/album.entity'; +import { AssetType } from 'src/infra/entities/asset.entity'; +import { SharedLinkEntity, SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; +import { assetStub } from 'test/fixtures/asset.stub'; +import { authStub } from 'test/fixtures/auth.stub'; +import { libraryStub } from 'test/fixtures/library.stub'; +import { userStub } from 'test/fixtures/user.stub'; const today = new Date(); const tomorrow = new Date(); diff --git a/server/test/fixtures/system-config.stub.ts b/server/test/fixtures/system-config.stub.ts index 9f9f02144..2de539848 100644 --- a/server/test/fixtures/system-config.stub.ts +++ b/server/test/fixtures/system-config.stub.ts @@ -1,4 +1,4 @@ -import { SystemConfigEntity, SystemConfigKey } from '@app/infra/entities'; +import { SystemConfigEntity, SystemConfigKey } from 'src/infra/entities/system-config.entity'; export const systemConfigStub: Record = { defaults: [], diff --git a/server/test/fixtures/tag.stub.ts b/server/test/fixtures/tag.stub.ts index cffae0032..a48005528 100644 --- a/server/test/fixtures/tag.stub.ts +++ b/server/test/fixtures/tag.stub.ts @@ -1,6 +1,6 @@ -import { TagResponseDto } from '@app/domain'; -import { TagEntity, TagType } from '@app/infra/entities'; -import { userStub } from './user.stub'; +import { TagResponseDto } from 'src/domain/tag/tag-response.dto'; +import { TagEntity, TagType } from 'src/infra/entities/tag.entity'; +import { userStub } from 'test/fixtures/user.stub'; export const tagStub = { tag1: Object.freeze({ diff --git a/server/test/fixtures/user-token.stub.ts b/server/test/fixtures/user-token.stub.ts index 975318e21..de42d1d32 100644 --- a/server/test/fixtures/user-token.stub.ts +++ b/server/test/fixtures/user-token.stub.ts @@ -1,5 +1,5 @@ -import { UserTokenEntity } from '@app/infra/entities'; -import { userStub } from './user.stub'; +import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { userStub } from 'test/fixtures/user.stub'; export const userTokenStub = { userToken: Object.freeze({ diff --git a/server/test/fixtures/user.stub.ts b/server/test/fixtures/user.stub.ts index e0d9113c6..7809583c7 100644 --- a/server/test/fixtures/user.stub.ts +++ b/server/test/fixtures/user.stub.ts @@ -1,5 +1,5 @@ -import { UserAvatarColor, UserEntity } from '@app/infra/entities'; -import { authStub } from './auth.stub'; +import { UserAvatarColor, UserEntity } from 'src/infra/entities/user.entity'; +import { authStub } from 'test/fixtures/auth.stub'; export const userDto = { user1: { diff --git a/server/test/index.ts b/server/test/index.ts deleted file mode 100644 index 784eeeb35..000000000 --- a/server/test/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export * from './fixtures'; -export * from './repositories'; diff --git a/server/test/repositories/access.repository.mock.ts b/server/test/repositories/access.repository.mock.ts index e10dd7d9a..4491d6e70 100644 --- a/server/test/repositories/access.repository.mock.ts +++ b/server/test/repositories/access.repository.mock.ts @@ -1,4 +1,5 @@ -import { AccessCore, IAccessRepository } from '@app/domain'; +import { AccessCore } from 'src/domain/access/access.core'; +import { IAccessRepository } from 'src/domain/repositories/access.repository'; export interface IAccessRepositoryMock { activity: jest.Mocked; diff --git a/server/test/repositories/activity.repository.mock.ts b/server/test/repositories/activity.repository.mock.ts index 349fa4636..166690b5f 100644 --- a/server/test/repositories/activity.repository.mock.ts +++ b/server/test/repositories/activity.repository.mock.ts @@ -1,4 +1,4 @@ -import { IActivityRepository } from '@app/domain'; +import { IActivityRepository } from 'src/domain/repositories/activity.repository'; export const newActivityRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/album.repository.mock.ts b/server/test/repositories/album.repository.mock.ts index 36c3afb29..8259ac456 100644 --- a/server/test/repositories/album.repository.mock.ts +++ b/server/test/repositories/album.repository.mock.ts @@ -1,4 +1,4 @@ -import { IAlbumRepository } from '@app/domain'; +import { IAlbumRepository } from 'src/domain/repositories/album.repository'; export const newAlbumRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/api-key.repository.mock.ts b/server/test/repositories/api-key.repository.mock.ts index 5688978e7..471b4bb94 100644 --- a/server/test/repositories/api-key.repository.mock.ts +++ b/server/test/repositories/api-key.repository.mock.ts @@ -1,4 +1,4 @@ -import { IKeyRepository } from '@app/domain'; +import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; export const newKeyRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/asset-stack.repository.mock.ts b/server/test/repositories/asset-stack.repository.mock.ts index d87f0316f..cb935a17e 100644 --- a/server/test/repositories/asset-stack.repository.mock.ts +++ b/server/test/repositories/asset-stack.repository.mock.ts @@ -1,4 +1,4 @@ -import { IAssetStackRepository } from '@app/domain'; +import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; export const newAssetStackRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/asset.repository.mock.ts b/server/test/repositories/asset.repository.mock.ts index b9451f34f..ab933e785 100644 --- a/server/test/repositories/asset.repository.mock.ts +++ b/server/test/repositories/asset.repository.mock.ts @@ -1,4 +1,4 @@ -import { IAssetRepository } from '@app/domain'; +import { IAssetRepository } from 'src/domain/repositories/asset.repository'; export const newAssetRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/audit.repository.mock.ts b/server/test/repositories/audit.repository.mock.ts index bd1a4b815..87a83787b 100644 --- a/server/test/repositories/audit.repository.mock.ts +++ b/server/test/repositories/audit.repository.mock.ts @@ -1,4 +1,4 @@ -import { IAuditRepository } from '@app/domain'; +import { IAuditRepository } from 'src/domain/repositories/audit.repository'; export const newAuditRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/communication.repository.mock.ts b/server/test/repositories/communication.repository.mock.ts index e98e0a68f..8ba1e370c 100644 --- a/server/test/repositories/communication.repository.mock.ts +++ b/server/test/repositories/communication.repository.mock.ts @@ -1,4 +1,4 @@ -import { ICommunicationRepository } from '@app/domain'; +import { ICommunicationRepository } from 'src/domain/repositories/communication.repository'; export const newCommunicationRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/crypto.repository.mock.ts b/server/test/repositories/crypto.repository.mock.ts index 52f438453..015593a88 100644 --- a/server/test/repositories/crypto.repository.mock.ts +++ b/server/test/repositories/crypto.repository.mock.ts @@ -1,4 +1,4 @@ -import { ICryptoRepository } from '@app/domain'; +import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; export const newCryptoRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/database.repository.mock.ts b/server/test/repositories/database.repository.mock.ts index 19e2df17a..5cf2960d2 100644 --- a/server/test/repositories/database.repository.mock.ts +++ b/server/test/repositories/database.repository.mock.ts @@ -1,4 +1,5 @@ -import { IDatabaseRepository, Version } from '@app/domain'; +import { Version } from 'src/domain/domain.constant'; +import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; export const newDatabaseRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/index.ts b/server/test/repositories/index.ts deleted file mode 100644 index 90fd1326b..000000000 --- a/server/test/repositories/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -export * from './access.repository.mock'; -export * from './album.repository.mock'; -export * from './api-key.repository.mock'; -export * from './asset-stack.repository.mock'; -export * from './asset.repository.mock'; -export * from './audit.repository.mock'; -export * from './communication.repository.mock'; -export * from './crypto.repository.mock'; -export * from './database.repository.mock'; -export * from './job.repository.mock'; -export * from './library.repository.mock'; -export * from './machine-learning.repository.mock'; -export * from './media.repository.mock'; -export * from './metadata.repository.mock'; -export * from './move.repository.mock'; -export * from './partner.repository.mock'; -export * from './person.repository.mock'; -export * from './search.repository.mock'; -export * from './shared-link.repository.mock'; -export * from './storage.repository.mock'; -export * from './system-config.repository.mock'; -export * from './system-info.repository.mock'; -export * from './system-metadata.repository.mock'; -export * from './tag.repository.mock'; -export * from './user-token.repository.mock'; -export * from './user.repository.mock'; diff --git a/server/test/repositories/job.repository.mock.ts b/server/test/repositories/job.repository.mock.ts index 5967c3ce2..216287343 100644 --- a/server/test/repositories/job.repository.mock.ts +++ b/server/test/repositories/job.repository.mock.ts @@ -1,4 +1,4 @@ -import { IJobRepository } from '@app/domain'; +import { IJobRepository } from 'src/domain/repositories/job.repository'; export const newJobRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/library.repository.mock.ts b/server/test/repositories/library.repository.mock.ts index 740f4c483..79d95cbb5 100644 --- a/server/test/repositories/library.repository.mock.ts +++ b/server/test/repositories/library.repository.mock.ts @@ -1,4 +1,4 @@ -import { ILibraryRepository } from '@app/domain'; +import { ILibraryRepository } from 'src/domain/repositories/library.repository'; export const newLibraryRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/machine-learning.repository.mock.ts b/server/test/repositories/machine-learning.repository.mock.ts index 3538b7893..2266dedae 100644 --- a/server/test/repositories/machine-learning.repository.mock.ts +++ b/server/test/repositories/machine-learning.repository.mock.ts @@ -1,4 +1,4 @@ -import { IMachineLearningRepository } from '@app/domain'; +import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; export const newMachineLearningRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/media.repository.mock.ts b/server/test/repositories/media.repository.mock.ts index 74c4a5d7a..8b21aad10 100644 --- a/server/test/repositories/media.repository.mock.ts +++ b/server/test/repositories/media.repository.mock.ts @@ -1,4 +1,4 @@ -import { IMediaRepository } from '@app/domain'; +import { IMediaRepository } from 'src/domain/repositories/media.repository'; export const newMediaRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/metadata.repository.mock.ts b/server/test/repositories/metadata.repository.mock.ts index e47120ac9..ff2bb53fb 100644 --- a/server/test/repositories/metadata.repository.mock.ts +++ b/server/test/repositories/metadata.repository.mock.ts @@ -1,4 +1,4 @@ -import { IMetadataRepository } from '@app/domain'; +import { IMetadataRepository } from 'src/domain/repositories/metadata.repository'; export const newMetadataRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/move.repository.mock.ts b/server/test/repositories/move.repository.mock.ts index e14b0640b..b42dc8610 100644 --- a/server/test/repositories/move.repository.mock.ts +++ b/server/test/repositories/move.repository.mock.ts @@ -1,4 +1,4 @@ -import { IMoveRepository } from '@app/domain'; +import { IMoveRepository } from 'src/domain/repositories/move.repository'; export const newMoveRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/partner.repository.mock.ts b/server/test/repositories/partner.repository.mock.ts index 1e839ae4f..c70147139 100644 --- a/server/test/repositories/partner.repository.mock.ts +++ b/server/test/repositories/partner.repository.mock.ts @@ -1,4 +1,4 @@ -import { IPartnerRepository } from '@app/domain'; +import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; export const newPartnerRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/person.repository.mock.ts b/server/test/repositories/person.repository.mock.ts index 2a1ccdfe5..c370241b7 100644 --- a/server/test/repositories/person.repository.mock.ts +++ b/server/test/repositories/person.repository.mock.ts @@ -1,4 +1,4 @@ -import { IPersonRepository } from '@app/domain'; +import { IPersonRepository } from 'src/domain/repositories/person.repository'; export const newPersonRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/search.repository.mock.ts b/server/test/repositories/search.repository.mock.ts index 7b428f0cc..e86b83350 100644 --- a/server/test/repositories/search.repository.mock.ts +++ b/server/test/repositories/search.repository.mock.ts @@ -1,4 +1,4 @@ -import { ISearchRepository } from '@app/domain'; +import { ISearchRepository } from 'src/domain/repositories/search.repository'; export const newSearchRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/shared-link.repository.mock.ts b/server/test/repositories/shared-link.repository.mock.ts index fb34b0ad7..2cdf0e2b2 100644 --- a/server/test/repositories/shared-link.repository.mock.ts +++ b/server/test/repositories/shared-link.repository.mock.ts @@ -1,4 +1,4 @@ -import { ISharedLinkRepository } from '@app/domain'; +import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; export const newSharedLinkRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/storage.repository.mock.ts b/server/test/repositories/storage.repository.mock.ts index a8ffbf410..a2851e9e1 100644 --- a/server/test/repositories/storage.repository.mock.ts +++ b/server/test/repositories/storage.repository.mock.ts @@ -1,5 +1,6 @@ -import { IStorageRepository, StorageCore, StorageEventType, WatchEvents } from '@app/domain'; import { WatchOptions } from 'chokidar'; +import { IStorageRepository, StorageEventType, WatchEvents } from 'src/domain/repositories/storage.repository'; +import { StorageCore } from 'src/domain/storage/storage.core'; interface MockWatcherOptions { items?: Array<{ event: 'change' | 'add' | 'unlink' | 'error'; value: string }>; diff --git a/server/test/repositories/system-config.repository.mock.ts b/server/test/repositories/system-config.repository.mock.ts index 3be69f267..6fb4520f8 100644 --- a/server/test/repositories/system-config.repository.mock.ts +++ b/server/test/repositories/system-config.repository.mock.ts @@ -1,4 +1,5 @@ -import { ISystemConfigRepository, SystemConfigCore } from '@app/domain'; +import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; export const newSystemConfigRepositoryMock = (reset = true): jest.Mocked => { if (reset) { diff --git a/server/test/repositories/system-info.repository.mock.ts b/server/test/repositories/system-info.repository.mock.ts index 14c52a6b7..a392818ed 100644 --- a/server/test/repositories/system-info.repository.mock.ts +++ b/server/test/repositories/system-info.repository.mock.ts @@ -1,4 +1,4 @@ -import { IServerInfoRepository } from '@app/domain'; +import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; export const newServerInfoRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/system-metadata.repository.mock.ts b/server/test/repositories/system-metadata.repository.mock.ts index fc4207da6..f031740a4 100644 --- a/server/test/repositories/system-metadata.repository.mock.ts +++ b/server/test/repositories/system-metadata.repository.mock.ts @@ -1,4 +1,4 @@ -import { ISystemMetadataRepository } from '@app/domain'; +import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; export const newSystemMetadataRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/tag.repository.mock.ts b/server/test/repositories/tag.repository.mock.ts index cb1e05a09..611e773ef 100644 --- a/server/test/repositories/tag.repository.mock.ts +++ b/server/test/repositories/tag.repository.mock.ts @@ -1,4 +1,4 @@ -import { ITagRepository } from '@app/domain'; +import { ITagRepository } from 'src/domain/repositories/tag.repository'; export const newTagRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/user-token.repository.mock.ts b/server/test/repositories/user-token.repository.mock.ts index 9d1bacf1c..c11cc5ed9 100644 --- a/server/test/repositories/user-token.repository.mock.ts +++ b/server/test/repositories/user-token.repository.mock.ts @@ -1,4 +1,4 @@ -import { IUserTokenRepository } from '@app/domain'; +import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; export const newUserTokenRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/user.repository.mock.ts b/server/test/repositories/user.repository.mock.ts index 402b90ead..e6772d2b1 100644 --- a/server/test/repositories/user.repository.mock.ts +++ b/server/test/repositories/user.repository.mock.ts @@ -1,4 +1,5 @@ -import { IUserRepository, UserCore } from '@app/domain'; +import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { UserCore } from 'src/domain/user/user.core'; export const newUserRepositoryMock = (reset = true): jest.Mocked => { if (reset) { diff --git a/server/tsconfig.json b/server/tsconfig.json index 6d89fe708..ce3edda39 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -17,16 +17,10 @@ "esModuleInterop": true, "preserveWatchOutput": true, "baseUrl": "./", - "paths": { - "@test": ["test"], - "@test/*": ["test/*"], - "@app/immich": ["src/immich"], - "@app/immich/*": ["src/immich/*"], - "@app/infra": ["src/infra"], - "@app/infra/*": ["src/infra/*"], - "@app/domain": ["src/domain"], - "@app/domain/*": ["src/domain/*"], - }, }, - "exclude": ["dist", "node_modules", "upload"], -} + "exclude": [ + "dist", + "node_modules", + "upload" + ], +} \ No newline at end of file From 851fe4a49f2f921405bc1ff9713464a72aee390d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:33:41 -0400 Subject: [PATCH 020/152] chore(deps): update dependency @types/node to v20.11.28 (#8064) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- open-api/typescript-sdk/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/open-api/typescript-sdk/package-lock.json b/open-api/typescript-sdk/package-lock.json index 165fb98e9..30b2d699b 100644 --- a/open-api/typescript-sdk/package-lock.json +++ b/open-api/typescript-sdk/package-lock.json @@ -22,9 +22,9 @@ "integrity": "sha512-V33FjR6V+AkGRWYQW3XPm5BLn2loGl2ujSeja1TzdjjEn2zjGgl3ve0dcFf/jEwPZEOqQZl6YwIgIB/clXVqWw==" }, "node_modules/@types/node": { - "version": "20.11.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", - "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "version": "20.11.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz", + "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 29be53e70d6c0e98d5011e03e0cd50991f26d9c9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:37:22 -0400 Subject: [PATCH 021/152] chore(deps): update prom/prometheus docker digest to 5ccad47 (#8071) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker/docker-compose.prod.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index 77effc15f..984d99667 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -78,7 +78,7 @@ services: container_name: immich_prometheus ports: - 9090:9090 - image: prom/prometheus@sha256:bc1794e85c9e00293351b967efa267ce6af1c824ac875a9d0c7ac84700a8b53e + image: prom/prometheus@sha256:5ccad477d0057e62a7cd1981ffcc43785ac10c5a35522dc207466ff7e7ec845f volumes: - ./prometheus.yml:/etc/prometheus/prometheus.yml - prometheus-data:/prometheus From 2267ca1949c4c4d548cd246794393cd61586e6ad Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:38:28 -0400 Subject: [PATCH 022/152] chore(deps): update node.js to 8765147 (#8058) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- server/Dockerfile | 2 +- web/Dockerfile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index 2c66c0af3..c42153d76 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -24,7 +24,7 @@ RUN npm prune --omit=dev --omit=optional COPY --from=dev /usr/src/app/node_modules/@img ./node_modules/@img # web build -FROM node:iron-alpine3.18@sha256:a02826c7340c37a29179152723190bcc3044f933c925f3c2d78abb20f794de3f as web +FROM node:iron-alpine3.18@sha256:876514790dabd49fae7d9c4dfbba027954bd91d8e7d36da76334466533bc6b0c as web WORKDIR /usr/src/open-api/typescript-sdk COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./ diff --git a/web/Dockerfile b/web/Dockerfile index 27d206e92..422ad9746 100644 --- a/web/Dockerfile +++ b/web/Dockerfile @@ -1,4 +1,4 @@ -FROM node:iron-alpine3.18@sha256:a02826c7340c37a29179152723190bcc3044f933c925f3c2d78abb20f794de3f +FROM node:iron-alpine3.18@sha256:876514790dabd49fae7d9c4dfbba027954bd91d8e7d36da76334466533bc6b0c RUN apk add --no-cache tini USER node From d97b0259fad7c975ccb6072ffa91dd857fc0bc60 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:38:48 -0400 Subject: [PATCH 023/152] chore(deps): update node.js to bf77dc2 (#8063) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- cli/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/Dockerfile b/cli/Dockerfile index cb0383a00..2eab54831 100644 --- a/cli/Dockerfile +++ b/cli/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20-alpine3.19@sha256:c0a3badbd8a0a760de903e00cedbca94588e609299820557e72cba2a53dbaa2c as core +FROM node:20-alpine3.19@sha256:bf77dc26e48ea95fca9d1aceb5acfa69d2e546b765ec2abfb502975f1a2d4def as core WORKDIR /usr/src/open-api/typescript-sdk COPY open-api/typescript-sdk/package*.json open-api/typescript-sdk/tsconfig*.json ./ From 373a03e8191d44a94ac1e2b663c1956979e916b7 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:06:58 -0500 Subject: [PATCH 024/152] chore(deps): update dependency @types/node to v20.11.28 (#8110) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- e2e/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 083964cb6..0de8d431a 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -1158,9 +1158,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.11.27", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.27.tgz", - "integrity": "sha512-qyUZfMnCg1KEz57r7pzFtSGt49f6RPkPBis3Vo4PbS7roQEDn22hiHzl/Lo1q4i4hDEgBJmBF/NTNg2XR0HbFg==", + "version": "20.11.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz", + "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" From 6d9ca82b193695e4d3ba9690f52fbd1841b89683 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:08:01 -0500 Subject: [PATCH 025/152] chore(deps): update web (#8066) * chore(deps): update web * fix: linting --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Jason Rasmussen --- web/.eslintignore | 1 + web/package-lock.json | 215 +++++++++++++++++++++--------------------- 2 files changed, 109 insertions(+), 107 deletions(-) diff --git a/web/.eslintignore b/web/.eslintignore index 38972655f..f944e33c4 100644 --- a/web/.eslintignore +++ b/web/.eslintignore @@ -11,3 +11,4 @@ node_modules pnpm-lock.yaml package-lock.json yarn.lock +svelte.config.js diff --git a/web/package-lock.json b/web/package-lock.json index c1af8d11f..85413cbc9 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -1456,9 +1456,9 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -1814,9 +1814,9 @@ } }, "node_modules/@sveltejs/enhanced-img": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/@sveltejs/enhanced-img/-/enhanced-img-0.1.8.tgz", - "integrity": "sha512-0cLVR9KiO0/t3VVm64OM7bPHTkdaT2aaz1rwoAhao+EBXR3vMvLoYXLHvz8o9/552PSV8G844RkH7qkGc3YAiQ==", + "version": "0.1.9", + "resolved": "https://registry.npmjs.org/@sveltejs/enhanced-img/-/enhanced-img-0.1.9.tgz", + "integrity": "sha512-gUgaiG88P6moWcxZx4YrzMhAlw1TgggKRp7n9gdfCREDeXHysCd1l9GpQR3sh109SM3rNlkiaAzt+iPLT0aG1w==", "dev": true, "dependencies": { "magic-string": "^0.30.5", @@ -1825,9 +1825,9 @@ } }, "node_modules/@sveltejs/kit": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.2.tgz", - "integrity": "sha512-1Pm2lsBYURQsjnLyZa+jw75eVD4gYHxGRwPyFe4DAmB3FjTVR8vRNWGeuDLGFcKMh/B1ij6FTUrc9GrerogCng==", + "version": "2.5.4", + "resolved": "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.5.4.tgz", + "integrity": "sha512-eDxK2d4EGzk99QsZNoPXe7jlzA5EGqfcCpUwZ912bhnalsZ2ZsG5wGRthkydupVjYyqdmzEanVKFhLxU2vkPSQ==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -2264,16 +2264,16 @@ } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", - "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.2.0.tgz", + "integrity": "sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/type-utils": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/type-utils": "7.2.0", + "@typescript-eslint/utils": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -2332,15 +2332,15 @@ "dev": true }, "node_modules/@typescript-eslint/parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", - "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4" }, "engines": { @@ -2360,13 +2360,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz", + "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2377,13 +2377,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", - "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.2.0.tgz", + "integrity": "sha512-xHi51adBHo9O9330J8GQYQwrKBqbIPJGZZVQTHHmy200hvkLZFWJIFtAG/7IYTWUyun6DE6w5InDReePJYJlJA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/utils": "7.2.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -2404,9 +2404,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz", + "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -2417,13 +2417,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz", + "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2502,17 +2502,17 @@ "dev": true }, "node_modules/@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.2.0.tgz", + "integrity": "sha512-YfHpnMAGb1Eekpm3XRK8hcMwGLGsnT6L+7b2XyRv6ouDuJU1tZir1GS2i0+VXRatMwSI1/UfcyPe53ADkU+IuA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", "semver": "^7.5.4" }, "engines": { @@ -2560,12 +2560,12 @@ "dev": true }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz", + "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.2.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -2583,14 +2583,14 @@ "dev": true }, "node_modules/@vitest/browser": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-1.3.1.tgz", - "integrity": "sha512-pRof8G8nqRWwg3ouyIctyhfIVk5jXgF056uF//sqdi37+pVtDz9kBI/RMu0xlc8tgCyJ2aEMfbgJZPUydlEVaQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/browser/-/browser-1.4.0.tgz", + "integrity": "sha512-kC44DzuqPZZrqe2P7SX2a3zHDAt919WtpkUMAxzv9eP5uPfVXtpk2Ipms2NXJGY5190aJc1uY+ambfJ3rwDJRA==", "dev": true, "optional": true, "peer": true, "dependencies": { - "@vitest/utils": "1.3.1", + "@vitest/utils": "1.4.0", "magic-string": "^0.30.5", "sirv": "^2.0.4" }, @@ -2599,7 +2599,7 @@ }, "peerDependencies": { "playwright": "*", - "vitest": "1.3.1", + "vitest": "1.4.0", "webdriverio": "*" }, "peerDependenciesMeta": { @@ -2615,9 +2615,9 @@ } }, "node_modules/@vitest/coverage-v8": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.3.1.tgz", - "integrity": "sha512-UuBnkSJUNE9rdHjDCPyJ4fYuMkoMtnghes1XohYa4At0MS3OQSAo97FrbwSLRshYsXThMZy1+ybD/byK5llyIg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.4.0.tgz", + "integrity": "sha512-4hDGyH1SvKpgZnIByr9LhGgCEuF9DKM34IBLCC/fVfy24Z3+PZ+Ii9hsVBsHvY1umM1aGPEjceRkzxCfcQ10wg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.1", @@ -2625,12 +2625,13 @@ "debug": "^4.3.4", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^4.0.1", + "istanbul-lib-source-maps": "^5.0.4", "istanbul-reports": "^3.1.6", "magic-string": "^0.30.5", "magicast": "^0.3.3", "picocolors": "^1.0.0", "std-env": "^3.5.0", + "strip-literal": "^2.0.0", "test-exclude": "^6.0.0", "v8-to-istanbul": "^9.2.0" }, @@ -2638,17 +2639,17 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "1.3.1" + "vitest": "1.4.0" } }, "node_modules/@vitest/expect": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.1.tgz", - "integrity": "sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.4.0.tgz", + "integrity": "sha512-Jths0sWCJZ8BxjKe+p+eKsoqev1/T8lYcrjavEaz8auEJ4jAVY0GwW3JKmdVU4mmNPLPHixh4GNXP7GFtAiDHA==", "dev": true, "dependencies": { - "@vitest/spy": "1.3.1", - "@vitest/utils": "1.3.1", + "@vitest/spy": "1.4.0", + "@vitest/utils": "1.4.0", "chai": "^4.3.10" }, "funding": { @@ -2656,12 +2657,12 @@ } }, "node_modules/@vitest/runner": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.1.tgz", - "integrity": "sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.4.0.tgz", + "integrity": "sha512-EDYVSmesqlQ4RD2VvWo3hQgTJ7ZrFQ2VSJdfiJiArkCerDAGeyF1i6dHkmySqk573jLp6d/cfqCN+7wUB5tLgg==", "dev": true, "dependencies": { - "@vitest/utils": "1.3.1", + "@vitest/utils": "1.4.0", "p-limit": "^5.0.0", "pathe": "^1.1.1" }, @@ -2697,9 +2698,9 @@ } }, "node_modules/@vitest/snapshot": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.1.tgz", - "integrity": "sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.4.0.tgz", + "integrity": "sha512-saAFnt5pPIA5qDGxOHxJ/XxhMFKkUSBJmVt5VgDsAqPTX6JP326r5C/c9UuCMPoXNzuudTPsYDZCoJ5ilpqG2A==", "dev": true, "dependencies": { "magic-string": "^0.30.5", @@ -2743,9 +2744,9 @@ "dev": true }, "node_modules/@vitest/spy": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz", - "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.4.0.tgz", + "integrity": "sha512-Ywau/Qs1DzM/8Uc+yA77CwSegizMlcgTJuYGAi0jujOteJOUf1ujunHThYo243KG9nAyWT3L9ifPYZ5+As/+6Q==", "dev": true, "dependencies": { "tinyspy": "^2.2.0" @@ -2755,9 +2756,9 @@ } }, "node_modules/@vitest/utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.1.tgz", - "integrity": "sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-mx3Yd1/6e2Vt/PUC98DcqTirtfxUyAZ32uK82r8rZzbtBeBo+nqgnjx/LvqQdWsrvNtm14VmurNgcf4nqY5gJg==", "dev": true, "dependencies": { "diff-sequences": "^29.6.3", @@ -5649,14 +5650,14 @@ } }, "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", + "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "istanbul-lib-coverage": "^3.0.0" }, "engines": { "node": ">=10" @@ -7671,9 +7672,9 @@ } }, "node_modules/socket.io-client": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz", - "integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", + "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", "dependencies": { "@socket.io/component-emitter": "~3.1.0", "debug": "~4.3.2", @@ -8038,9 +8039,9 @@ } }, "node_modules/svelte-check": { - "version": "3.6.6", - "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.6.6.tgz", - "integrity": "sha512-b9q9rOHOMYF3U8XllK7LmXTq1LeWQ98waGfEJzrFutViadkNl1tgdEtxIQ8yuPx+VQ4l7YrknYol+0lfZocaZw==", + "version": "3.6.7", + "resolved": "https://registry.npmjs.org/svelte-check/-/svelte-check-3.6.7.tgz", + "integrity": "sha512-tKEjemK9FYCySAseCaIt+ps5o0XRvLC7ECjyJXXtO7vOQhR9E6JavgoUbGP1PCulD2OTcB/fi9RjV3nyF1AROw==", "dev": true, "dependencies": { "@jridgewell/trace-mapping": "^0.3.17", @@ -8670,9 +8671,9 @@ } }, "node_modules/vite": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.5.tgz", - "integrity": "sha512-BdN1xh0Of/oQafhU+FvopafUp6WaYenLU/NFoL5WyJL++GxkNfieKzBhM24H3HVsPQrlAqB7iJYTHabzaRed5Q==", + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.6.tgz", + "integrity": "sha512-yYIAZs9nVfRJ/AiOLCA91zzhjsHUgMjB+EigzFb6W2XTLO8JixBCKCjvhKZaye+NKYHCrkv3Oh50dH9EdLU2RA==", "dev": true, "dependencies": { "esbuild": "^0.19.3", @@ -8738,9 +8739,9 @@ } }, "node_modules/vite-node": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz", - "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.4.0.tgz", + "integrity": "sha512-VZDAseqjrHgNd4Kh8icYHWzTKSCZMhia7GyHfhtzLW33fZlG9SwsB6CEhgyVOWkJfJ2pFLrp/Gj1FSfAiqH9Lw==", "dev": true, "dependencies": { "cac": "^6.7.14", @@ -8774,16 +8775,16 @@ } }, "node_modules/vitest": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.1.tgz", - "integrity": "sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.4.0.tgz", + "integrity": "sha512-gujzn0g7fmwf83/WzrDTnncZt2UiXP41mHuFYFrdwaLRVQ6JYQEiME2IfEjU3vcFL3VKa75XhI3lFgn+hfVsQw==", "dev": true, "dependencies": { - "@vitest/expect": "1.3.1", - "@vitest/runner": "1.3.1", - "@vitest/snapshot": "1.3.1", - "@vitest/spy": "1.3.1", - "@vitest/utils": "1.3.1", + "@vitest/expect": "1.4.0", + "@vitest/runner": "1.4.0", + "@vitest/snapshot": "1.4.0", + "@vitest/spy": "1.4.0", + "@vitest/utils": "1.4.0", "acorn-walk": "^8.3.2", "chai": "^4.3.10", "debug": "^4.3.4", @@ -8797,7 +8798,7 @@ "tinybench": "^2.5.1", "tinypool": "^0.8.2", "vite": "^5.0.0", - "vite-node": "1.3.1", + "vite-node": "1.4.0", "why-is-node-running": "^2.2.2" }, "bin": { @@ -8812,8 +8813,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.3.1", - "@vitest/ui": "1.3.1", + "@vitest/browser": "1.4.0", + "@vitest/ui": "1.4.0", "happy-dom": "*", "jsdom": "*" }, From dab4595a4efb958425adc85bc0092a5582cd091b Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 14:09:10 -0500 Subject: [PATCH 026/152] chore(deps): update redis:6.2-alpine docker digest to fd35357 (#8001) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- docker/docker-compose.dev.yml | 2 +- docker/docker-compose.prod.yml | 2 +- e2e/docker-compose.yml | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docker/docker-compose.dev.yml b/docker/docker-compose.dev.yml index 2541a1a20..ac56a2e06 100644 --- a/docker/docker-compose.dev.yml +++ b/docker/docker-compose.dev.yml @@ -99,7 +99,7 @@ services: redis: container_name: immich_redis - image: redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5 + image: redis:6.2-alpine@sha256:fd3535746075ba01b73c3602c0704bc944dd064c0a4ac46341a4a351bec69db8 database: container_name: immich_postgres diff --git a/docker/docker-compose.prod.yml b/docker/docker-compose.prod.yml index 984d99667..b797e9e8e 100644 --- a/docker/docker-compose.prod.yml +++ b/docker/docker-compose.prod.yml @@ -56,7 +56,7 @@ services: redis: container_name: immich_redis - image: redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5 + image: redis:6.2-alpine@sha256:fd3535746075ba01b73c3602c0704bc944dd064c0a4ac46341a4a351bec69db8 restart: always database: diff --git a/e2e/docker-compose.yml b/e2e/docker-compose.yml index 7cda6a12c..2c22fa72a 100644 --- a/e2e/docker-compose.yml +++ b/e2e/docker-compose.yml @@ -36,7 +36,7 @@ services: <<: *server-common redis: - image: redis:6.2-alpine@sha256:51d6c56749a4243096327e3fb964a48ed92254357108449cb6e23999c37773c5 + image: redis:6.2-alpine@sha256:fd3535746075ba01b73c3602c0704bc944dd064c0a4ac46341a4a351bec69db8 database: image: tensorchord/pgvecto-rs:pg14-v0.2.0@sha256:90724186f0a3517cf6914295b5ab410db9ce23190a2d9d0b9dd6463e3fa298f0 From 3f0d54c752a3c50a6f12365ed7d431c24f7831d3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 15:34:12 -0400 Subject: [PATCH 027/152] fix(deps): update server (#8067) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- server/package-lock.json | 426 +++++++++++++++++++++++---------------- server/package.json | 4 +- 2 files changed, 256 insertions(+), 174 deletions(-) diff --git a/server/package-lock.json b/server/package-lock.json index 8d623c509..1b288ba87 100644 --- a/server/package-lock.json +++ b/server/package-lock.json @@ -22,7 +22,7 @@ "@nestjs/swagger": "^7.1.8", "@nestjs/typeorm": "^10.0.0", "@nestjs/websockets": "^10.2.2", - "@opentelemetry/auto-instrumentations-node": "^0.42.0", + "@opentelemetry/auto-instrumentations-node": "^0.43.0", "@opentelemetry/exporter-prometheus": "^0.49.0", "@opentelemetry/sdk-node": "^0.49.0", "@socket.io/postgres-adapter": "^0.3.1", @@ -82,7 +82,7 @@ "@types/mock-fs": "^4.13.1", "@types/multer": "^1.4.7", "@types/node": "^20.5.7", - "@types/sharp": "^0.31.1", + "@types/sharp": "^0.32.0", "@types/supertest": "^6.0.0", "@types/ua-parser-js": "^0.7.36", "@typescript-eslint/eslint-plugin": "^7.0.0", @@ -1720,9 +1720,12 @@ } }, "node_modules/@immich/cli": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@immich/cli/-/cli-2.0.7.tgz", - "integrity": "sha512-36bpL7SCnbWuaHwuvVmV0iw2dgxX6umk3DhQ5rThJ6C9vOVZs8WY2zMU0voTATlEPoJkpwcQTOMLKFLTPL5OJw==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@immich/cli/-/cli-2.1.0.tgz", + "integrity": "sha512-3s/8+Js1dAwibzgaRtZ+bsAL9nOtvoEX/qMlOTgbgLf/lT96M88QScqhb+YrU2l3WBugtts6xW76XQTrWGXcmw==", + "dependencies": { + "lodash-es": "^4.17.21" + }, "bin": { "immich": "dist/index.js" }, @@ -2910,25 +2913,25 @@ } }, "node_modules/@opentelemetry/auto-instrumentations-node": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.42.0.tgz", - "integrity": "sha512-fxcB7My5QTVfX6kBH4r5OFduGSxdpROgyIu7CqClp1psFHfVaBMQd4lbK2u+39K5kbjzJT2OaUP8yQuAvKJqBg==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.43.0.tgz", + "integrity": "sha512-2WvHUSi/QVeVG8ObPD0Ls6WevfIbQjspxIQRuHaQFWXhmEwy/MsEcoQUjbNKXwO5516aS04GTydKEoRKsMwhdA==", "dependencies": { "@opentelemetry/instrumentation": "^0.49.1", "@opentelemetry/instrumentation-amqplib": "^0.35.0", "@opentelemetry/instrumentation-aws-lambda": "^0.39.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.39.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.39.1", "@opentelemetry/instrumentation-bunyan": "^0.36.0", "@opentelemetry/instrumentation-cassandra-driver": "^0.36.0", "@opentelemetry/instrumentation-connect": "^0.34.0", "@opentelemetry/instrumentation-cucumber": "^0.4.0", "@opentelemetry/instrumentation-dataloader": "^0.7.0", "@opentelemetry/instrumentation-dns": "^0.34.0", - "@opentelemetry/instrumentation-express": "^0.36.0", + "@opentelemetry/instrumentation-express": "^0.36.1", "@opentelemetry/instrumentation-fastify": "^0.34.0", "@opentelemetry/instrumentation-fs": "^0.10.0", "@opentelemetry/instrumentation-generic-pool": "^0.34.0", - "@opentelemetry/instrumentation-graphql": "^0.38.0", + "@opentelemetry/instrumentation-graphql": "^0.38.1", "@opentelemetry/instrumentation-grpc": "^0.49.1", "@opentelemetry/instrumentation-hapi": "^0.35.0", "@opentelemetry/instrumentation-http": "^0.49.1", @@ -2937,13 +2940,13 @@ "@opentelemetry/instrumentation-koa": "^0.38.0", "@opentelemetry/instrumentation-lru-memoizer": "^0.35.0", "@opentelemetry/instrumentation-memcached": "^0.34.0", - "@opentelemetry/instrumentation-mongodb": "^0.40.0", + "@opentelemetry/instrumentation-mongodb": "^0.41.0", "@opentelemetry/instrumentation-mongoose": "^0.36.0", "@opentelemetry/instrumentation-mysql": "^0.36.0", "@opentelemetry/instrumentation-mysql2": "^0.36.0", "@opentelemetry/instrumentation-nestjs-core": "^0.35.0", "@opentelemetry/instrumentation-net": "^0.34.0", - "@opentelemetry/instrumentation-pg": "^0.39.0", + "@opentelemetry/instrumentation-pg": "^0.39.1", "@opentelemetry/instrumentation-pino": "^0.36.0", "@opentelemetry/instrumentation-redis": "^0.37.0", "@opentelemetry/instrumentation-redis-4": "^0.37.0", @@ -3465,9 +3468,9 @@ } }, "node_modules/@opentelemetry/instrumentation-mongodb": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.40.0.tgz", - "integrity": "sha512-ldlJUW/1UlnGtIWBt7fIUl+7+TGOKxIU+0Js5ukpXfQc07ENYFeck5TdbFjvYtF8GppPErnsZJiFiRdYm6Pv/Q==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.41.0.tgz", + "integrity": "sha512-DlSH0oyEuTW5gprCUppb0Qe3pK3cpUUFW5eTmayWNyICI1LFunwtcrULTNv6UiThD/V5ykAf/GGGEa7KFAmkog==", "dependencies": { "@opentelemetry/instrumentation": "^0.49.1", "@opentelemetry/sdk-metrics": "^1.9.1", @@ -4645,9 +4648,9 @@ } }, "node_modules/@types/lodash": { - "version": "4.14.202", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", - "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", "dev": true }, "node_modules/@types/luxon": { @@ -4706,9 +4709,9 @@ } }, "node_modules/@types/node": { - "version": "20.11.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", - "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "version": "20.11.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz", + "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==", "dependencies": { "undici-types": "~5.26.4" } @@ -4839,12 +4842,13 @@ } }, "node_modules/@types/sharp": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.31.1.tgz", - "integrity": "sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==", + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.32.0.tgz", + "integrity": "sha512-OOi3kL+FZDnPhVzsfD37J88FNeZh6gQsGcLc95NbeURRGvmSjeXiDcyWzF2o3yh/gQAUn2uhh/e+CPCa5nwAxw==", + "deprecated": "This is a stub types definition. sharp provides its own type definitions, so you do not need this installed.", "dev": true, "dependencies": { - "@types/node": "*" + "sharp": "*" } }, "node_modules/@types/shimmer": { @@ -4942,16 +4946,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", - "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.2.0.tgz", + "integrity": "sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/type-utils": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/type-utils": "7.2.0", + "@typescript-eslint/utils": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -4977,15 +4981,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", - "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4" }, "engines": { @@ -5005,13 +5009,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz", + "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -5022,13 +5026,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", - "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.2.0.tgz", + "integrity": "sha512-xHi51adBHo9O9330J8GQYQwrKBqbIPJGZZVQTHHmy200hvkLZFWJIFtAG/7IYTWUyun6DE6w5InDReePJYJlJA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/utils": "7.2.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -5049,9 +5053,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz", + "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==", "dev": true, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -5062,13 +5066,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz", + "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -5114,17 +5118,17 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.2.0.tgz", + "integrity": "sha512-YfHpnMAGb1Eekpm3XRK8hcMwGLGsnT6L+7b2XyRv6ouDuJU1tZir1GS2i0+VXRatMwSI1/UfcyPe53ADkU+IuA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", "semver": "^7.5.4" }, "engines": { @@ -5139,12 +5143,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz", + "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.2.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -5531,38 +5535,77 @@ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "node_modules/archiver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.0.tgz", - "integrity": "sha512-R9HM9egs8FfktSqUqyjlKmvF4U+CWNqm/2tlROV+lOFg79MLdT67ae1l3hU47pGy8twSXxHoiefMCh43w0BriQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", "dependencies": { - "archiver-utils": "^5.0.0", + "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", - "zip-stream": "^6.0.0" + "zip-stream": "^6.0.1" }, "engines": { "node": ">= 14" } }, "node_modules/archiver-utils": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.1.tgz", - "integrity": "sha512-MMAoLdMvT/nckofX1tCLrf7uJce4jTNkiT6smA2u57AOImc1nce7mR3EDujxL5yv6/MnILuQH4sAsPtDS8kTvg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", "dependencies": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" + "readable-stream": "^4.0.0" }, "engines": { "node": ">= 14" } }, + "node_modules/archiver-utils/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/archiver/node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -6587,12 +6630,13 @@ "dev": true }, "node_modules/compress-commons": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.1.tgz", - "integrity": "sha512-l7occIJn8YwlCEbWUCrG6gPms9qnJTCZSaznCa5HaV+yJMH4kM8BDc7q9NyoQuoiB2O6jKgTcTeY462qw6MyHw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", "dependencies": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" }, @@ -8370,9 +8414,9 @@ } }, "node_modules/geo-tz": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.0.1.tgz", - "integrity": "sha512-hpFbw3NKFOVy461NrWIt6Z6JQpGnMpYvNpvDunIrixbHsBPOnDcrfao0p+o/7gsMJnkhSYnTJ9DkyV2tXBLI8w==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.0.2.tgz", + "integrity": "sha512-NjEzJBzaMhO9C7lFZIsWDkVED7aLxcES3iEZOWJ97dhnDUGhEB8vhW7MaWR+2y4aWvtFV/VyuDi8Y0rUHvm4tw==", "dependencies": { "@turf/boolean-point-in-polygon": "^6.5.0", "@turf/helpers": "^6.5.0", @@ -10119,6 +10163,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -14487,12 +14536,12 @@ } }, "node_modules/zip-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.0.tgz", - "integrity": "sha512-X0WFquRRDtL9HR9hc1OrabOP/VKJEX7gAr2geayt3b7dLgXgSXI6ucC4CphLQP/aQt2GyHIYgmXxtC+dVdghAQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", "dependencies": { "archiver-utils": "^5.0.0", - "compress-commons": "^6.0.0", + "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" }, "engines": { @@ -15567,9 +15616,12 @@ "optional": true }, "@immich/cli": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@immich/cli/-/cli-2.0.7.tgz", - "integrity": "sha512-36bpL7SCnbWuaHwuvVmV0iw2dgxX6umk3DhQ5rThJ6C9vOVZs8WY2zMU0voTATlEPoJkpwcQTOMLKFLTPL5OJw==" + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@immich/cli/-/cli-2.1.0.tgz", + "integrity": "sha512-3s/8+Js1dAwibzgaRtZ+bsAL9nOtvoEX/qMlOTgbgLf/lT96M88QScqhb+YrU2l3WBugtts6xW76XQTrWGXcmw==", + "requires": { + "lodash-es": "^4.17.21" + } }, "@ioredis/commands": { "version": "1.2.0", @@ -16371,25 +16423,25 @@ } }, "@opentelemetry/auto-instrumentations-node": { - "version": "0.42.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.42.0.tgz", - "integrity": "sha512-fxcB7My5QTVfX6kBH4r5OFduGSxdpROgyIu7CqClp1psFHfVaBMQd4lbK2u+39K5kbjzJT2OaUP8yQuAvKJqBg==", + "version": "0.43.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/auto-instrumentations-node/-/auto-instrumentations-node-0.43.0.tgz", + "integrity": "sha512-2WvHUSi/QVeVG8ObPD0Ls6WevfIbQjspxIQRuHaQFWXhmEwy/MsEcoQUjbNKXwO5516aS04GTydKEoRKsMwhdA==", "requires": { "@opentelemetry/instrumentation": "^0.49.1", "@opentelemetry/instrumentation-amqplib": "^0.35.0", "@opentelemetry/instrumentation-aws-lambda": "^0.39.0", - "@opentelemetry/instrumentation-aws-sdk": "^0.39.0", + "@opentelemetry/instrumentation-aws-sdk": "^0.39.1", "@opentelemetry/instrumentation-bunyan": "^0.36.0", "@opentelemetry/instrumentation-cassandra-driver": "^0.36.0", "@opentelemetry/instrumentation-connect": "^0.34.0", "@opentelemetry/instrumentation-cucumber": "^0.4.0", "@opentelemetry/instrumentation-dataloader": "^0.7.0", "@opentelemetry/instrumentation-dns": "^0.34.0", - "@opentelemetry/instrumentation-express": "^0.36.0", + "@opentelemetry/instrumentation-express": "^0.36.1", "@opentelemetry/instrumentation-fastify": "^0.34.0", "@opentelemetry/instrumentation-fs": "^0.10.0", "@opentelemetry/instrumentation-generic-pool": "^0.34.0", - "@opentelemetry/instrumentation-graphql": "^0.38.0", + "@opentelemetry/instrumentation-graphql": "^0.38.1", "@opentelemetry/instrumentation-grpc": "^0.49.1", "@opentelemetry/instrumentation-hapi": "^0.35.0", "@opentelemetry/instrumentation-http": "^0.49.1", @@ -16398,13 +16450,13 @@ "@opentelemetry/instrumentation-koa": "^0.38.0", "@opentelemetry/instrumentation-lru-memoizer": "^0.35.0", "@opentelemetry/instrumentation-memcached": "^0.34.0", - "@opentelemetry/instrumentation-mongodb": "^0.40.0", + "@opentelemetry/instrumentation-mongodb": "^0.41.0", "@opentelemetry/instrumentation-mongoose": "^0.36.0", "@opentelemetry/instrumentation-mysql": "^0.36.0", "@opentelemetry/instrumentation-mysql2": "^0.36.0", "@opentelemetry/instrumentation-nestjs-core": "^0.35.0", "@opentelemetry/instrumentation-net": "^0.34.0", - "@opentelemetry/instrumentation-pg": "^0.39.0", + "@opentelemetry/instrumentation-pg": "^0.39.1", "@opentelemetry/instrumentation-pino": "^0.36.0", "@opentelemetry/instrumentation-redis": "^0.37.0", "@opentelemetry/instrumentation-redis-4": "^0.37.0", @@ -16735,9 +16787,9 @@ } }, "@opentelemetry/instrumentation-mongodb": { - "version": "0.40.0", - "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.40.0.tgz", - "integrity": "sha512-ldlJUW/1UlnGtIWBt7fIUl+7+TGOKxIU+0Js5ukpXfQc07ENYFeck5TdbFjvYtF8GppPErnsZJiFiRdYm6Pv/Q==", + "version": "0.41.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/instrumentation-mongodb/-/instrumentation-mongodb-0.41.0.tgz", + "integrity": "sha512-DlSH0oyEuTW5gprCUppb0Qe3pK3cpUUFW5eTmayWNyICI1LFunwtcrULTNv6UiThD/V5ykAf/GGGEa7KFAmkog==", "requires": { "@opentelemetry/instrumentation": "^0.49.1", "@opentelemetry/sdk-metrics": "^1.9.1", @@ -17682,9 +17734,9 @@ } }, "@types/lodash": { - "version": "4.14.202", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.202.tgz", - "integrity": "sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==", + "version": "4.17.0", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", + "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", "dev": true }, "@types/luxon": { @@ -17743,9 +17795,9 @@ } }, "@types/node": { - "version": "20.11.25", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.25.tgz", - "integrity": "sha512-TBHyJxk2b7HceLVGFcpAUjsa5zIdsPWlR6XHfyGzd0SFu+/NFgQgMAl96MSDZgQDvJAvV6BKsFOrt6zIL09JDw==", + "version": "20.11.28", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.28.tgz", + "integrity": "sha512-M/GPWVS2wLkSkNHVeLkrF2fD5Lx5UC4PxA0uZcKc6QqbIQUJyW1jVjueJYi1z8n0I5PxYrtpnPnWglE+y9A0KA==", "requires": { "undici-types": "~5.26.4" } @@ -17863,12 +17915,12 @@ } }, "@types/sharp": { - "version": "0.31.1", - "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.31.1.tgz", - "integrity": "sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==", + "version": "0.32.0", + "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.32.0.tgz", + "integrity": "sha512-OOi3kL+FZDnPhVzsfD37J88FNeZh6gQsGcLc95NbeURRGvmSjeXiDcyWzF2o3yh/gQAUn2uhh/e+CPCa5nwAxw==", "dev": true, "requires": { - "@types/node": "*" + "sharp": "*" } }, "@types/shimmer": { @@ -17966,16 +18018,16 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.1.1.tgz", - "integrity": "sha512-zioDz623d0RHNhvx0eesUmGfIjzrk18nSBC8xewepKXbBvN/7c1qImV7Hg8TI1URTxKax7/zxfxj3Uph8Chcuw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.2.0.tgz", + "integrity": "sha512-mdekAHOqS9UjlmyF/LSs6AIEvfceV749GFxoBAjwAv0nkevfKHWQFDMcBZWUiIC5ft6ePWivXoS36aKQ0Cy3sw==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/type-utils": "7.1.1", - "@typescript-eslint/utils": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/type-utils": "7.2.0", + "@typescript-eslint/utils": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -17985,54 +18037,54 @@ } }, "@typescript-eslint/parser": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.1.1.tgz", - "integrity": "sha512-ZWUFyL0z04R1nAEgr9e79YtV5LbafdOtN7yapNbn1ansMyaegl2D4bL7vHoJ4HPSc4CaLwuCVas8CVuneKzplQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.2.0.tgz", + "integrity": "sha512-5FKsVcHTk6TafQKQbuIVkXq58Fnbkd2wDL4LB7AURN7RUOu1utVP+G8+6u3ZhEroW3DF6hyo3ZEXxgKgp4KeCg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.1.1.tgz", - "integrity": "sha512-cirZpA8bJMRb4WZ+rO6+mnOJrGFDd38WoXCEI57+CYBqta8Yc8aJym2i7vyqLL1vVYljgw0X27axkUXz32T8TA==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.2.0.tgz", + "integrity": "sha512-Qh976RbQM/fYtjx9hs4XkayYujB/aPwglw2choHmf3zBjB4qOywWSdt9+KLRdHubGcoSwBnXUH2sR3hkyaERRg==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1" + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0" } }, "@typescript-eslint/type-utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.1.1.tgz", - "integrity": "sha512-5r4RKze6XHEEhlZnJtR3GYeCh1IueUHdbrukV2KSlLXaTjuSfeVF8mZUVPLovidCuZfbVjfhi4c0DNSa/Rdg5g==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.2.0.tgz", + "integrity": "sha512-xHi51adBHo9O9330J8GQYQwrKBqbIPJGZZVQTHHmy200hvkLZFWJIFtAG/7IYTWUyun6DE6w5InDReePJYJlJA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.1.1", - "@typescript-eslint/utils": "7.1.1", + "@typescript-eslint/typescript-estree": "7.2.0", + "@typescript-eslint/utils": "7.2.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" } }, "@typescript-eslint/types": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.1.1.tgz", - "integrity": "sha512-KhewzrlRMrgeKm1U9bh2z5aoL4s7K3tK5DwHDn8MHv0yQfWFz/0ZR6trrIHHa5CsF83j/GgHqzdbzCXJ3crx0Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.2.0.tgz", + "integrity": "sha512-XFtUHPI/abFhm4cbCDc5Ykc8npOKBSJePY3a3s+lwumt7XWJuzP5cZcfZ610MIPHjQjNsOLlYK8ASPaNG8UiyA==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.1.1.tgz", - "integrity": "sha512-9ZOncVSfr+sMXVxxca2OJOPagRwT0u/UHikM2Rd6L/aB+kL/QAuTnsv6MeXtjzCJYb8PzrXarypSGIPx3Jemxw==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.2.0.tgz", + "integrity": "sha512-cyxS5WQQCoBwSakpMrvMXuMDEbhOo9bNHHrNcEWis6XHx6KF518tkF1wBvKIn/tpq5ZpUYK7Bdklu8qY0MsFIA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/visitor-keys": "7.1.1", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/visitor-keys": "7.2.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -18062,27 +18114,27 @@ } }, "@typescript-eslint/utils": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.1.1.tgz", - "integrity": "sha512-thOXM89xA03xAE0lW7alstvnyoBUbBX38YtY+zAUcpRPcq9EIhXPuJ0YTv948MbzmKh6e1AUszn5cBFK49Umqg==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.2.0.tgz", + "integrity": "sha512-YfHpnMAGb1Eekpm3XRK8hcMwGLGsnT6L+7b2XyRv6ouDuJU1tZir1GS2i0+VXRatMwSI1/UfcyPe53ADkU+IuA==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.1.1", - "@typescript-eslint/types": "7.1.1", - "@typescript-eslint/typescript-estree": "7.1.1", + "@typescript-eslint/scope-manager": "7.2.0", + "@typescript-eslint/types": "7.2.0", + "@typescript-eslint/typescript-estree": "7.2.0", "semver": "^7.5.4" } }, "@typescript-eslint/visitor-keys": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.1.1.tgz", - "integrity": "sha512-yTdHDQxY7cSoCcAtiBzVzxleJhkGB9NncSIyMYe2+OGON1ZsP9zOPws/Pqgopa65jvknOjlk/w7ulPlZ78PiLQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.2.0.tgz", + "integrity": "sha512-c6EIQRHhcpl6+tO8EMR+kjkkV+ugUNXOmeASA1rlzkd8EPIriavpWoiEz1HR/VLhbVIdhqnV6E7JZm00cBDx2A==", "dev": true, "requires": { - "@typescript-eslint/types": "7.1.1", + "@typescript-eslint/types": "7.2.0", "eslint-visitor-keys": "^3.4.1" } }, @@ -18396,17 +18448,17 @@ "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==" }, "archiver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.0.tgz", - "integrity": "sha512-R9HM9egs8FfktSqUqyjlKmvF4U+CWNqm/2tlROV+lOFg79MLdT67ae1l3hU47pGy8twSXxHoiefMCh43w0BriQ==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", "requires": { - "archiver-utils": "^5.0.0", + "archiver-utils": "^5.0.2", "async": "^3.2.4", "buffer-crc32": "^1.0.0", "readable-stream": "^4.0.0", "readdir-glob": "^1.1.2", "tar-stream": "^3.0.0", - "zip-stream": "^6.0.0" + "zip-stream": "^6.0.1" }, "dependencies": { "buffer": { @@ -18438,16 +18490,40 @@ } }, "archiver-utils": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.1.tgz", - "integrity": "sha512-MMAoLdMvT/nckofX1tCLrf7uJce4jTNkiT6smA2u57AOImc1nce7mR3EDujxL5yv6/MnILuQH4sAsPtDS8kTvg==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", "requires": { "glob": "^10.0.0", "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", "lazystream": "^1.0.0", "lodash": "^4.17.15", "normalize-path": "^3.0.0", - "readable-stream": "^3.6.0" + "readable-stream": "^4.0.0" + }, + "dependencies": { + "buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "requires": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + } + } } }, "are-we-there-yet": { @@ -19178,12 +19254,13 @@ "dev": true }, "compress-commons": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.1.tgz", - "integrity": "sha512-l7occIJn8YwlCEbWUCrG6gPms9qnJTCZSaznCa5HaV+yJMH4kM8BDc7q9NyoQuoiB2O6jKgTcTeY462qw6MyHw==", + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", "requires": { "crc-32": "^1.2.0", "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", "normalize-path": "^3.0.0", "readable-stream": "^4.0.0" }, @@ -20526,9 +20603,9 @@ "dev": true }, "geo-tz": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.0.1.tgz", - "integrity": "sha512-hpFbw3NKFOVy461NrWIt6Z6JQpGnMpYvNpvDunIrixbHsBPOnDcrfao0p+o/7gsMJnkhSYnTJ9DkyV2tXBLI8w==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/geo-tz/-/geo-tz-8.0.2.tgz", + "integrity": "sha512-NjEzJBzaMhO9C7lFZIsWDkVED7aLxcES3iEZOWJ97dhnDUGhEB8vhW7MaWR+2y4aWvtFV/VyuDi8Y0rUHvm4tw==", "requires": { "@turf/boolean-point-in-polygon": "^6.5.0", "@turf/helpers": "^6.5.0", @@ -21820,6 +21897,11 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, + "lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==" + }, "lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", @@ -25018,12 +25100,12 @@ "dev": true }, "zip-stream": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.0.tgz", - "integrity": "sha512-X0WFquRRDtL9HR9hc1OrabOP/VKJEX7gAr2geayt3b7dLgXgSXI6ucC4CphLQP/aQt2GyHIYgmXxtC+dVdghAQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", "requires": { "archiver-utils": "^5.0.0", - "compress-commons": "^6.0.0", + "compress-commons": "^6.0.2", "readable-stream": "^4.0.0" }, "dependencies": { diff --git a/server/package.json b/server/package.json index 5aede827b..30ba53b61 100644 --- a/server/package.json +++ b/server/package.json @@ -46,7 +46,7 @@ "@nestjs/swagger": "^7.1.8", "@nestjs/typeorm": "^10.0.0", "@nestjs/websockets": "^10.2.2", - "@opentelemetry/auto-instrumentations-node": "^0.42.0", + "@opentelemetry/auto-instrumentations-node": "^0.43.0", "@opentelemetry/exporter-prometheus": "^0.49.0", "@opentelemetry/sdk-node": "^0.49.0", "@socket.io/postgres-adapter": "^0.3.1", @@ -106,7 +106,7 @@ "@types/mock-fs": "^4.13.1", "@types/multer": "^1.4.7", "@types/node": "^20.5.7", - "@types/sharp": "^0.31.1", + "@types/sharp": "^0.32.0", "@types/supertest": "^6.0.0", "@types/ua-parser-js": "^0.7.36", "@typescript-eslint/eslint-plugin": "^7.0.0", From bd5952b94324d61b024ee4ac1e32e398eaa8a871 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 15:35:07 -0400 Subject: [PATCH 028/152] chore(deps): update vitest monorepo to v1.4.0 (#8112) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- e2e/package-lock.json | 426 +++++++++++++++++++++--------------------- 1 file changed, 209 insertions(+), 217 deletions(-) diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 0de8d431a..50c714f48 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -339,9 +339,9 @@ "dev": true }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz", - "integrity": "sha512-bmoCYyWdEL3wDQIVbcyzRyeKLgk2WtWLTWz1ZIAZF/EGbNOwSA6ew3PftJ1PqMiOOGu0OyFMzG53L0zqIpPeNA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", "cpu": [ "ppc64" ], @@ -355,9 +355,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.12.tgz", - "integrity": "sha512-qg/Lj1mu3CdQlDEEiWrlC4eaPZ1KztwGJ9B6J+/6G+/4ewxJg7gqj8eVYWvao1bXrqGiW2rsBZFSX3q2lcW05w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", "cpu": [ "arm" ], @@ -371,9 +371,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.12.tgz", - "integrity": "sha512-P0UVNGIienjZv3f5zq0DP3Nt2IE/3plFzuaS96vihvD0Hd6H/q4WXUGpCxD/E8YrSXfNyRPbpTq+T8ZQioSuPA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", "cpu": [ "arm64" ], @@ -387,9 +387,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.12.tgz", - "integrity": "sha512-3k7ZoUW6Q6YqhdhIaq/WZ7HwBpnFBlW905Fa4s4qWJyiNOgT1dOqDiVAQFwBH7gBRZr17gLrlFCRzF6jFh7Kew==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", "cpu": [ "x64" ], @@ -403,9 +403,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.12.tgz", - "integrity": "sha512-B6IeSgZgtEzGC42jsI+YYu9Z3HKRxp8ZT3cqhvliEHovq8HSX2YX8lNocDn79gCKJXOSaEot9MVYky7AKjCs8g==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", "cpu": [ "arm64" ], @@ -419,9 +419,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.12.tgz", - "integrity": "sha512-hKoVkKzFiToTgn+41qGhsUJXFlIjxI/jSYeZf3ugemDYZldIXIxhvwN6erJGlX4t5h417iFuheZ7l+YVn05N3A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", "cpu": [ "x64" ], @@ -435,9 +435,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.12.tgz", - "integrity": "sha512-4aRvFIXmwAcDBw9AueDQ2YnGmz5L6obe5kmPT8Vd+/+x/JMVKCgdcRwH6APrbpNXsPz+K653Qg8HB/oXvXVukA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", "cpu": [ "arm64" ], @@ -451,9 +451,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.12.tgz", - "integrity": "sha512-EYoXZ4d8xtBoVN7CEwWY2IN4ho76xjYXqSXMNccFSx2lgqOG/1TBPW0yPx1bJZk94qu3tX0fycJeeQsKovA8gg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", "cpu": [ "x64" ], @@ -467,9 +467,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.12.tgz", - "integrity": "sha512-J5jPms//KhSNv+LO1S1TX1UWp1ucM6N6XuL6ITdKWElCu8wXP72l9MM0zDTzzeikVyqFE6U8YAV9/tFyj0ti+w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", "cpu": [ "arm" ], @@ -483,9 +483,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.12.tgz", - "integrity": "sha512-EoTjyYyLuVPfdPLsGVVVC8a0p1BFFvtpQDB/YLEhaXyf/5bczaGeN15QkR+O4S5LeJ92Tqotve7i1jn35qwvdA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", "cpu": [ "arm64" ], @@ -499,9 +499,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.12.tgz", - "integrity": "sha512-Thsa42rrP1+UIGaWz47uydHSBOgTUnwBwNq59khgIwktK6x60Hivfbux9iNR0eHCHzOLjLMLfUMLCypBkZXMHA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", "cpu": [ "ia32" ], @@ -515,9 +515,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.12.tgz", - "integrity": "sha512-LiXdXA0s3IqRRjm6rV6XaWATScKAXjI4R4LoDlvO7+yQqFdlr1Bax62sRwkVvRIrwXxvtYEHHI4dm50jAXkuAA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", "cpu": [ "loong64" ], @@ -531,9 +531,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.12.tgz", - "integrity": "sha512-fEnAuj5VGTanfJ07ff0gOA6IPsvrVHLVb6Lyd1g2/ed67oU1eFzL0r9WL7ZzscD+/N6i3dWumGE1Un4f7Amf+w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", "cpu": [ "mips64el" ], @@ -547,9 +547,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.12.tgz", - "integrity": "sha512-nYJA2/QPimDQOh1rKWedNOe3Gfc8PabU7HT3iXWtNUbRzXS9+vgB0Fjaqr//XNbd82mCxHzik2qotuI89cfixg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", "cpu": [ "ppc64" ], @@ -563,9 +563,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.12.tgz", - "integrity": "sha512-2MueBrlPQCw5dVJJpQdUYgeqIzDQgw3QtiAHUC4RBz9FXPrskyyU3VI1hw7C0BSKB9OduwSJ79FTCqtGMWqJHg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", "cpu": [ "riscv64" ], @@ -579,9 +579,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.12.tgz", - "integrity": "sha512-+Pil1Nv3Umes4m3AZKqA2anfhJiVmNCYkPchwFJNEJN5QxmTs1uzyy4TvmDrCRNT2ApwSari7ZIgrPeUx4UZDg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", "cpu": [ "s390x" ], @@ -595,9 +595,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.12.tgz", - "integrity": "sha512-B71g1QpxfwBvNrfyJdVDexenDIt1CiDN1TIXLbhOw0KhJzE78KIFGX6OJ9MrtC0oOqMWf+0xop4qEU8JrJTwCg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", "cpu": [ "x64" ], @@ -611,9 +611,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.12.tgz", - "integrity": "sha512-3ltjQ7n1owJgFbuC61Oj++XhtzmymoCihNFgT84UAmJnxJfm4sYCiSLTXZtE00VWYpPMYc+ZQmB6xbSdVh0JWA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", "cpu": [ "x64" ], @@ -627,9 +627,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.12.tgz", - "integrity": "sha512-RbrfTB9SWsr0kWmb9srfF+L933uMDdu9BIzdA7os2t0TXhCRjrQyCeOt6wVxr79CKD4c+p+YhCj31HBkYcXebw==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", "cpu": [ "x64" ], @@ -643,9 +643,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.12.tgz", - "integrity": "sha512-HKjJwRrW8uWtCQnQOz9qcU3mUZhTUQvi56Q8DPTLLB+DawoiQdjsYq+j+D3s9I8VFtDr+F9CjgXKKC4ss89IeA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", "cpu": [ "x64" ], @@ -659,9 +659,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.12.tgz", - "integrity": "sha512-URgtR1dJnmGvX864pn1B2YUYNzjmXkuJOIqG2HdU62MVS4EHpU2946OZoTMnRUHklGtJdJZ33QfzdjGACXhn1A==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", "cpu": [ "arm64" ], @@ -675,9 +675,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.12.tgz", - "integrity": "sha512-+ZOE6pUkMOJfmxmBZElNOx72NKpIa/HFOMGzu8fqzQJ5kgf6aTGrcJaFsNiVMH4JKpMipyK+7k0n2UXN7a8YKQ==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", "cpu": [ "ia32" ], @@ -691,9 +691,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.12.tgz", - "integrity": "sha512-T1QyPSDCyMXaO3pzBkF96E8xMkiRYbUEZADd29SyPGabqxMViNoii+NcK7eWJAEoU6RZyEm5lVSIjTmcdoB9HA==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", "cpu": [ "x64" ], @@ -863,9 +863,9 @@ "dev": true }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.22", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", - "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -941,9 +941,9 @@ } }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.12.0.tgz", - "integrity": "sha512-+ac02NL/2TCKRrJu2wffk1kZ+RyqxVUlbjSagNgPm94frxtr+XDL12E5Ll1enWskLrtrZ2r8L3wED1orIibV/w==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.13.0.tgz", + "integrity": "sha512-5ZYPOuaAqEH/W3gYsRkxQATBW3Ii1MfaT4EQstTnLKViLi2gLSQmlmtTpGucNP3sXEpOiI5tdGhjdE111ekyEg==", "cpu": [ "arm" ], @@ -954,9 +954,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.12.0.tgz", - "integrity": "sha512-OBqcX2BMe6nvjQ0Nyp7cC90cnumt8PXmO7Dp3gfAju/6YwG0Tj74z1vKrfRz7qAv23nBcYM8BCbhrsWqO7PzQQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.13.0.tgz", + "integrity": "sha512-BSbaCmn8ZadK3UAQdlauSvtaJjhlDEjS5hEVVIN3A4bbl3X+otyf/kOJV08bYiRxfejP3DXFzO2jz3G20107+Q==", "cpu": [ "arm64" ], @@ -967,9 +967,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.12.0.tgz", - "integrity": "sha512-X64tZd8dRE/QTrBIEs63kaOBG0b5GVEd3ccoLtyf6IdXtHdh8h+I56C2yC3PtC9Ucnv0CpNFJLqKFVgCYe0lOQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.13.0.tgz", + "integrity": "sha512-Ovf2evVaP6sW5Ut0GHyUSOqA6tVKfrTHddtmxGQc1CTQa1Cw3/KMCDEEICZBbyppcwnhMwcDce9ZRxdWRpVd6g==", "cpu": [ "arm64" ], @@ -980,9 +980,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.12.0.tgz", - "integrity": "sha512-cc71KUZoVbUJmGP2cOuiZ9HSOP14AzBAThn3OU+9LcA1+IUqswJyR1cAJj3Mg55HbjZP6OLAIscbQsQLrpgTOg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.13.0.tgz", + "integrity": "sha512-U+Jcxm89UTK592vZ2J9st9ajRv/hrwHdnvyuJpa5A2ngGSVHypigidkQJP+YiGL6JODiUeMzkqQzbCG3At81Gg==", "cpu": [ "x64" ], @@ -993,9 +993,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.12.0.tgz", - "integrity": "sha512-a6w/Y3hyyO6GlpKL2xJ4IOh/7d+APaqLYdMf86xnczU3nurFTaVN9s9jOXQg97BE4nYm/7Ga51rjec5nfRdrvA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.13.0.tgz", + "integrity": "sha512-8wZidaUJUTIR5T4vRS22VkSMOVooG0F4N+JSwQXWSRiC6yfEsFMLTYRFHvby5mFFuExHa/yAp9juSphQQJAijQ==", "cpu": [ "arm" ], @@ -1006,9 +1006,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.12.0.tgz", - "integrity": "sha512-0fZBq27b+D7Ar5CQMofVN8sggOVhEtzFUwOwPppQt0k+VR+7UHMZZY4y+64WJ06XOhBTKXtQB/Sv0NwQMXyNAA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.13.0.tgz", + "integrity": "sha512-Iu0Kno1vrD7zHQDxOmvweqLkAzjxEVqNhUIXBsZ8hu8Oak7/5VTPrxOEZXYC1nmrBVJp0ZcL2E7lSuuOVaE3+w==", "cpu": [ "arm64" ], @@ -1019,9 +1019,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.12.0.tgz", - "integrity": "sha512-eTvzUS3hhhlgeAv6bfigekzWZjaEX9xP9HhxB0Dvrdbkk5w/b+1Sxct2ZuDxNJKzsRStSq1EaEkVSEe7A7ipgQ==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.13.0.tgz", + "integrity": "sha512-C31QrW47llgVyrRjIwiOwsHFcaIwmkKi3PCroQY5aVq4H0A5v/vVVAtFsI1nfBngtoRpeREvZOkIhmRwUKkAdw==", "cpu": [ "arm64" ], @@ -1032,9 +1032,9 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.12.0.tgz", - "integrity": "sha512-ix+qAB9qmrCRiaO71VFfY8rkiAZJL8zQRXveS27HS+pKdjwUfEhqo2+YF2oI+H/22Xsiski+qqwIBxVewLK7sw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.13.0.tgz", + "integrity": "sha512-Oq90dtMHvthFOPMl7pt7KmxzX7E71AfyIhh+cPhLY9oko97Zf2C9tt/XJD4RgxhaGeAraAXDtqxvKE1y/j35lA==", "cpu": [ "riscv64" ], @@ -1045,9 +1045,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.12.0.tgz", - "integrity": "sha512-TenQhZVOtw/3qKOPa7d+QgkeM6xY0LtwzR8OplmyL5LrgTWIXpTQg2Q2ycBf8jm+SFW2Wt/DTn1gf7nFp3ssVA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.13.0.tgz", + "integrity": "sha512-yUD/8wMffnTKuiIsl6xU+4IA8UNhQ/f1sAnQebmE/lyQ8abjsVyDkyRkWop0kdMhKMprpNIhPmYlCxgHrPoXoA==", "cpu": [ "x64" ], @@ -1058,9 +1058,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.12.0.tgz", - "integrity": "sha512-LfFdRhNnW0zdMvdCb5FNuWlls2WbbSridJvxOvYWgSBOYZtgBfW9UGNJG//rwMqTX1xQE9BAodvMH9tAusKDUw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.13.0.tgz", + "integrity": "sha512-9RyNqoFNdF0vu/qqX63fKotBh43fJQeYC98hCaf89DYQpv+xu0D8QFSOS0biA7cGuqJFOc1bJ+m2rhhsKcw1hw==", "cpu": [ "x64" ], @@ -1071,9 +1071,9 @@ ] }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.12.0.tgz", - "integrity": "sha512-JPDxovheWNp6d7AHCgsUlkuCKvtu3RB55iNEkaQcf0ttsDU/JZF+iQnYcQJSk/7PtT4mjjVG8N1kpwnI9SLYaw==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.13.0.tgz", + "integrity": "sha512-46ue8ymtm/5PUU6pCvjlic0z82qWkxv54GTJZgHrQUuZnVH+tvvSP0LsozIDsCBFO4VjJ13N68wqrKSeScUKdA==", "cpu": [ "arm64" ], @@ -1084,9 +1084,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.12.0.tgz", - "integrity": "sha512-fjtuvMWRGJn1oZacG8IPnzIV6GF2/XG+h71FKn76OYFqySXInJtseAqdprVTDTyqPxQOG9Exak5/E9Z3+EJ8ZA==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.13.0.tgz", + "integrity": "sha512-P5/MqLdLSlqxbeuJ3YDeX37srC8mCflSyTrUsgbU1c/U9j6l2g2GiIdYaGD9QjdMQPMSgYm7hgg0551wHyIluw==", "cpu": [ "ia32" ], @@ -1097,9 +1097,9 @@ ] }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.12.0.tgz", - "integrity": "sha512-ZYmr5mS2wd4Dew/JjT0Fqi2NPB/ZhZ2VvPp7SmvPZb4Y1CG/LRcS6tcRo2cYU7zLK5A7cdbhWnnWmUjoI4qapg==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.13.0.tgz", + "integrity": "sha512-UKXUQNbO3DOhzLRwHSpa0HnhhCgNODvfoPWv2FCXme8N/ANFfhIPMGuOT+QuKd16+B5yxZ0HdpNlqPvTMS1qfw==", "cpu": [ "x64" ], @@ -1497,9 +1497,9 @@ "dev": true }, "node_modules/@vitest/coverage-v8": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.3.1.tgz", - "integrity": "sha512-UuBnkSJUNE9rdHjDCPyJ4fYuMkoMtnghes1XohYa4At0MS3OQSAo97FrbwSLRshYsXThMZy1+ybD/byK5llyIg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/coverage-v8/-/coverage-v8-1.4.0.tgz", + "integrity": "sha512-4hDGyH1SvKpgZnIByr9LhGgCEuF9DKM34IBLCC/fVfy24Z3+PZ+Ii9hsVBsHvY1umM1aGPEjceRkzxCfcQ10wg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.1", @@ -1507,12 +1507,13 @@ "debug": "^4.3.4", "istanbul-lib-coverage": "^3.2.2", "istanbul-lib-report": "^3.0.1", - "istanbul-lib-source-maps": "^4.0.1", + "istanbul-lib-source-maps": "^5.0.4", "istanbul-reports": "^3.1.6", "magic-string": "^0.30.5", "magicast": "^0.3.3", "picocolors": "^1.0.0", "std-env": "^3.5.0", + "strip-literal": "^2.0.0", "test-exclude": "^6.0.0", "v8-to-istanbul": "^9.2.0" }, @@ -1520,17 +1521,17 @@ "url": "https://opencollective.com/vitest" }, "peerDependencies": { - "vitest": "1.3.1" + "vitest": "1.4.0" } }, "node_modules/@vitest/expect": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.3.1.tgz", - "integrity": "sha512-xofQFwIzfdmLLlHa6ag0dPV8YsnKOCP1KdAeVVh34vSjN2dcUiXYCD9htu/9eM7t8Xln4v03U9HLxLpPlsXdZw==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-1.4.0.tgz", + "integrity": "sha512-Jths0sWCJZ8BxjKe+p+eKsoqev1/T8lYcrjavEaz8auEJ4jAVY0GwW3JKmdVU4mmNPLPHixh4GNXP7GFtAiDHA==", "dev": true, "dependencies": { - "@vitest/spy": "1.3.1", - "@vitest/utils": "1.3.1", + "@vitest/spy": "1.4.0", + "@vitest/utils": "1.4.0", "chai": "^4.3.10" }, "funding": { @@ -1538,12 +1539,12 @@ } }, "node_modules/@vitest/runner": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.3.1.tgz", - "integrity": "sha512-5FzF9c3jG/z5bgCnjr8j9LNq/9OxV2uEBAITOXfoe3rdZJTdO7jzThth7FXv/6b+kdY65tpRQB7WaKhNZwX+Kg==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-1.4.0.tgz", + "integrity": "sha512-EDYVSmesqlQ4RD2VvWo3hQgTJ7ZrFQ2VSJdfiJiArkCerDAGeyF1i6dHkmySqk573jLp6d/cfqCN+7wUB5tLgg==", "dev": true, "dependencies": { - "@vitest/utils": "1.3.1", + "@vitest/utils": "1.4.0", "p-limit": "^5.0.0", "pathe": "^1.1.1" }, @@ -1552,9 +1553,9 @@ } }, "node_modules/@vitest/snapshot": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.3.1.tgz", - "integrity": "sha512-EF++BZbt6RZmOlE3SuTPu/NfwBF6q4ABS37HHXzs2LUVPBLx2QoY/K0fKpRChSo8eLiuxcbCVfqKgx/dplCDuQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-1.4.0.tgz", + "integrity": "sha512-saAFnt5pPIA5qDGxOHxJ/XxhMFKkUSBJmVt5VgDsAqPTX6JP326r5C/c9UuCMPoXNzuudTPsYDZCoJ5ilpqG2A==", "dev": true, "dependencies": { "magic-string": "^0.30.5", @@ -1566,9 +1567,9 @@ } }, "node_modules/@vitest/spy": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.3.1.tgz", - "integrity": "sha512-xAcW+S099ylC9VLU7eZfdT9myV67Nor9w9zhf0mGCYJSO+zM2839tOeROTdikOi/8Qeusffvxb/MyBSOja1Uig==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-1.4.0.tgz", + "integrity": "sha512-Ywau/Qs1DzM/8Uc+yA77CwSegizMlcgTJuYGAi0jujOteJOUf1ujunHThYo243KG9nAyWT3L9ifPYZ5+As/+6Q==", "dev": true, "dependencies": { "tinyspy": "^2.2.0" @@ -1578,9 +1579,9 @@ } }, "node_modules/@vitest/utils": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.3.1.tgz", - "integrity": "sha512-d3Waie/299qqRyHTm2DjADeTaNdNSVsnwHPWrs20JMpjh6eiVq7ggggweO8rc4arhf6rRkWuHKwvxGvejUXZZQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-1.4.0.tgz", + "integrity": "sha512-mx3Yd1/6e2Vt/PUC98DcqTirtfxUyAZ32uK82r8rZzbtBeBo+nqgnjx/LvqQdWsrvNtm14VmurNgcf4nqY5gJg==", "dev": true, "dependencies": { "diff-sequences": "^29.6.3", @@ -2186,9 +2187,9 @@ } }, "node_modules/esbuild": { - "version": "0.19.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.12.tgz", - "integrity": "sha512-aARqgq8roFBj054KvQr5f1sFu0D65G+miZRCuJyJ0G13Zwx7vRar5Zhn2tkQNzIXcBrNVsv/8stehpj+GAjgbg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", "dev": true, "hasInstallScript": true, "bin": { @@ -2198,29 +2199,29 @@ "node": ">=12" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.19.12", - "@esbuild/android-arm": "0.19.12", - "@esbuild/android-arm64": "0.19.12", - "@esbuild/android-x64": "0.19.12", - "@esbuild/darwin-arm64": "0.19.12", - "@esbuild/darwin-x64": "0.19.12", - "@esbuild/freebsd-arm64": "0.19.12", - "@esbuild/freebsd-x64": "0.19.12", - "@esbuild/linux-arm": "0.19.12", - "@esbuild/linux-arm64": "0.19.12", - "@esbuild/linux-ia32": "0.19.12", - "@esbuild/linux-loong64": "0.19.12", - "@esbuild/linux-mips64el": "0.19.12", - "@esbuild/linux-ppc64": "0.19.12", - "@esbuild/linux-riscv64": "0.19.12", - "@esbuild/linux-s390x": "0.19.12", - "@esbuild/linux-x64": "0.19.12", - "@esbuild/netbsd-x64": "0.19.12", - "@esbuild/openbsd-x64": "0.19.12", - "@esbuild/sunos-x64": "0.19.12", - "@esbuild/win32-arm64": "0.19.12", - "@esbuild/win32-ia32": "0.19.12", - "@esbuild/win32-x64": "0.19.12" + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, "node_modules/escalade": { @@ -3109,14 +3110,14 @@ } }, "node_modules/istanbul-lib-source-maps": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", - "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz", + "integrity": "sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==", "dev": true, "dependencies": { + "@jridgewell/trace-mapping": "^0.3.23", "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "istanbul-lib-coverage": "^3.0.0" }, "engines": { "node": ">=10" @@ -3920,9 +3921,9 @@ } }, "node_modules/postcss": { - "version": "8.4.35", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.35.tgz", - "integrity": "sha512-u5U8qYpBCpN13BsiEB0CbR1Hhh4Gc0zLFuedrHJKMctHCHAGrMdG0PRM/KErzAL3CU6/eckEtmHNB3x6e3c0vA==", + "version": "8.4.37", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.37.tgz", + "integrity": "sha512-7iB/v/r7Woof0glKLH8b1SPHrsX7uhdO+Geb41QpF/+mWZHU3uxxSlN+UXGVit1PawOYDToO+AbZzhBzWRDwbQ==", "dev": true, "funding": [ { @@ -3941,7 +3942,7 @@ "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" @@ -4296,9 +4297,9 @@ } }, "node_modules/rollup": { - "version": "4.12.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.12.0.tgz", - "integrity": "sha512-wz66wn4t1OHIJw3+XU7mJJQV/2NAfw5OAk6G6Hoo3zcvz/XOfQ52Vgi+AN4Uxoxi0KBBwk2g8zPrTDA4btSB/Q==", + "version": "4.13.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.13.0.tgz", + "integrity": "sha512-3YegKemjoQnYKmsBlOHfMLVPPA5xLkQ8MHLLSw/fBrFaVkEayL51DilPpNNLq1exr98F2B1TzrV0FUlN3gWRPg==", "dev": true, "dependencies": { "@types/estree": "1.0.5" @@ -4311,19 +4312,19 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.12.0", - "@rollup/rollup-android-arm64": "4.12.0", - "@rollup/rollup-darwin-arm64": "4.12.0", - "@rollup/rollup-darwin-x64": "4.12.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.12.0", - "@rollup/rollup-linux-arm64-gnu": "4.12.0", - "@rollup/rollup-linux-arm64-musl": "4.12.0", - "@rollup/rollup-linux-riscv64-gnu": "4.12.0", - "@rollup/rollup-linux-x64-gnu": "4.12.0", - "@rollup/rollup-linux-x64-musl": "4.12.0", - "@rollup/rollup-win32-arm64-msvc": "4.12.0", - "@rollup/rollup-win32-ia32-msvc": "4.12.0", - "@rollup/rollup-win32-x64-msvc": "4.12.0", + "@rollup/rollup-android-arm-eabi": "4.13.0", + "@rollup/rollup-android-arm64": "4.13.0", + "@rollup/rollup-darwin-arm64": "4.13.0", + "@rollup/rollup-darwin-x64": "4.13.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.13.0", + "@rollup/rollup-linux-arm64-gnu": "4.13.0", + "@rollup/rollup-linux-arm64-musl": "4.13.0", + "@rollup/rollup-linux-riscv64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-gnu": "4.13.0", + "@rollup/rollup-linux-x64-musl": "4.13.0", + "@rollup/rollup-win32-arm64-msvc": "4.13.0", + "@rollup/rollup-win32-ia32-msvc": "4.13.0", + "@rollup/rollup-win32-x64-msvc": "4.13.0", "fsevents": "~2.3.2" } }, @@ -4476,19 +4477,10 @@ "node": ">=10.0.0" } }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", + "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "engines": { "node": ">=0.10.0" @@ -4886,14 +4878,14 @@ } }, "node_modules/vite": { - "version": "5.1.4", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.1.4.tgz", - "integrity": "sha512-n+MPqzq+d9nMVTKyewqw6kSt+R3CkvF9QAKY8obiQn8g1fwTscKxyfaYnC632HtBXAQGc1Yjomphwn1dtwGAHg==", + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.2.tgz", + "integrity": "sha512-FWZbz0oSdLq5snUI0b6sULbz58iXFXdvkZfZWR/F0ZJuKTSPO7v72QPXt6KqYeMFb0yytNp6kZosxJ96Nr/wDQ==", "dev": true, "dependencies": { - "esbuild": "^0.19.3", - "postcss": "^8.4.35", - "rollup": "^4.2.0" + "esbuild": "^0.20.1", + "postcss": "^8.4.36", + "rollup": "^4.13.0" }, "bin": { "vite": "bin/vite.js" @@ -4941,9 +4933,9 @@ } }, "node_modules/vite-node": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.3.1.tgz", - "integrity": "sha512-azbRrqRxlWTJEVbzInZCTchx0X69M/XPTCz4H+TLvlTcR/xH/3hkRqhOakT41fMJCMzXTu4UvegkZiEoJAWvng==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-1.4.0.tgz", + "integrity": "sha512-VZDAseqjrHgNd4Kh8icYHWzTKSCZMhia7GyHfhtzLW33fZlG9SwsB6CEhgyVOWkJfJ2pFLrp/Gj1FSfAiqH9Lw==", "dev": true, "dependencies": { "cac": "^6.7.14", @@ -4977,16 +4969,16 @@ } }, "node_modules/vitest": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.3.1.tgz", - "integrity": "sha512-/1QJqXs8YbCrfv/GPQ05wAZf2eakUPLPa18vkJAKE7RXOKfVHqMZZ1WlTjiwl6Gcn65M5vpNUB6EFLnEdRdEXQ==", + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-1.4.0.tgz", + "integrity": "sha512-gujzn0g7fmwf83/WzrDTnncZt2UiXP41mHuFYFrdwaLRVQ6JYQEiME2IfEjU3vcFL3VKa75XhI3lFgn+hfVsQw==", "dev": true, "dependencies": { - "@vitest/expect": "1.3.1", - "@vitest/runner": "1.3.1", - "@vitest/snapshot": "1.3.1", - "@vitest/spy": "1.3.1", - "@vitest/utils": "1.3.1", + "@vitest/expect": "1.4.0", + "@vitest/runner": "1.4.0", + "@vitest/snapshot": "1.4.0", + "@vitest/spy": "1.4.0", + "@vitest/utils": "1.4.0", "acorn-walk": "^8.3.2", "chai": "^4.3.10", "debug": "^4.3.4", @@ -5000,7 +4992,7 @@ "tinybench": "^2.5.1", "tinypool": "^0.8.2", "vite": "^5.0.0", - "vite-node": "1.3.1", + "vite-node": "1.4.0", "why-is-node-running": "^2.2.2" }, "bin": { @@ -5015,8 +5007,8 @@ "peerDependencies": { "@edge-runtime/vm": "*", "@types/node": "^18.0.0 || >=20.0.0", - "@vitest/browser": "1.3.1", - "@vitest/ui": "1.3.1", + "@vitest/browser": "1.4.0", + "@vitest/ui": "1.4.0", "happy-dom": "*", "jsdom": "*" }, From ec9a6bca144c565e2e29e0ae34f8da01a663e94d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 15:38:58 -0400 Subject: [PATCH 029/152] chore(deps): update dependency socket.io-client to v4.7.5 (#8111) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- e2e/package-lock.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/package-lock.json b/e2e/package-lock.json index 50c714f48..3f892fe2e 100644 --- a/e2e/package-lock.json +++ b/e2e/package-lock.json @@ -4450,9 +4450,9 @@ } }, "node_modules/socket.io-client": { - "version": "4.7.4", - "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.4.tgz", - "integrity": "sha512-wh+OkeF0rAVCrABWQBaEjLfb7DVPotMbu0cgWgyR0v6eA4EoVnAwcIeIbcdTE3GT/H3kbdLl7OoH2+asoDRIIg==", + "version": "4.7.5", + "resolved": "https://registry.npmjs.org/socket.io-client/-/socket.io-client-4.7.5.tgz", + "integrity": "sha512-sJ/tqHOCe7Z50JCBCXrsY3I2k03iOiUe+tj1OmKeD2lXPiGH/RUCdTZFoqVyN7l1MnpIzPrGtLcijffmeouNlQ==", "dev": true, "dependencies": { "@socket.io/component-emitter": "~3.1.0", From 048d437b0b7f6b21312f0e5c20e99a2c9dde50fa Mon Sep 17 00:00:00 2001 From: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com> Date: Wed, 20 Mar 2024 20:40:41 +0100 Subject: [PATCH 030/152] fix(web): prevent duplicate time bucket loads (#8091) --- web/src/lib/stores/asset.store.spec.ts | 41 ++++++++++++++++++++++---- web/src/lib/stores/assets.store.ts | 30 ++++++++++--------- web/src/lib/utils.ts | 2 +- 3 files changed, 53 insertions(+), 20 deletions(-) diff --git a/web/src/lib/stores/asset.store.spec.ts b/web/src/lib/stores/asset.store.spec.ts index d97692ef6..55f3fe1ff 100644 --- a/web/src/lib/stores/asset.store.spec.ts +++ b/web/src/lib/stores/asset.store.spec.ts @@ -1,4 +1,5 @@ import { sdkMock } from '$lib/__mocks__/sdk.mock'; +import { AbortError } from '$lib/utils'; import { TimeBucketSize, type AssetResponseDto } from '@immich/sdk'; import { assetFactory } from '@test-data/factories/asset-factory'; import { AssetStore, BucketPosition } from './assets.store'; @@ -62,7 +63,15 @@ describe('AssetStore', () => { { count: 1, timeBucket: '2024-01-03T00:00:00.000Z' }, { count: 3, timeBucket: '2024-01-01T00:00:00.000Z' }, ]); - sdkMock.getTimeBucket.mockImplementation(({ timeBucket }) => Promise.resolve(bucketAssets[timeBucket])); + sdkMock.getTimeBucket.mockImplementation(async ({ timeBucket }, { signal } = {}) => { + // Allow request to be aborted + await new Promise((resolve) => setTimeout(resolve, 0)); + if (signal?.aborted) { + throw new AbortError(); + } + + return bucketAssets[timeBucket]; + }); await assetStore.init({ width: 0, height: 0 }); }); @@ -87,17 +96,39 @@ describe('AssetStore', () => { }); it('cancels bucket loading', async () => { - const abortSpy = vi.spyOn(AbortController.prototype, 'abort'); - const loadPromise = assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Unknown); - const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z'); - expect(bucket).not.toBeNull(); + const loadPromise = assetStore.loadBucket(bucket!.bucketDate, BucketPosition.Unknown); + const abortSpy = vi.spyOn(bucket!.cancelToken!, 'abort'); assetStore.cancelBucket(bucket!); expect(abortSpy).toBeCalledTimes(1); + await loadPromise; expect(assetStore.getBucketByDate('2024-01-01T00:00:00.000Z')?.assets.length).toEqual(0); }); + + it('prevents loading buckets multiple times', async () => { + await Promise.all([ + assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Unknown), + assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Unknown), + ]); + expect(sdkMock.getTimeBucket).toBeCalledTimes(1); + + await assetStore.loadBucket('2024-01-01T00:00:00.000Z', BucketPosition.Unknown); + expect(sdkMock.getTimeBucket).toBeCalledTimes(1); + }); + + it('allows loading a canceled bucket', async () => { + const bucket = assetStore.getBucketByDate('2024-01-01T00:00:00.000Z'); + const loadPromise = assetStore.loadBucket(bucket!.bucketDate, BucketPosition.Unknown); + + assetStore.cancelBucket(bucket!); + await loadPromise; + expect(bucket?.assets.length).toEqual(0); + + await assetStore.loadBucket(bucket!.bucketDate, BucketPosition.Unknown); + expect(bucket!.assets.length).toEqual(3); + }); }); describe('addAssets', () => { diff --git a/web/src/lib/stores/assets.store.ts b/web/src/lib/stores/assets.store.ts index 30fc06085..45b26c1a1 100644 --- a/web/src/lib/stores/assets.store.ts +++ b/web/src/lib/stores/assets.store.ts @@ -229,21 +229,21 @@ export class AssetStore { } async loadBucket(bucketDate: string, position: BucketPosition): Promise { + const bucket = this.getBucketByDate(bucketDate); + if (!bucket) { + return; + } + + bucket.position = position; + + if (bucket.cancelToken || bucket.assets.length > 0) { + this.emit(false); + return; + } + + bucket.cancelToken = new AbortController(); + try { - const bucket = this.getBucketByDate(bucketDate); - if (!bucket) { - return; - } - - bucket.position = position; - - if (bucket.assets.length > 0) { - this.emit(false); - return; - } - - bucket.cancelToken = new AbortController(); - const assets = await getTimeBucket( { ...this.options, @@ -278,6 +278,8 @@ export class AssetStore { this.emit(true); } catch (error) { handleError(error, 'Failed to load assets'); + } finally { + bucket.cancelToken = null; } } diff --git a/web/src/lib/utils.ts b/web/src/lib/utils.ts index 4b1892ae8..2cebba630 100644 --- a/web/src/lib/utils.ts +++ b/web/src/lib/utils.ts @@ -27,7 +27,7 @@ interface UploadRequestOptions { onUploadProgress?: (event: ProgressEvent) => void; } -class AbortError extends Error { +export class AbortError extends Error { name = 'AbortError'; } From 92cc647cf6e3b0927146b6ee034a111a623fa3c6 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 20 Mar 2024 14:50:01 -0500 Subject: [PATCH 031/152] chore: renovate grouping (#8113) --- renovate.json | 56 +++++++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 38 deletions(-) diff --git a/renovate.json b/renovate.json index 7cb136b1a..afa68011d 100644 --- a/renovate.json +++ b/renovate.json @@ -4,33 +4,28 @@ "minimumReleaseAge": "5 days", "packageRules": [ { - "matchFileNames": ["cli/**"], - "groupName": "@immich/cli", - "matchUpdateTypes": ["minor", "patch"], - "schedule": "on tuesday" - }, - { - "matchFileNames": ["docs/**"], - "groupName": "docs", - "matchUpdateTypes": ["minor", "patch"], - "schedule": "on tuesday" - }, - { - "matchFileNames": ["mobile/**"], - "groupName": "mobile", - "matchUpdateTypes": ["minor", "patch"], - "schedule": "on tuesday" - }, - { - "matchFileNames": ["server/**"], - "groupName": "server", + "matchFileNames": [ + "cli/**", + "docs/**", + "e2e/**", + "open-api/**", + "server/**", + "web/**" + ], + "groupName": "typescript-projects", "matchUpdateTypes": ["minor", "patch"], "excludePackagePrefixes": ["exiftool", "reflect-metadata"], "schedule": "on tuesday" }, { - "matchFileNames": ["open-api/**"], - "groupName": "open-api", + "matchFileNames": ["machine-learning/**"], + "groupName": "machine-learning", + "rangeStrategy": "in-range-only", + "schedule": "on tuesday" + }, + { + "matchFileNames": ["mobile/**"], + "groupName": "mobile", "matchUpdateTypes": ["minor", "patch"], "schedule": "on tuesday" }, @@ -45,18 +40,6 @@ "matchPackagePrefixes": ["@sveltejs"], "schedule": "on tuesday" }, - { - "matchFileNames": ["web/**"], - "groupName": "web", - "matchUpdateTypes": ["minor", "patch"], - "schedule": "on tuesday" - }, - { - "matchFileNames": ["machine-learning/**"], - "groupName": "machine-learning", - "rangeStrategy": "in-range-only", - "schedule": "on tuesday" - }, { "matchFileNames": [".github/**"], "groupName": "github-actions", @@ -81,9 +64,6 @@ } ], "ignorePaths": ["mobile/openapi/pubspec.yaml"], - "ignoreDeps": [ - "http", - "intl" - ], + "ignoreDeps": ["http", "intl"], "labels": ["dependencies", "renovate"] } From 81f0265095779a5bb4ba8bea53893aea9a2552af Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 20 Mar 2024 15:04:03 -0500 Subject: [PATCH 032/152] chore: organize config, validation, decorators (#8118) * refactor: validation * refactor: utilities * refactor: config --- .../src/{infra/infra.config.ts => config.ts} | 35 +++ server/src/decorators.ts | 124 ++++++++ server/src/domain/access/access.core.ts | 2 +- server/src/domain/activity/activity.dto.ts | 2 +- server/src/domain/album/album-response.dto.ts | 2 +- server/src/domain/album/album.service.ts | 2 +- .../domain/album/dto/album-add-users.dto.ts | 2 +- .../src/domain/album/dto/album-create.dto.ts | 2 +- .../src/domain/album/dto/album-update.dto.ts | 2 +- server/src/domain/album/dto/album.dto.ts | 2 +- server/src/domain/album/dto/get-albums.dto.ts | 2 +- server/src/domain/api-key/api-key.dto.ts | 2 +- server/src/domain/asset/asset.service.ts | 2 +- server/src/domain/asset/dto/asset-ids.dto.ts | 2 +- .../src/domain/asset/dto/asset-stack.dto.ts | 2 +- .../domain/asset/dto/asset-statistics.dto.ts | 2 +- server/src/domain/asset/dto/asset.dto.ts | 2 +- server/src/domain/asset/dto/map-marker.dto.ts | 2 +- .../src/domain/asset/dto/time-bucket.dto.ts | 2 +- .../response-dto/asset-ids-response.dto.ts | 2 +- server/src/domain/audit/audit.dto.ts | 2 +- server/src/domain/audit/audit.service.ts | 2 +- server/src/domain/auth/auth.service.ts | 2 +- server/src/domain/domain.config.ts | 36 --- server/src/domain/domain.util.ts | 280 ------------------ server/src/domain/download/download.dto.ts | 2 +- .../domain/download/download.service.spec.ts | 2 +- .../src/domain/download/download.service.ts | 2 +- server/src/domain/job/job.dto.ts | 2 +- server/src/domain/library/library.dto.ts | 2 +- server/src/domain/library/library.service.ts | 3 +- server/src/domain/media/media.service.ts | 2 +- .../src/domain/metadata/metadata.service.ts | 2 +- server/src/domain/person/person.dto.ts | 2 +- .../src/domain/person/person.service.spec.ts | 2 +- server/src/domain/person/person.service.ts | 2 +- .../domain/repositories/asset.repository.ts | 2 +- .../domain/repositories/person.repository.ts | 2 +- .../domain/repositories/search.repository.ts | 2 +- .../search/dto/search-suggestion.dto.ts | 2 +- server/src/domain/search/dto/search.dto.ts | 2 +- .../domain/server-info/server-info.service.ts | 2 +- .../src/domain/shared-link/shared-link.dto.ts | 2 +- .../domain/shared-link/shared-link.service.ts | 2 +- .../domain/smart-info/dto/model-config.dto.ts | 2 +- .../domain/smart-info/smart-info.service.ts | 2 +- .../storage-template.service.ts | 2 +- .../dto/system-config-ffmpeg.dto.ts | 2 +- .../dto/system-config-library.dto.ts | 2 +- .../dto/system-config-logging.dto.ts | 2 +- .../dto/system-config-machine-learning.dto.ts | 2 +- .../dto/system-config-map.dto.ts | 2 +- .../system-config-new-version-check.dto.ts | 2 +- .../dto/system-config-oauth.dto.ts | 2 +- .../dto/system-config-password-login.dto.ts | 2 +- .../system-config-reverse-geocoding.dto.ts | 2 +- .../dto/system-config-storage-template.dto.ts | 2 +- .../dto/system-config-trash.dto.ts | 2 +- server/src/domain/tag/tag.dto.ts | 2 +- server/src/domain/trash/trash.service.ts | 2 +- server/src/domain/user/dto/create-user.dto.ts | 2 +- server/src/domain/user/dto/delete-user.dto.ts | 2 +- server/src/domain/user/dto/update-user.dto.ts | 2 +- server/src/domain/user/user.service.spec.ts | 2 +- server/src/domain/user/user.service.ts | 2 +- .../immich/api-v1/asset/asset.controller.ts | 3 +- .../src/immich/api-v1/asset/asset.service.ts | 2 +- .../api-v1/asset/dto/asset-search.dto.ts | 2 +- .../api-v1/asset/dto/create-asset.dto.ts | 2 +- .../asset/dto/get-asset-thumbnail.dto.ts | 2 +- .../immich/api-v1/asset/dto/serve-file.dto.ts | 2 +- .../validation/file-not-empty-validator.ts | 21 -- .../api-v1/validation/parse-me-uuid-pipe.ts | 11 - server/src/immich/app.service.ts | 2 +- server/src/immich/app.utils.ts | 2 +- .../immich/controllers/activity.controller.ts | 2 +- .../immich/controllers/album.controller.ts | 3 +- .../immich/controllers/api-key.controller.ts | 2 +- .../immich/controllers/asset.controller.ts | 2 +- .../src/immich/controllers/auth.controller.ts | 2 +- .../immich/controllers/download.controller.ts | 2 +- .../immich/controllers/dto/uuid-param.dto.ts | 9 - .../src/immich/controllers/face.controller.ts | 2 +- .../immich/controllers/library.controller.ts | 2 +- .../immich/controllers/partner.controller.ts | 2 +- .../immich/controllers/person.controller.ts | 2 +- .../controllers/shared-link.controller.ts | 2 +- .../src/immich/controllers/tag.controller.ts | 2 +- .../src/immich/controllers/user.controller.ts | 2 +- .../immich/interceptors/error.interceptor.ts | 2 +- server/src/immich/main.ts | 2 +- server/src/infra/infra.module.ts | 3 +- server/src/infra/infra.util.ts | 30 -- server/src/infra/infra.utils.ts | 80 +---- server/src/infra/instrumentation.ts | 4 +- .../infra/repositories/access.repository.ts | 3 +- .../infra/repositories/activity.repository.ts | 2 +- .../infra/repositories/album.repository.ts | 5 +- .../infra/repositories/api-key.repository.ts | 2 +- .../infra/repositories/asset.repository.ts | 13 +- .../infra/repositories/database.repository.ts | 2 +- .../src/infra/repositories/job.repository.ts | 2 +- .../infra/repositories/library.repository.ts | 2 +- .../infra/repositories/media.repository.ts | 2 +- .../infra/repositories/metadata.repository.ts | 2 +- .../src/infra/repositories/move.repository.ts | 2 +- .../infra/repositories/person.repository.ts | 6 +- .../infra/repositories/search.repository.ts | 7 +- .../repositories/shared-link.repository.ts | 2 +- .../repositories/system-config.repository.ts | 3 +- .../repositories/user-token.repository.ts | 2 +- .../src/infra/repositories/user.repository.ts | 2 +- server/src/infra/sql-generator/index.ts | 2 +- .../microservices/utils/exif/coordinates.ts | 26 -- .../src/microservices/utils/numbers.spec.ts | 47 --- server/src/microservices/utils/numbers.ts | 19 -- .../coordinates.spec.ts => utils.spec.ts} | 48 ++- server/src/utils.ts | 181 +++++++++++ server/src/validation.ts | 164 ++++++++++ 119 files changed, 666 insertions(+), 684 deletions(-) rename server/src/{infra/infra.config.ts => config.ts} (50%) create mode 100644 server/src/decorators.ts delete mode 100644 server/src/domain/domain.config.ts delete mode 100644 server/src/domain/domain.util.ts delete mode 100644 server/src/immich/api-v1/validation/file-not-empty-validator.ts delete mode 100644 server/src/immich/api-v1/validation/parse-me-uuid-pipe.ts delete mode 100644 server/src/immich/controllers/dto/uuid-param.dto.ts delete mode 100644 server/src/infra/infra.util.ts delete mode 100644 server/src/microservices/utils/exif/coordinates.ts delete mode 100644 server/src/microservices/utils/numbers.spec.ts delete mode 100644 server/src/microservices/utils/numbers.ts rename server/src/{microservices/utils/exif/coordinates.spec.ts => utils.spec.ts} (53%) create mode 100644 server/src/utils.ts create mode 100644 server/src/validation.ts diff --git a/server/src/infra/infra.config.ts b/server/src/config.ts similarity index 50% rename from server/src/infra/infra.config.ts rename to server/src/config.ts index f521b96b7..01f3f1a1c 100644 --- a/server/src/infra/infra.config.ts +++ b/server/src/config.ts @@ -1,7 +1,42 @@ import { RegisterQueueOptions } from '@nestjs/bullmq'; +import { ConfigModuleOptions } from '@nestjs/config'; import { QueueOptions } from 'bullmq'; import { RedisOptions } from 'ioredis'; +import Joi from 'joi'; import { QueueName } from 'src/domain/job/job.constants'; +import { LogLevel } from 'src/infra/entities/system-config.entity'; + +const WHEN_DB_URL_SET = Joi.when('DB_URL', { + is: Joi.exist(), + then: Joi.string().optional(), + otherwise: Joi.string().required(), +}); + +export const immichAppConfig: ConfigModuleOptions = { + envFilePath: '.env', + isGlobal: true, + validationSchema: Joi.object({ + NODE_ENV: Joi.string().optional().valid('development', 'production', 'staging').default('development'), + LOG_LEVEL: Joi.string() + .optional() + .valid(...Object.values(LogLevel)), + + DB_USERNAME: WHEN_DB_URL_SET, + DB_PASSWORD: WHEN_DB_URL_SET, + DB_DATABASE_NAME: WHEN_DB_URL_SET, + DB_URL: Joi.string().optional(), + DB_VECTOR_EXTENSION: Joi.string().optional().valid('pgvector', 'pgvecto.rs').default('pgvecto.rs'), + + MACHINE_LEARNING_PORT: Joi.number().optional(), + MICROSERVICES_PORT: Joi.number().optional(), + IMMICH_METRICS_PORT: Joi.number().optional(), + + IMMICH_METRICS: Joi.boolean().optional().default(false), + IMMICH_HOST_METRICS: Joi.boolean().optional().default(false), + IMMICH_API_METRICS: Joi.boolean().optional().default(false), + IMMICH_IO_METRICS: Joi.boolean().optional().default(false), + }), +}; function parseRedisConfig(): RedisOptions { const redisUrl = process.env.REDIS_URL; diff --git a/server/src/decorators.ts b/server/src/decorators.ts new file mode 100644 index 000000000..06dc0bfdc --- /dev/null +++ b/server/src/decorators.ts @@ -0,0 +1,124 @@ +import { SetMetadata } from '@nestjs/common'; +import _ from 'lodash'; +import { setUnion } from 'src/utils'; + +// PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the +// maximum number of parameters is 65535. Any query that tries to bind more than that (e.g. searching +// by a list of IDs) requires splitting the query into multiple chunks. +// We are rounding down this limit, as queries commonly include other filters and parameters. +export const DATABASE_PARAMETER_CHUNK_SIZE = 65_500; + +/** + * Chunks an array or set into smaller collections of the same type and specified size. + * + * @param collection The collection to chunk. + * @param size The size of each chunk. + */ +function chunks(collection: Array, size: number): Array>; +function chunks(collection: Set, size: number): Array>; +function chunks(collection: Array | Set, size: number): Array> | Array> { + if (collection instanceof Set) { + const result = []; + let chunk = new Set(); + for (const element of collection) { + chunk.add(element); + if (chunk.size === size) { + result.push(chunk); + chunk = new Set(); + } + } + if (chunk.size > 0) { + result.push(chunk); + } + return result; + } else { + return _.chunk(collection, size); + } +} + +/** + * Wraps a method that takes a collection of parameters and sequentially calls it with chunks of the collection, + * to overcome the maximum number of parameters allowed by the database driver. + * + * @param options.paramIndex The index of the function parameter to chunk. Defaults to 0. + * @param options.flatten Whether to flatten the results. Defaults to false. + */ +export function Chunked(options: { paramIndex?: number; mergeFn?: (results: any) => any } = {}): MethodDecorator { + return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => { + const originalMethod = descriptor.value; + const parameterIndex = options.paramIndex ?? 0; + descriptor.value = async function (...arguments_: any[]) { + const argument = arguments_[parameterIndex]; + + // Early return if argument length is less than or equal to the chunk size. + if ( + (Array.isArray(argument) && argument.length <= DATABASE_PARAMETER_CHUNK_SIZE) || + (argument instanceof Set && argument.size <= DATABASE_PARAMETER_CHUNK_SIZE) + ) { + return await originalMethod.apply(this, arguments_); + } + + return Promise.all( + chunks(argument, DATABASE_PARAMETER_CHUNK_SIZE).map(async (chunk) => { + await Reflect.apply(originalMethod, this, [ + ...arguments_.slice(0, parameterIndex), + chunk, + ...arguments_.slice(parameterIndex + 1), + ]); + }), + ).then((results) => (options.mergeFn ? options.mergeFn(results) : results)); + }; + }; +} + +export function ChunkedArray(options?: { paramIndex?: number }): MethodDecorator { + return Chunked({ ...options, mergeFn: _.flatten }); +} + +export function ChunkedSet(options?: { paramIndex?: number }): MethodDecorator { + return Chunked({ ...options, mergeFn: setUnion }); +} + +// https://stackoverflow.com/a/74898678 +export function DecorateAll( + decorator: ( + target: any, + propertyKey: string, + descriptor: TypedPropertyDescriptor, + ) => TypedPropertyDescriptor | void, +) { + return (target: any) => { + const descriptors = Object.getOwnPropertyDescriptors(target.prototype); + for (const [propName, descriptor] of Object.entries(descriptors)) { + const isMethod = typeof descriptor.value == 'function' && propName !== 'constructor'; + if (!isMethod) { + continue; + } + decorator({ ...target, constructor: { ...target.constructor, name: target.name } as any }, propName, descriptor); + Object.defineProperty(target.prototype, propName, descriptor); + } + }; +} + +const UUID = '00000000-0000-4000-a000-000000000000'; + +export const DummyValue = { + UUID, + UUID_SET: new Set([UUID]), + PAGINATION: { take: 10, skip: 0 }, + EMAIL: 'user@immich.app', + STRING: 'abcdefghi', + BUFFER: Buffer.from('abcdefghi'), + DATE: new Date(), + TIME_BUCKET: '2024-01-01T00:00:00.000Z', +}; + +export const GENERATE_SQL_KEY = 'generate-sql-key'; + +export interface GenerateSqlQueries { + name?: string; + params: unknown[]; +} + +/** Decorator to enable versioning/tracking of generated Sql */ +export const GenerateSql = (...options: GenerateSqlQueries[]) => SetMetadata(GENERATE_SQL_KEY, options); diff --git a/server/src/domain/access/access.core.ts b/server/src/domain/access/access.core.ts index a51412856..eb4ff55d1 100644 --- a/server/src/domain/access/access.core.ts +++ b/server/src/domain/access/access.core.ts @@ -1,8 +1,8 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { setDifference, setIsEqual, setUnion } from 'src/domain/domain.util'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { setDifference, setIsEqual, setUnion } from 'src/utils'; export enum Permission { ACTIVITY_CREATE = 'activity.create', diff --git a/server/src/domain/activity/activity.dto.ts b/server/src/domain/activity/activity.dto.ts index 627a06c42..1bfbabd80 100644 --- a/server/src/domain/activity/activity.dto.ts +++ b/server/src/domain/activity/activity.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString, ValidateIf } from 'class-validator'; -import { Optional, ValidateUUID } from 'src/domain/domain.util'; import { UserDto, mapSimpleUser } from 'src/domain/user/response-dto/user-response.dto'; import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { Optional, ValidateUUID } from 'src/validation'; export enum ReactionType { COMMENT = 'comment', diff --git a/server/src/domain/album/album-response.dto.ts b/server/src/domain/album/album-response.dto.ts index ab8454a49..663a463f2 100644 --- a/server/src/domain/album/album-response.dto.ts +++ b/server/src/domain/album/album-response.dto.ts @@ -1,9 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { Optional } from 'src/domain/domain.util'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { AlbumEntity, AssetOrder } from 'src/infra/entities/album.entity'; +import { Optional } from 'src/validation'; export class AlbumResponseDto { id!: string; diff --git a/server/src/domain/album/album.service.ts b/server/src/domain/album/album.service.ts index 7ba91f1d9..d54680fe4 100644 --- a/server/src/domain/album/album.service.ts +++ b/server/src/domain/album/album.service.ts @@ -14,7 +14,6 @@ import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { setUnion } from 'src/domain/domain.util'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/domain/repositories/album.repository'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; @@ -22,6 +21,7 @@ import { IUserRepository } from 'src/domain/repositories/user.repository'; import { AlbumEntity } from 'src/infra/entities/album.entity'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { UserEntity } from 'src/infra/entities/user.entity'; +import { setUnion } from 'src/utils'; @Injectable() export class AlbumService { diff --git a/server/src/domain/album/dto/album-add-users.dto.ts b/server/src/domain/album/dto/album-add-users.dto.ts index b6a9e8be9..1a6be4823 100644 --- a/server/src/domain/album/dto/album-add-users.dto.ts +++ b/server/src/domain/album/dto/album-add-users.dto.ts @@ -1,5 +1,5 @@ import { ArrayNotEmpty } from 'class-validator'; -import { ValidateUUID } from 'src/domain/domain.util'; +import { ValidateUUID } from 'src/validation'; export class AddUsersDto { @ValidateUUID({ each: true }) diff --git a/server/src/domain/album/dto/album-create.dto.ts b/server/src/domain/album/dto/album-create.dto.ts index 0765e4d77..1b4a75332 100644 --- a/server/src/domain/album/dto/album-create.dto.ts +++ b/server/src/domain/album/dto/album-create.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsString } from 'class-validator'; -import { Optional, ValidateUUID } from 'src/domain/domain.util'; +import { Optional, ValidateUUID } from 'src/validation'; export class CreateAlbumDto { @IsString() diff --git a/server/src/domain/album/dto/album-update.dto.ts b/server/src/domain/album/dto/album-update.dto.ts index c6b21e08d..1f329cb3c 100644 --- a/server/src/domain/album/dto/album-update.dto.ts +++ b/server/src/domain/album/dto/album-update.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; import { AssetOrder } from 'src/infra/entities/album.entity'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class UpdateAlbumDto { @Optional() diff --git a/server/src/domain/album/dto/album.dto.ts b/server/src/domain/album/dto/album.dto.ts index f1772b4c2..fe0eb0d5c 100644 --- a/server/src/domain/album/dto/album.dto.ts +++ b/server/src/domain/album/dto/album.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class AlbumInfoDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/album/dto/get-albums.dto.ts b/server/src/domain/album/dto/get-albums.dto.ts index e03c219aa..15e4f1cf2 100644 --- a/server/src/domain/album/dto/get-albums.dto.ts +++ b/server/src/domain/album/dto/get-albums.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; +import { ValidateBoolean, ValidateUUID } from 'src/validation'; export class GetAlbumsDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/api-key/api-key.dto.ts b/server/src/domain/api-key/api-key.dto.ts index 19099ba18..1f4f85521 100644 --- a/server/src/domain/api-key/api-key.dto.ts +++ b/server/src/domain/api-key/api-key.dto.ts @@ -1,5 +1,5 @@ import { IsNotEmpty, IsString } from 'class-validator'; -import { Optional } from 'src/domain/domain.util'; +import { Optional } from 'src/validation'; export class APIKeyCreateDto { @IsString() @IsNotEmpty() diff --git a/server/src/domain/asset/asset.service.ts b/server/src/domain/asset/asset.service.ts index 3d78c8c7b..2d514a937 100644 --- a/server/src/domain/asset/asset.service.ts +++ b/server/src/domain/asset/asset.service.ts @@ -21,7 +21,6 @@ import { MapMarkerResponseDto } from 'src/domain/asset/response-dto/map-marker-r import { TimeBucketResponseDto } from 'src/domain/asset/response-dto/time-bucket-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; -import { usePagination } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; import { IAssetDeletionJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; @@ -38,6 +37,7 @@ import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { usePagination } from 'src/utils'; export enum UploadFieldName { ASSET_DATA = 'assetData', diff --git a/server/src/domain/asset/dto/asset-ids.dto.ts b/server/src/domain/asset/dto/asset-ids.dto.ts index ae236f13d..ea875e85e 100644 --- a/server/src/domain/asset/dto/asset-ids.dto.ts +++ b/server/src/domain/asset/dto/asset-ids.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; -import { ValidateUUID } from 'src/domain/domain.util'; +import { ValidateUUID } from 'src/validation'; export class AssetIdsDto { @ValidateUUID({ each: true }) diff --git a/server/src/domain/asset/dto/asset-stack.dto.ts b/server/src/domain/asset/dto/asset-stack.dto.ts index e05bf6a0b..3ff04ee5e 100644 --- a/server/src/domain/asset/dto/asset-stack.dto.ts +++ b/server/src/domain/asset/dto/asset-stack.dto.ts @@ -1,4 +1,4 @@ -import { ValidateUUID } from 'src/domain/domain.util'; +import { ValidateUUID } from 'src/validation'; export class UpdateStackParentDto { @ValidateUUID() diff --git a/server/src/domain/asset/dto/asset-statistics.dto.ts b/server/src/domain/asset/dto/asset-statistics.dto.ts index 9d935789a..7694955c2 100644 --- a/server/src/domain/asset/dto/asset-statistics.dto.ts +++ b/server/src/domain/asset/dto/asset-statistics.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; -import { ValidateBoolean } from 'src/domain/domain.util'; import { AssetStats } from 'src/domain/repositories/asset.repository'; import { AssetType } from 'src/infra/entities/asset.entity'; +import { ValidateBoolean } from 'src/validation'; export class AssetStatsDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/asset/dto/asset.dto.ts b/server/src/domain/asset/dto/asset.dto.ts index 31eaa916e..a93a59ae3 100644 --- a/server/src/domain/asset/dto/asset.dto.ts +++ b/server/src/domain/asset/dto/asset.dto.ts @@ -10,7 +10,7 @@ import { ValidateIf, } from 'class-validator'; import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { Optional, ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class DeviceIdDto { @IsNotEmpty() diff --git a/server/src/domain/asset/dto/map-marker.dto.ts b/server/src/domain/asset/dto/map-marker.dto.ts index f06dc201e..158750e51 100644 --- a/server/src/domain/asset/dto/map-marker.dto.ts +++ b/server/src/domain/asset/dto/map-marker.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean, ValidateDate } from 'src/domain/domain.util'; +import { ValidateBoolean, ValidateDate } from 'src/validation'; export class MapMarkerDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/asset/dto/time-bucket.dto.ts b/server/src/domain/asset/dto/time-bucket.dto.ts index 052e3732e..c9e104256 100644 --- a/server/src/domain/asset/dto/time-bucket.dto.ts +++ b/server/src/domain/asset/dto/time-bucket.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; import { TimeBucketSize } from 'src/domain/repositories/asset.repository'; import { AssetOrder } from 'src/infra/entities/album.entity'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class TimeBucketDto { @IsNotEmpty() diff --git a/server/src/domain/asset/response-dto/asset-ids-response.dto.ts b/server/src/domain/asset/response-dto/asset-ids-response.dto.ts index 3a7e8129a..fdc9942e3 100644 --- a/server/src/domain/asset/response-dto/asset-ids-response.dto.ts +++ b/server/src/domain/asset/response-dto/asset-ids-response.dto.ts @@ -1,4 +1,4 @@ -import { ValidateUUID } from 'src/domain/domain.util'; +import { ValidateUUID } from 'src/validation'; /** @deprecated Use `BulkIdResponseDto` instead */ export enum AssetIdErrorReason { diff --git a/server/src/domain/audit/audit.dto.ts b/server/src/domain/audit/audit.dto.ts index 131ce147b..1c34e9491 100644 --- a/server/src/domain/audit/audit.dto.ts +++ b/server/src/domain/audit/audit.dto.ts @@ -1,9 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsEnum, IsString, IsUUID, ValidateNested } from 'class-validator'; -import { Optional, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; import { EntityType } from 'src/infra/entities/audit.entity'; import { AssetPathType, PathType, PersonPathType, UserPathType } from 'src/infra/entities/move.entity'; +import { Optional, ValidateDate, ValidateUUID } from 'src/validation'; const PathEnum = Object.values({ ...AssetPathType, ...PersonPathType, ...UserPathType }); diff --git a/server/src/domain/audit/audit.service.ts b/server/src/domain/audit/audit.service.ts index 0bcb2ed15..c72d1d8cf 100644 --- a/server/src/domain/audit/audit.service.ts +++ b/server/src/domain/audit/audit.service.ts @@ -12,7 +12,6 @@ import { } from 'src/domain/audit/audit.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { AUDIT_LOG_MAX_DURATION } from 'src/domain/domain.constant'; -import { usePagination } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; @@ -26,6 +25,7 @@ import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; import { DatabaseAction } from 'src/infra/entities/audit.entity'; import { AssetPathType, PersonPathType, UserPathType } from 'src/infra/entities/move.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { usePagination } from 'src/utils'; @Injectable() export class AuditService { diff --git a/server/src/domain/auth/auth.service.ts b/server/src/domain/auth/auth.service.ts index bb01e1b3b..e66a6d0d7 100644 --- a/server/src/domain/auth/auth.service.ts +++ b/server/src/domain/auth/auth.service.ts @@ -34,7 +34,6 @@ import { mapLoginResponse, mapUserToken, } from 'src/domain/auth/auth.dto'; -import { HumanReadableSize } from 'src/domain/domain.util'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; @@ -49,6 +48,7 @@ import { UserCore } from 'src/domain/user/user.core'; import { SystemConfig } from 'src/infra/entities/system-config.entity'; import { UserEntity } from 'src/infra/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { HumanReadableSize } from 'src/utils'; export interface LoginDetails { isSecure: boolean; diff --git a/server/src/domain/domain.config.ts b/server/src/domain/domain.config.ts deleted file mode 100644 index 40580b8e4..000000000 --- a/server/src/domain/domain.config.ts +++ /dev/null @@ -1,36 +0,0 @@ -// TODO: remove nestjs references from domain -import { ConfigModuleOptions } from '@nestjs/config'; -import Joi from 'joi'; -import { LogLevel } from 'src/infra/entities/system-config.entity'; - -const WHEN_DB_URL_SET = Joi.when('DB_URL', { - is: Joi.exist(), - then: Joi.string().optional(), - otherwise: Joi.string().required(), -}); - -export const immichAppConfig: ConfigModuleOptions = { - envFilePath: '.env', - isGlobal: true, - validationSchema: Joi.object({ - NODE_ENV: Joi.string().optional().valid('development', 'production', 'staging').default('development'), - LOG_LEVEL: Joi.string() - .optional() - .valid(...Object.values(LogLevel)), - - DB_USERNAME: WHEN_DB_URL_SET, - DB_PASSWORD: WHEN_DB_URL_SET, - DB_DATABASE_NAME: WHEN_DB_URL_SET, - DB_URL: Joi.string().optional(), - DB_VECTOR_EXTENSION: Joi.string().optional().valid('pgvector', 'pgvecto.rs').default('pgvecto.rs'), - - MACHINE_LEARNING_PORT: Joi.number().optional(), - MICROSERVICES_PORT: Joi.number().optional(), - IMMICH_METRICS_PORT: Joi.number().optional(), - - IMMICH_METRICS: Joi.boolean().optional().default(false), - IMMICH_HOST_METRICS: Joi.boolean().optional().default(false), - IMMICH_API_METRICS: Joi.boolean().optional().default(false), - IMMICH_IO_METRICS: Joi.boolean().optional().default(false), - }), -}; diff --git a/server/src/domain/domain.util.ts b/server/src/domain/domain.util.ts deleted file mode 100644 index 820c17f3f..000000000 --- a/server/src/domain/domain.util.ts +++ /dev/null @@ -1,280 +0,0 @@ -import { BadRequestException, applyDecorators } from '@nestjs/common'; -import { ApiProperty } from '@nestjs/swagger'; -import { Transform } from 'class-transformer'; -import { - IsArray, - IsBoolean, - IsDate, - IsNotEmpty, - IsOptional, - IsString, - IsUUID, - ValidateIf, - ValidationOptions, - isDateString, -} from 'class-validator'; -import { CronJob } from 'cron'; -import _ from 'lodash'; -import { basename, extname } from 'node:path'; -import sanitize from 'sanitize-filename'; -import { ImmichLogger } from 'src/infra/logger'; - -export enum CacheControl { - PRIVATE_WITH_CACHE = 'private_with_cache', - PRIVATE_WITHOUT_CACHE = 'private_without_cache', - NONE = 'none', -} - -export class ImmichFileResponse { - public readonly path!: string; - public readonly contentType!: string; - public readonly cacheControl!: CacheControl; - - constructor(response: ImmichFileResponse) { - Object.assign(this, response); - } -} - -export interface OpenGraphTags { - title: string; - description: string; - imageUrl?: string; -} - -export const isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED'; - -type UUIDOptions = { optional?: boolean; each?: boolean }; -export const ValidateUUID = (options?: UUIDOptions) => { - const { optional, each } = { optional: false, each: false, ...options }; - return applyDecorators( - IsUUID('4', { each }), - ApiProperty({ format: 'uuid' }), - optional ? Optional() : IsNotEmpty(), - each ? IsArray() : IsString(), - ); -}; - -type DateOptions = { optional?: boolean; nullable?: boolean; format?: 'date' | 'date-time' }; -export const ValidateDate = (options?: DateOptions) => { - const { optional, nullable, format } = { optional: false, nullable: false, format: 'date-time', ...options }; - - const decorators = [ - ApiProperty({ format }), - IsDate(), - optional ? Optional({ nullable: true }) : IsNotEmpty(), - Transform(({ key, value }) => { - if (value === null || value === undefined) { - return value; - } - - if (!isDateString(value)) { - throw new BadRequestException(`${key} must be a date string`); - } - - return new Date(value as string); - }), - ]; - - if (optional) { - decorators.push(Optional({ nullable })); - } - - return applyDecorators(...decorators); -}; - -type BooleanOptions = { optional?: boolean }; -export const ValidateBoolean = (options?: BooleanOptions) => { - const { optional } = { optional: false, ...options }; - const decorators = [ - // ApiProperty(), - IsBoolean(), - Transform(({ value }) => { - if (value == 'true') { - return true; - } else if (value == 'false') { - return false; - } - return value; - }), - ]; - - if (optional) { - decorators.push(Optional()); - } - - return applyDecorators(...decorators); -}; - -export function validateCronExpression(expression: string) { - try { - new CronJob(expression, () => {}); - } catch { - return false; - } - - return true; -} - -type IValue = { value: string }; - -export const toEmail = ({ value }: IValue) => value?.toLowerCase(); - -export const toSanitized = ({ value }: IValue) => sanitize((value || '').replaceAll('.', '')); - -export function getFileNameWithoutExtension(path: string): string { - return basename(path, extname(path)); -} - -export function getLivePhotoMotionFilename(stillName: string, motionName: string) { - return getFileNameWithoutExtension(stillName) + extname(motionName); -} - -const KiB = Math.pow(1024, 1); -const MiB = Math.pow(1024, 2); -const GiB = Math.pow(1024, 3); -const TiB = Math.pow(1024, 4); -const PiB = Math.pow(1024, 5); - -export const HumanReadableSize = { KiB, MiB, GiB, TiB, PiB }; - -export function asHumanReadable(bytes: number, precision = 1): string { - const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']; - - let magnitude = 0; - let remainder = bytes; - while (remainder >= 1024) { - if (magnitude + 1 < units.length) { - magnitude++; - remainder /= 1024; - } else { - break; - } - } - - return `${remainder.toFixed(magnitude == 0 ? 0 : precision)} ${units[magnitude]}`; -} - -export interface PaginationOptions { - take: number; - skip?: number; -} - -export enum PaginationMode { - LIMIT_OFFSET = 'limit-offset', - SKIP_TAKE = 'skip-take', -} - -export interface PaginatedBuilderOptions { - take: number; - skip?: number; - mode?: PaginationMode; -} - -export interface PaginationResult { - items: T[]; - hasNextPage: boolean; -} - -export type Paginated = Promise>; - -export async function* usePagination( - pageSize: number, - getNextPage: (pagination: PaginationOptions) => PaginationResult | Paginated, -) { - let hasNextPage = true; - - for (let skip = 0; hasNextPage; skip += pageSize) { - const result = await getNextPage({ take: pageSize, skip }); - hasNextPage = result.hasNextPage; - yield result.items; - } -} - -export interface OptionalOptions extends ValidationOptions { - nullable?: boolean; -} - -/** - * Checks if value is missing and if so, ignores all validators. - * - * @param validationOptions {@link OptionalOptions} - * - * @see IsOptional exported from `class-validator. - */ -// https://stackoverflow.com/a/71353929 -export function Optional({ nullable, ...validationOptions }: OptionalOptions = {}) { - if (nullable === true) { - return IsOptional(validationOptions); - } - - return ValidateIf((object: any, v: any) => v !== undefined, validationOptions); -} - -/** - * Chunks an array or set into smaller collections of the same type and specified size. - * - * @param collection The collection to chunk. - * @param size The size of each chunk. - */ -export function chunks(collection: Array, size: number): Array>; -export function chunks(collection: Set, size: number): Array>; -export function chunks(collection: Array | Set, size: number): Array> | Array> { - if (collection instanceof Set) { - const result = []; - let chunk = new Set(); - for (const element of collection) { - chunk.add(element); - if (chunk.size === size) { - result.push(chunk); - chunk = new Set(); - } - } - if (chunk.size > 0) { - result.push(chunk); - } - return result; - } else { - return _.chunk(collection, size); - } -} - -// NOTE: The following Set utils have been added here, to easily determine where they are used. -// They should be replaced with native Set operations, when they are added to the language. -// Proposal reference: https://github.com/tc39/proposal-set-methods - -export const setUnion = (...sets: Set[]): Set => { - const union = new Set(sets[0]); - for (const set of sets.slice(1)) { - for (const element of set) { - union.add(element); - } - } - return union; -}; - -export const setDifference = (setA: Set, ...sets: Set[]): Set => { - const difference = new Set(setA); - for (const set of sets) { - for (const element of set) { - difference.delete(element); - } - } - return difference; -}; - -export const setIsSuperset = (set: Set, subset: Set): boolean => { - for (const element of subset) { - if (!set.has(element)) { - return false; - } - } - return true; -}; - -export const setIsEqual = (setA: Set, setB: Set): boolean => { - return setA.size === setB.size && setIsSuperset(setA, setB); -}; - -export const handlePromiseError = (promise: Promise, logger: ImmichLogger): void => { - promise.catch((error: Error | any) => logger.error(`Promise error: ${error}`, error?.stack)); -}; diff --git a/server/src/domain/download/download.dto.ts b/server/src/domain/download/download.dto.ts index e350d66ac..e6588a994 100644 --- a/server/src/domain/download/download.dto.ts +++ b/server/src/domain/download/download.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsInt, IsPositive } from 'class-validator'; -import { Optional, ValidateUUID } from 'src/domain/domain.util'; +import { Optional, ValidateUUID } from 'src/validation'; export class DownloadInfoDto { @ValidateUUID({ each: true, optional: true }) diff --git a/server/src/domain/download/download.service.spec.ts b/server/src/domain/download/download.service.spec.ts index d22ce69e8..7c3ecbb02 100644 --- a/server/src/domain/download/download.service.spec.ts +++ b/server/src/domain/download/download.service.spec.ts @@ -1,10 +1,10 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; -import { CacheControl, ImmichFileResponse } from 'src/domain/domain.util'; import { DownloadResponseDto } from 'src/domain/download/download.dto'; import { DownloadService } from 'src/domain/download/download.service'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { CacheControl, ImmichFileResponse } from 'src/utils'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; diff --git a/server/src/domain/download/download.service.ts b/server/src/domain/download/download.service.ts index b069ac9b3..13f513c9b 100644 --- a/server/src/domain/download/download.service.ts +++ b/server/src/domain/download/download.service.ts @@ -4,12 +4,12 @@ import { AccessCore, Permission } from 'src/domain/access/access.core'; import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; -import { CacheControl, HumanReadableSize, ImmichFileResponse, usePagination } from 'src/domain/domain.util'; import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/download.dto'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; import { IStorageRepository, ImmichReadStream } from 'src/domain/repositories/storage.repository'; import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { CacheControl, HumanReadableSize, ImmichFileResponse, usePagination } from 'src/utils'; @Injectable() export class DownloadService { diff --git a/server/src/domain/job/job.dto.ts b/server/src/domain/job/job.dto.ts index f551ab961..fd463a9b0 100644 --- a/server/src/domain/job/job.dto.ts +++ b/server/src/domain/job/job.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty } from 'class-validator'; -import { ValidateBoolean } from 'src/domain/domain.util'; import { JobCommand, QueueName } from 'src/domain/job/job.constants'; +import { ValidateBoolean } from 'src/validation'; export class JobIdParamDto { @IsNotEmpty() diff --git a/server/src/domain/library/library.dto.ts b/server/src/domain/library/library.dto.ts index 26faf4340..f65779fb8 100644 --- a/server/src/domain/library/library.dto.ts +++ b/server/src/domain/library/library.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { ArrayMaxSize, ArrayUnique, IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateUUID } from 'src/domain/domain.util'; import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class CreateLibraryDto { @IsEnum(LibraryType) diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts index 7ad781f28..46b4d11f5 100644 --- a/server/src/domain/library/library.service.ts +++ b/server/src/domain/library/library.service.ts @@ -7,7 +7,6 @@ import { Stats } from 'node:fs'; import path, { basename, parse } from 'node:path'; import picomatch from 'picomatch'; import { mimeTypes } from 'src/domain/domain.constant'; -import { handlePromiseError, usePagination, validateCronExpression } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob, ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; import { @@ -35,6 +34,8 @@ import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetType } from 'src/infra/entities/asset.entity'; import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { handlePromiseError, usePagination } from 'src/utils'; +import { validateCronExpression } from 'src/validation'; const LIBRARY_SCAN_BATCH_SIZE = 5000; diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index bb0c2503d..f06f9ed28 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -1,5 +1,4 @@ import { Inject, Injectable, UnsupportedMediaTypeException } from '@nestjs/common'; -import { usePagination } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; import { @@ -39,6 +38,7 @@ import { VideoCodec, } from 'src/infra/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { usePagination } from 'src/utils'; @Injectable() export class MediaService { diff --git a/server/src/domain/metadata/metadata.service.ts b/server/src/domain/metadata/metadata.service.ts index 4f45b9853..360f916ac 100644 --- a/server/src/domain/metadata/metadata.service.ts +++ b/server/src/domain/metadata/metadata.service.ts @@ -6,7 +6,6 @@ import { Duration } from 'luxon'; import { constants } from 'node:fs/promises'; import path from 'node:path'; import { Subscription } from 'rxjs'; -import { handlePromiseError, usePagination } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; import { IAlbumRepository } from 'src/domain/repositories/album.repository'; @@ -26,6 +25,7 @@ import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-c import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { handlePromiseError, usePagination } from 'src/utils'; /** look for a date from these tags (in order) */ const EXIF_DATE_TAGS: Array = [ diff --git a/server/src/domain/person/person.dto.ts b/server/src/domain/person/person.dto.ts index 9ac66332f..f3699499a 100644 --- a/server/src/domain/person/person.dto.ts +++ b/server/src/domain/person/person.dto.ts @@ -2,9 +2,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsNotEmpty, IsString, MaxDate, ValidateNested } from 'class-validator'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; export class PersonCreateDto { /** diff --git a/server/src/domain/person/person.service.spec.ts b/server/src/domain/person/person.service.spec.ts index b0aa3c33a..a4b1282d3 100644 --- a/server/src/domain/person/person.service.spec.ts +++ b/server/src/domain/person/person.service.spec.ts @@ -1,6 +1,5 @@ import { BadRequestException, NotFoundException } from '@nestjs/common'; import { BulkIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { CacheControl, ImmichFileResponse } from 'src/domain/domain.util'; import { JobName } from 'src/domain/job/job.constants'; import { PersonResponseDto, mapFaces, mapPerson } from 'src/domain/person/person.dto'; import { PersonService } from 'src/domain/person/person.service'; @@ -16,6 +15,7 @@ import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; import { Colorspace, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { CacheControl, ImmichFileResponse } from 'src/utils'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { faceStub } from 'test/fixtures/face.stub'; diff --git a/server/src/domain/person/person.service.ts b/server/src/domain/person/person.service.ts index 1928191a3..46538e04f 100644 --- a/server/src/domain/person/person.service.ts +++ b/server/src/domain/person/person.service.ts @@ -4,7 +4,6 @@ import { BulkIdErrorReason, BulkIdResponseDto } from 'src/domain/asset/response- import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; -import { CacheControl, ImmichFileResponse, usePagination } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IDeferrableJob, IEntityJob } from 'src/domain/job/job.interface'; import { FACE_THUMBNAIL_SIZE } from 'src/domain/media/media.constant'; @@ -39,6 +38,7 @@ import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { PersonPathType } from 'src/infra/entities/move.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { CacheControl, ImmichFileResponse, usePagination } from 'src/utils'; import { IsNull } from 'typeorm'; @Injectable() diff --git a/server/src/domain/repositories/asset.repository.ts b/server/src/domain/repositories/asset.repository.ts index e8bbdeb38..336db8d70 100644 --- a/server/src/domain/repositories/asset.repository.ts +++ b/server/src/domain/repositories/asset.repository.ts @@ -1,10 +1,10 @@ -import { Paginated, PaginationOptions } from 'src/domain/domain.util'; import { ReverseGeocodeResult } from 'src/domain/repositories/metadata.repository'; import { AssetSearchOptions, SearchExploreItem } from 'src/domain/repositories/search.repository'; import { AssetOrder } from 'src/infra/entities/album.entity'; import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { Paginated, PaginationOptions } from 'src/utils'; import { FindOptionsRelations, FindOptionsSelect } from 'typeorm'; export type AssetStats = Record; diff --git a/server/src/domain/repositories/person.repository.ts b/server/src/domain/repositories/person.repository.ts index 93787f7b9..f00fce44e 100644 --- a/server/src/domain/repositories/person.repository.ts +++ b/server/src/domain/repositories/person.repository.ts @@ -1,7 +1,7 @@ -import { Paginated, PaginationOptions } from 'src/domain/domain.util'; import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; +import { Paginated, PaginationOptions } from 'src/utils'; import { FindManyOptions, FindOptionsRelations, FindOptionsSelect } from 'typeorm'; export const IPersonRepository = 'IPersonRepository'; diff --git a/server/src/domain/repositories/search.repository.ts b/server/src/domain/repositories/search.repository.ts index 3dc9c1ea5..a54147f1f 100644 --- a/server/src/domain/repositories/search.repository.ts +++ b/server/src/domain/repositories/search.repository.ts @@ -1,8 +1,8 @@ -import { Paginated } from 'src/domain/domain.util'; import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { Paginated } from 'src/utils'; export const ISearchRepository = 'ISearchRepository'; diff --git a/server/src/domain/search/dto/search-suggestion.dto.ts b/server/src/domain/search/dto/search-suggestion.dto.ts index f2f70062a..f702293d0 100644 --- a/server/src/domain/search/dto/search-suggestion.dto.ts +++ b/server/src/domain/search/dto/search-suggestion.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional } from 'src/domain/domain.util'; +import { Optional } from 'src/validation'; export enum SearchSuggestionType { COUNTRY = 'country', diff --git a/server/src/domain/search/dto/search.dto.ts b/server/src/domain/search/dto/search.dto.ts index 0dcaa22fb..52090b945 100644 --- a/server/src/domain/search/dto/search.dto.ts +++ b/server/src/domain/search/dto/search.dto.ts @@ -1,10 +1,10 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsInt, IsNotEmpty, IsString, Max, Min } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; import { AssetOrder } from 'src/infra/entities/album.entity'; import { AssetType } from 'src/infra/entities/asset.entity'; import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; class BaseSearchDto { @ValidateUUID({ optional: true }) diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index 77c675b87..3ceb3039d 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -1,7 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; import { Version, isDev, mimeTypes, serverVersion } from 'src/domain/domain.constant'; -import { asHumanReadable } from 'src/domain/domain.util'; import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; @@ -21,6 +20,7 @@ import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { asHumanReadable } from 'src/utils'; @Injectable() export class ServerInfoService { diff --git a/server/src/domain/shared-link/shared-link.dto.ts b/server/src/domain/shared-link/shared-link.dto.ts index ea529979c..7ef9a7733 100644 --- a/server/src/domain/shared-link/shared-link.dto.ts +++ b/server/src/domain/shared-link/shared-link.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; import { SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; export class SharedLinkCreateDto { @IsEnum(SharedLinkType) diff --git a/server/src/domain/shared-link/shared-link.service.ts b/server/src/domain/shared-link/shared-link.service.ts index a5a28b374..b55085492 100644 --- a/server/src/domain/shared-link/shared-link.service.ts +++ b/server/src/domain/shared-link/shared-link.service.ts @@ -3,7 +3,6 @@ import { AccessCore, Permission } from 'src/domain/access/access.core'; import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { OpenGraphTags } from 'src/domain/domain.util'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; @@ -15,6 +14,7 @@ import { import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { SharedLinkEntity, SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { OpenGraphTags } from 'src/utils'; @Injectable() export class SharedLinkService { diff --git a/server/src/domain/smart-info/dto/model-config.dto.ts b/server/src/domain/smart-info/dto/model-config.dto.ts index 0b12e1cc6..e0977c4da 100644 --- a/server/src/domain/smart-info/dto/model-config.dto.ts +++ b/server/src/domain/smart-info/dto/model-config.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsNotEmpty, IsNumber, IsString, Max, Min } from 'class-validator'; -import { Optional, ValidateBoolean } from 'src/domain/domain.util'; import { CLIPMode, ModelType } from 'src/domain/repositories/machine-learning.repository'; +import { Optional, ValidateBoolean } from 'src/validation'; export class ModelConfig { @ValidateBoolean() diff --git a/server/src/domain/smart-info/smart-info.service.ts b/server/src/domain/smart-info/smart-info.service.ts index 8f20f56d5..fdf9862f8 100644 --- a/server/src/domain/smart-info/smart-info.service.ts +++ b/server/src/domain/smart-info/smart-info.service.ts @@ -1,5 +1,4 @@ import { Inject, Injectable } from '@nestjs/common'; -import { usePagination } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; @@ -10,6 +9,7 @@ import { ISearchRepository } from 'src/domain/repositories/search.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { ImmichLogger } from 'src/infra/logger'; +import { usePagination } from 'src/utils'; @Injectable() export class SmartInfoService { diff --git a/server/src/domain/storage-template/storage-template.service.ts b/server/src/domain/storage-template/storage-template.service.ts index 8028eb359..f3e24c056 100644 --- a/server/src/domain/storage-template/storage-template.service.ts +++ b/server/src/domain/storage-template/storage-template.service.ts @@ -4,7 +4,6 @@ import handlebar from 'handlebars'; import { DateTime } from 'luxon'; import path from 'node:path'; import sanitize from 'sanitize-filename'; -import { getLivePhotoMotionFilename, usePagination } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; import { IEntityJob } from 'src/domain/job/job.interface'; import { IAlbumRepository } from 'src/domain/repositories/album.repository'; @@ -33,6 +32,7 @@ import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { AssetPathType } from 'src/infra/entities/move.entity'; import { SystemConfig } from 'src/infra/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { getLivePhotoMotionFilename, usePagination } from 'src/utils'; export interface MoveAssetMetadata { storageLabel: string | null; diff --git a/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts b/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts index 99077176b..16f81b37c 100644 --- a/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts +++ b/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts @@ -1,7 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsInt, IsString, Max, Min } from 'class-validator'; -import { ValidateBoolean } from 'src/domain/domain.util'; import { AudioCodec, CQMode, @@ -10,6 +9,7 @@ import { TranscodePolicy, VideoCodec, } from 'src/infra/entities/system-config.entity'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigFFmpegDto { @IsInt() diff --git a/server/src/domain/system-config/dto/system-config-library.dto.ts b/server/src/domain/system-config/dto/system-config-library.dto.ts index f322423df..8c7501ae4 100644 --- a/server/src/domain/system-config/dto/system-config-library.dto.ts +++ b/server/src/domain/system-config/dto/system-config-library.dto.ts @@ -9,7 +9,7 @@ import { ValidatorConstraint, ValidatorConstraintInterface, } from 'class-validator'; -import { ValidateBoolean, validateCronExpression } from 'src/domain/domain.util'; +import { ValidateBoolean, validateCronExpression } from 'src/validation'; const isEnabled = (config: SystemConfigLibraryScanDto) => config.enabled; diff --git a/server/src/domain/system-config/dto/system-config-logging.dto.ts b/server/src/domain/system-config/dto/system-config-logging.dto.ts index 0f1664ee3..f41b568a2 100644 --- a/server/src/domain/system-config/dto/system-config-logging.dto.ts +++ b/server/src/domain/system-config/dto/system-config-logging.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; -import { ValidateBoolean } from 'src/domain/domain.util'; import { LogLevel } from 'src/infra/entities/system-config.entity'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigLoggingDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts b/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts index 1b33d5920..058585992 100644 --- a/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts +++ b/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts @@ -1,7 +1,7 @@ import { Type } from 'class-transformer'; import { IsObject, IsUrl, ValidateIf, ValidateNested } from 'class-validator'; -import { ValidateBoolean } from 'src/domain/domain.util'; import { CLIPConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigMachineLearningDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-map.dto.ts b/server/src/domain/system-config/dto/system-config-map.dto.ts index fb8aac593..9ec0abfa4 100644 --- a/server/src/domain/system-config/dto/system-config-map.dto.ts +++ b/server/src/domain/system-config/dto/system-config-map.dto.ts @@ -1,5 +1,5 @@ import { IsString } from 'class-validator'; -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigMapDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts b/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts index 27afe1e68..7d5c5134f 100644 --- a/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts +++ b/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigNewVersionCheckDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-oauth.dto.ts b/server/src/domain/system-config/dto/system-config-oauth.dto.ts index 13465b772..9c7fc5f40 100644 --- a/server/src/domain/system-config/dto/system-config-oauth.dto.ts +++ b/server/src/domain/system-config/dto/system-config-oauth.dto.ts @@ -1,5 +1,5 @@ import { IsNotEmpty, IsNumber, IsString, IsUrl, Min, ValidateIf } from 'class-validator'; -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; const isEnabled = (config: SystemConfigOAuthDto) => config.enabled; const isOverrideEnabled = (config: SystemConfigOAuthDto) => config.mobileOverrideEnabled; diff --git a/server/src/domain/system-config/dto/system-config-password-login.dto.ts b/server/src/domain/system-config/dto/system-config-password-login.dto.ts index 3d98ae045..8d49a7002 100644 --- a/server/src/domain/system-config/dto/system-config-password-login.dto.ts +++ b/server/src/domain/system-config/dto/system-config-password-login.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigPasswordLoginDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts b/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts index ad4bcaab6..8ff286601 100644 --- a/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts +++ b/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigReverseGeocodingDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-storage-template.dto.ts b/server/src/domain/system-config/dto/system-config-storage-template.dto.ts index c35dcd476..77204b46e 100644 --- a/server/src/domain/system-config/dto/system-config-storage-template.dto.ts +++ b/server/src/domain/system-config/dto/system-config-storage-template.dto.ts @@ -1,5 +1,5 @@ import { IsNotEmpty, IsString } from 'class-validator'; -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigStorageTemplateDto { @ValidateBoolean() diff --git a/server/src/domain/system-config/dto/system-config-trash.dto.ts b/server/src/domain/system-config/dto/system-config-trash.dto.ts index 8765b4ff1..a9e5483eb 100644 --- a/server/src/domain/system-config/dto/system-config-trash.dto.ts +++ b/server/src/domain/system-config/dto/system-config-trash.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsInt, Min } from 'class-validator'; -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class SystemConfigTrashDto { @ValidateBoolean() diff --git a/server/src/domain/tag/tag.dto.ts b/server/src/domain/tag/tag.dto.ts index e0c27294a..322f40acf 100644 --- a/server/src/domain/tag/tag.dto.ts +++ b/server/src/domain/tag/tag.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional } from 'src/domain/domain.util'; import { TagType } from 'src/infra/entities/tag.entity'; +import { Optional } from 'src/validation'; export class CreateTagDto { @IsString() diff --git a/server/src/domain/trash/trash.service.ts b/server/src/domain/trash/trash.service.ts index 230ce77f3..aa95a4889 100644 --- a/server/src/domain/trash/trash.service.ts +++ b/server/src/domain/trash/trash.service.ts @@ -3,12 +3,12 @@ import { DateTime } from 'luxon'; import { AccessCore, Permission } from 'src/domain/access/access.core'; import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { usePagination } from 'src/domain/domain.util'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { usePagination } from 'src/utils'; export class TrashService { private access: AccessCore; diff --git a/server/src/domain/user/dto/create-user.dto.ts b/server/src/domain/user/dto/create-user.dto.ts index aa295cb2b..7861c58c2 100644 --- a/server/src/domain/user/dto/create-user.dto.ts +++ b/server/src/domain/user/dto/create-user.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsEmail, IsNotEmpty, IsNumber, IsPositive, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/domain/domain.util'; +import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation'; export class CreateUserDto { @IsEmail({ require_tld: false }) diff --git a/server/src/domain/user/dto/delete-user.dto.ts b/server/src/domain/user/dto/delete-user.dto.ts index 09b1c5bf3..aa41e18aa 100644 --- a/server/src/domain/user/dto/delete-user.dto.ts +++ b/server/src/domain/user/dto/delete-user.dto.ts @@ -1,4 +1,4 @@ -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class DeleteUserDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/domain/user/dto/update-user.dto.ts b/server/src/domain/user/dto/update-user.dto.ts index 605017e54..c7c47c4cf 100644 --- a/server/src/domain/user/dto/update-user.dto.ts +++ b/server/src/domain/user/dto/update-user.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator'; -import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/domain/domain.util'; import { UserAvatarColor } from 'src/infra/entities/user.entity'; +import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation'; export class UpdateUserDto { @Optional() diff --git a/server/src/domain/user/user.service.spec.ts b/server/src/domain/user/user.service.spec.ts index 8fed91c71..d590d7fda 100644 --- a/server/src/domain/user/user.service.spec.ts +++ b/server/src/domain/user/user.service.spec.ts @@ -5,7 +5,6 @@ import { NotFoundException, } from '@nestjs/common'; import { when } from 'jest-when'; -import { CacheControl, ImmichFileResponse } from 'src/domain/domain.util'; import { JobName } from 'src/domain/job/job.constants'; import { IAlbumRepository } from 'src/domain/repositories/album.repository'; import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; @@ -18,6 +17,7 @@ import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { UserService } from 'src/domain/user/user.service'; import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; +import { CacheControl, ImmichFileResponse } from 'src/utils'; import { authStub } from 'test/fixtures/auth.stub'; import { systemConfigStub } from 'test/fixtures/system-config.stub'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/src/domain/user/user.service.ts b/server/src/domain/user/user.service.ts index 18f485b00..6eca5ff55 100644 --- a/server/src/domain/user/user.service.ts +++ b/server/src/domain/user/user.service.ts @@ -2,7 +2,6 @@ import { BadRequestException, ForbiddenException, Inject, Injectable, NotFoundEx import { DateTime } from 'luxon'; import { randomBytes } from 'node:crypto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { CacheControl, ImmichFileResponse } from 'src/domain/domain.util'; import { JobName } from 'src/domain/job/job.constants'; import { IEntityJob } from 'src/domain/job/job.interface'; import { IAlbumRepository } from 'src/domain/repositories/album.repository'; @@ -25,6 +24,7 @@ import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-resp import { UserCore } from 'src/domain/user/user.core'; import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { CacheControl, ImmichFileResponse } from 'src/utils'; @Injectable() export class UserService { diff --git a/server/src/immich/api-v1/asset/asset.controller.ts b/server/src/immich/api-v1/asset/asset.controller.ts index 3faf33641..0496c75be 100644 --- a/server/src/immich/api-v1/asset/asset.controller.ts +++ b/server/src/immich/api-v1/asset/asset.controller.ts @@ -29,16 +29,15 @@ import { AssetFileUploadResponseDto } from 'src/immich/api-v1/asset/response-dto import { CheckExistingAssetsResponseDto } from 'src/immich/api-v1/asset/response-dto/check-existing-assets-response.dto'; import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; -import FileNotEmptyValidator from 'src/immich/api-v1/validation/file-not-empty-validator'; import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/immich/app.guard'; import { sendFile } from 'src/immich/app.utils'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; import { FileUploadInterceptor, ImmichFile, Route, mapToUploadFile, } from 'src/immich/interceptors/file-upload.interceptor'; +import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation'; interface UploadFiles { assetData: ImmichFile[]; diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 78f7fa24f..613e8f2ed 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -10,7 +10,6 @@ import { UploadFile } from 'src/domain/asset/asset.service'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; -import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/domain/domain.util'; import { JobName } from 'src/domain/job/job.constants'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; @@ -37,6 +36,7 @@ import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/ import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/utils'; import { QueryFailedError } from 'typeorm'; @Injectable() diff --git a/server/src/immich/api-v1/asset/dto/asset-search.dto.ts b/server/src/immich/api-v1/asset/dto/asset-search.dto.ts index 499ec7499..97d0aa1fa 100644 --- a/server/src/immich/api-v1/asset/dto/asset-search.dto.ts +++ b/server/src/immich/api-v1/asset/dto/asset-search.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsInt, IsUUID } from 'class-validator'; -import { Optional, ValidateBoolean, ValidateDate } from 'src/domain/domain.util'; +import { Optional, ValidateBoolean, ValidateDate } from 'src/validation'; export class AssetSearchDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/immich/api-v1/asset/dto/create-asset.dto.ts b/server/src/immich/api-v1/asset/dto/create-asset.dto.ts index 90b2d2245..d16a9c05c 100644 --- a/server/src/immich/api-v1/asset/dto/create-asset.dto.ts +++ b/server/src/immich/api-v1/asset/dto/create-asset.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsString } from 'class-validator'; import { UploadFieldName } from 'src/domain/asset/asset.service'; -import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/domain/domain.util'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; export class CreateAssetDto { @ValidateUUID({ optional: true }) diff --git a/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts b/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts index 65c6a7deb..6c709eb02 100644 --- a/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts +++ b/server/src/immich/api-v1/asset/dto/get-asset-thumbnail.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; -import { Optional } from 'src/domain/domain.util'; +import { Optional } from 'src/validation'; export enum GetAssetThumbnailFormatEnum { JPEG = 'JPEG', diff --git a/server/src/immich/api-v1/asset/dto/serve-file.dto.ts b/server/src/immich/api-v1/asset/dto/serve-file.dto.ts index cc8d8fd15..8b3147fc2 100644 --- a/server/src/immich/api-v1/asset/dto/serve-file.dto.ts +++ b/server/src/immich/api-v1/asset/dto/serve-file.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { ValidateBoolean } from 'src/domain/domain.util'; +import { ValidateBoolean } from 'src/validation'; export class ServeFileDto { @ValidateBoolean({ optional: true }) diff --git a/server/src/immich/api-v1/validation/file-not-empty-validator.ts b/server/src/immich/api-v1/validation/file-not-empty-validator.ts deleted file mode 100644 index 21f93a952..000000000 --- a/server/src/immich/api-v1/validation/file-not-empty-validator.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { FileValidator, Injectable } from '@nestjs/common'; - -@Injectable() -export default class FileNotEmptyValidator extends FileValidator { - constructor(private requiredFields: string[]) { - super({}); - this.requiredFields = requiredFields; - } - - isValid(files?: any): boolean { - if (!files) { - return false; - } - - return this.requiredFields.every((field) => files[field]); - } - - buildErrorMessage(): string { - return `Field(s) ${this.requiredFields.join(', ')} should not be empty`; - } -} diff --git a/server/src/immich/api-v1/validation/parse-me-uuid-pipe.ts b/server/src/immich/api-v1/validation/parse-me-uuid-pipe.ts deleted file mode 100644 index 4329af011..000000000 --- a/server/src/immich/api-v1/validation/parse-me-uuid-pipe.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { ArgumentMetadata, Injectable, ParseUUIDPipe } from '@nestjs/common'; - -@Injectable() -export class ParseMeUUIDPipe extends ParseUUIDPipe { - async transform(value: string, metadata: ArgumentMetadata) { - if (value == 'me') { - return value; - } - return super.transform(value, metadata); - } -} diff --git a/server/src/immich/app.service.ts b/server/src/immich/app.service.ts index 8cbb6cf23..f7f1664be 100644 --- a/server/src/immich/app.service.ts +++ b/server/src/immich/app.service.ts @@ -6,13 +6,13 @@ import { join } from 'node:path'; import { AuthService } from 'src/domain/auth/auth.service'; import { DatabaseService } from 'src/domain/database/database.service'; import { ONE_HOUR, WEB_ROOT } from 'src/domain/domain.constant'; -import { OpenGraphTags } from 'src/domain/domain.util'; import { JobService } from 'src/domain/job/job.service'; import { ServerInfoService } from 'src/domain/server-info/server-info.service'; import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; import { StorageService } from 'src/domain/storage/storage.service'; import { SystemConfigService } from 'src/domain/system-config/system-config.service'; import { ImmichLogger } from 'src/infra/logger'; +import { OpenGraphTags } from 'src/utils'; const render = (index: string, meta: OpenGraphTags) => { const tags = ` diff --git a/server/src/immich/app.utils.ts b/server/src/immich/app.utils.ts index 4d78ffb24..48f01d8dd 100644 --- a/server/src/immich/app.utils.ts +++ b/server/src/immich/app.utils.ts @@ -15,10 +15,10 @@ import path, { isAbsolute } from 'node:path'; import { promisify } from 'node:util'; import { IMMICH_ACCESS_COOKIE, IMMICH_API_KEY_HEADER, IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; import { serverVersion } from 'src/domain/domain.constant'; -import { CacheControl, ImmichFileResponse, isConnectionAborted } from 'src/domain/domain.util'; import { ImmichReadStream } from 'src/domain/repositories/storage.repository'; import { Metadata } from 'src/immich/app.guard'; import { ImmichLogger } from 'src/infra/logger'; +import { CacheControl, ImmichFileResponse, isConnectionAborted } from 'src/utils'; type SendFile = Parameters; type SendFileOptions = SendFile[1]; diff --git a/server/src/immich/controllers/activity.controller.ts b/server/src/immich/controllers/activity.controller.ts index c79a56407..45f58e9f2 100644 --- a/server/src/immich/controllers/activity.controller.ts +++ b/server/src/immich/controllers/activity.controller.ts @@ -11,7 +11,7 @@ import { import { ActivityService } from 'src/domain/activity/activity.service'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { Auth, Authenticated } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Activity') @Controller('activity') diff --git a/server/src/immich/controllers/album.controller.ts b/server/src/immich/controllers/album.controller.ts index 8981de212..12e35a0f6 100644 --- a/server/src/immich/controllers/album.controller.ts +++ b/server/src/immich/controllers/album.controller.ts @@ -9,9 +9,8 @@ import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; import { BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { ParseMeUUIDPipe } from 'src/immich/api-v1/validation/parse-me-uuid-pipe'; import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { ParseMeUUIDPipe, UUIDParamDto } from 'src/validation'; @ApiTags('Album') @Controller('album') diff --git a/server/src/immich/controllers/api-key.controller.ts b/server/src/immich/controllers/api-key.controller.ts index b9b449610..96afe676d 100644 --- a/server/src/immich/controllers/api-key.controller.ts +++ b/server/src/immich/controllers/api-key.controller.ts @@ -9,7 +9,7 @@ import { import { APIKeyService } from 'src/domain/api-key/api-key.service'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { Auth, Authenticated } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('API Key') @Controller('api-key') diff --git a/server/src/immich/controllers/asset.controller.ts b/server/src/immich/controllers/asset.controller.ts index d085dbe57..ee35c98dd 100644 --- a/server/src/immich/controllers/asset.controller.ts +++ b/server/src/immich/controllers/asset.controller.ts @@ -21,8 +21,8 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; import { MetadataSearchDto } from 'src/domain/search/dto/search.dto'; import { SearchService } from 'src/domain/search/search.service'; import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; import { Route } from 'src/immich/interceptors/file-upload.interceptor'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Asset') @Controller('assets') diff --git a/server/src/immich/controllers/auth.controller.ts b/server/src/immich/controllers/auth.controller.ts index b2dece148..7f9fea47c 100644 --- a/server/src/immich/controllers/auth.controller.ts +++ b/server/src/immich/controllers/auth.controller.ts @@ -15,7 +15,7 @@ import { import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Authentication') @Controller('auth') diff --git a/server/src/immich/controllers/download.controller.ts b/server/src/immich/controllers/download.controller.ts index 41849a41d..0cfaa3ea8 100644 --- a/server/src/immich/controllers/download.controller.ts +++ b/server/src/immich/controllers/download.controller.ts @@ -7,7 +7,7 @@ import { DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/downlo import { DownloadService } from 'src/domain/download/download.service'; import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/immich/app.guard'; import { asStreamableFile, sendFile } from 'src/immich/app.utils'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Download') @Controller('download') diff --git a/server/src/immich/controllers/dto/uuid-param.dto.ts b/server/src/immich/controllers/dto/uuid-param.dto.ts deleted file mode 100644 index 6e1b5a36c..000000000 --- a/server/src/immich/controllers/dto/uuid-param.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsNotEmpty, IsUUID } from 'class-validator'; - -export class UUIDParamDto { - @IsNotEmpty() - @IsUUID('4') - @ApiProperty({ format: 'uuid' }) - id!: string; -} diff --git a/server/src/immich/controllers/face.controller.ts b/server/src/immich/controllers/face.controller.ts index 0fab1bb91..e7d1c3fba 100644 --- a/server/src/immich/controllers/face.controller.ts +++ b/server/src/immich/controllers/face.controller.ts @@ -4,7 +4,7 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; import { AssetFaceResponseDto, FaceDto, PersonResponseDto } from 'src/domain/person/person.dto'; import { PersonService } from 'src/domain/person/person.service'; import { Auth, Authenticated } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Face') @Controller('face') diff --git a/server/src/immich/controllers/library.controller.ts b/server/src/immich/controllers/library.controller.ts index d72461988..5e362f6d0 100644 --- a/server/src/immich/controllers/library.controller.ts +++ b/server/src/immich/controllers/library.controller.ts @@ -12,7 +12,7 @@ import { } from 'src/domain/library/library.dto'; import { LibraryService } from 'src/domain/library/library.service'; import { AdminRoute, Authenticated } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Library') @Controller('library') diff --git a/server/src/immich/controllers/partner.controller.ts b/server/src/immich/controllers/partner.controller.ts index 43c388e10..c6bfea355 100644 --- a/server/src/immich/controllers/partner.controller.ts +++ b/server/src/immich/controllers/partner.controller.ts @@ -5,7 +5,7 @@ import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner import { PartnerService } from 'src/domain/partner/partner.service'; import { PartnerDirection } from 'src/domain/repositories/partner.repository'; import { Auth, Authenticated } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Partner') @Controller('partner') diff --git a/server/src/immich/controllers/person.controller.ts b/server/src/immich/controllers/person.controller.ts index c2b789678..9ef791c3c 100644 --- a/server/src/immich/controllers/person.controller.ts +++ b/server/src/immich/controllers/person.controller.ts @@ -18,7 +18,7 @@ import { import { PersonService } from 'src/domain/person/person.service'; import { Auth, Authenticated, FileResponse } from 'src/immich/app.guard'; import { sendFile } from 'src/immich/app.utils'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Person') @Controller('person') diff --git a/server/src/immich/controllers/shared-link.controller.ts b/server/src/immich/controllers/shared-link.controller.ts index 39e4c084e..b0717026c 100644 --- a/server/src/immich/controllers/shared-link.controller.ts +++ b/server/src/immich/controllers/shared-link.controller.ts @@ -9,7 +9,7 @@ import { SharedLinkResponseDto } from 'src/domain/shared-link/shared-link-respon import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Shared Link') @Controller('shared-link') diff --git a/server/src/immich/controllers/tag.controller.ts b/server/src/immich/controllers/tag.controller.ts index 511d7b1d1..99715d5c7 100644 --- a/server/src/immich/controllers/tag.controller.ts +++ b/server/src/immich/controllers/tag.controller.ts @@ -8,7 +8,7 @@ import { TagResponseDto } from 'src/domain/tag/tag-response.dto'; import { CreateTagDto, UpdateTagDto } from 'src/domain/tag/tag.dto'; import { TagService } from 'src/domain/tag/tag.service'; import { Auth, Authenticated } from 'src/immich/app.guard'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('Tag') @Controller('tag') diff --git a/server/src/immich/controllers/user.controller.ts b/server/src/immich/controllers/user.controller.ts index 10b16859f..3f80765a9 100644 --- a/server/src/immich/controllers/user.controller.ts +++ b/server/src/immich/controllers/user.controller.ts @@ -26,8 +26,8 @@ import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto' import { UserService } from 'src/domain/user/user.service'; import { AdminRoute, Auth, Authenticated, FileResponse } from 'src/immich/app.guard'; import { sendFile } from 'src/immich/app.utils'; -import { UUIDParamDto } from 'src/immich/controllers/dto/uuid-param.dto'; import { FileUploadInterceptor, Route } from 'src/immich/interceptors/file-upload.interceptor'; +import { UUIDParamDto } from 'src/validation'; @ApiTags('User') @Controller(Route.USER) diff --git a/server/src/immich/interceptors/error.interceptor.ts b/server/src/immich/interceptors/error.interceptor.ts index 809464b37..70c129922 100644 --- a/server/src/immich/interceptors/error.interceptor.ts +++ b/server/src/immich/interceptors/error.interceptor.ts @@ -7,9 +7,9 @@ import { NestInterceptor, } from '@nestjs/common'; import { Observable, catchError, throwError } from 'rxjs'; -import { isConnectionAborted } from 'src/domain/domain.util'; import { routeToErrorMessage } from 'src/immich/app.utils'; import { ImmichLogger } from 'src/infra/logger'; +import { isConnectionAborted } from 'src/utils'; @Injectable() export class ErrorInterceptor implements NestInterceptor { diff --git a/server/src/immich/main.ts b/server/src/immich/main.ts index adfe476a2..310ac9302 100644 --- a/server/src/immich/main.ts +++ b/server/src/immich/main.ts @@ -4,11 +4,11 @@ import { json } from 'body-parser'; import cookieParser from 'cookie-parser'; import { existsSync } from 'node:fs'; import sirv from 'sirv'; +import { excludePaths } from 'src/config'; import { WEB_ROOT, envName, isDev, serverVersion } from 'src/domain/domain.constant'; import { AppModule } from 'src/immich/app.module'; import { AppService } from 'src/immich/app.service'; import { useSwagger } from 'src/immich/app.utils'; -import { excludePaths } from 'src/infra/infra.config'; import { otelSDK } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; import { WebSocketAdapter } from 'src/infra/websocket.adapter'; diff --git a/server/src/infra/infra.module.ts b/server/src/infra/infra.module.ts index 7ac208c1f..b1636c5e2 100644 --- a/server/src/infra/infra.module.ts +++ b/server/src/infra/infra.module.ts @@ -5,7 +5,7 @@ import { EventEmitterModule } from '@nestjs/event-emitter'; import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpenTelemetryModule } from 'nestjs-otel'; -import { immichAppConfig } from 'src/domain/domain.config'; +import { bullConfig, bullQueues, immichAppConfig } from 'src/config'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { IActivityRepository } from 'src/domain/repositories/activity.repository'; import { IAlbumRepository } from 'src/domain/repositories/album.repository'; @@ -35,7 +35,6 @@ import { IUserTokenRepository } from 'src/domain/repositories/user-token.reposit import { IUserRepository } from 'src/domain/repositories/user.repository'; import { databaseConfig } from 'src/infra/database.config'; import { databaseEntities } from 'src/infra/entities'; -import { bullConfig, bullQueues } from 'src/infra/infra.config'; import { otelConfig } from 'src/infra/instrumentation'; import { AccessRepository } from 'src/infra/repositories/access.repository'; import { ActivityRepository } from 'src/infra/repositories/activity.repository'; diff --git a/server/src/infra/infra.util.ts b/server/src/infra/infra.util.ts deleted file mode 100644 index 585d058e0..000000000 --- a/server/src/infra/infra.util.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { SetMetadata } from '@nestjs/common'; - -export const GENERATE_SQL_KEY = 'generate-sql-key'; - -export interface GenerateSqlQueries { - name?: string; - params: unknown[]; -} - -/** Decorator to enable versioning/tracking of generated Sql */ -export const GenerateSql = (...options: GenerateSqlQueries[]) => SetMetadata(GENERATE_SQL_KEY, options); - -const UUID = '00000000-0000-4000-a000-000000000000'; - -export const DummyValue = { - UUID, - UUID_SET: new Set([UUID]), - PAGINATION: { take: 10, skip: 0 }, - EMAIL: 'user@immich.app', - STRING: 'abcdefghi', - BUFFER: Buffer.from('abcdefghi'), - DATE: new Date(), - TIME_BUCKET: '2024-01-01T00:00:00.000Z', -}; - -// PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the -// maximum number of parameters is 65535. Any query that tries to bind more than that (e.g. searching -// by a list of IDs) requires splitting the query into multiple chunks. -// We are rounding down this limit, as queries commonly include other filters and parameters. -export const DATABASE_PARAMETER_CHUNK_SIZE = 65_500; diff --git a/server/src/infra/infra.utils.ts b/server/src/infra/infra.utils.ts index 2cc5f629a..41c57904b 100644 --- a/server/src/infra/infra.utils.ts +++ b/server/src/infra/infra.utils.ts @@ -1,16 +1,7 @@ import _ from 'lodash'; -import { - Paginated, - PaginatedBuilderOptions, - PaginationMode, - PaginationOptions, - PaginationResult, - chunks, - setUnion, -} from 'src/domain/domain.util'; import { AssetSearchBuilderOptions } from 'src/domain/repositories/search.repository'; import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { DATABASE_PARAMETER_CHUNK_SIZE } from 'src/infra/infra.util'; +import { Paginated, PaginatedBuilderOptions, PaginationMode, PaginationOptions, PaginationResult } from 'src/utils'; import { Between, FindManyOptions, @@ -37,11 +28,6 @@ export function OptionalBetween(from?: T, to?: T) { } } -export const isValidInteger = (value: number, options: { min?: number; max?: number }): value is number => { - const { min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER } = options; - return Number.isInteger(value) && value >= min && value <= max; -}; - function paginationHelper(items: Entity[], take: number): PaginationResult { const hasNextPage = items.length > take; items.splice(take); @@ -86,70 +72,6 @@ export async function paginatedBuilder( export const asVector = (embedding: number[], quote = false) => quote ? `'[${embedding.join(',')}]'` : `[${embedding.join(',')}]`; -/** - * Wraps a method that takes a collection of parameters and sequentially calls it with chunks of the collection, - * to overcome the maximum number of parameters allowed by the database driver. - * - * @param options.paramIndex The index of the function parameter to chunk. Defaults to 0. - * @param options.flatten Whether to flatten the results. Defaults to false. - */ -export function Chunked(options: { paramIndex?: number; mergeFn?: (results: any) => any } = {}): MethodDecorator { - return (target: any, propertyKey: string | symbol, descriptor: PropertyDescriptor) => { - const originalMethod = descriptor.value; - const parameterIndex = options.paramIndex ?? 0; - descriptor.value = async function (...arguments_: any[]) { - const argument = arguments_[parameterIndex]; - - // Early return if argument length is less than or equal to the chunk size. - if ( - (Array.isArray(argument) && argument.length <= DATABASE_PARAMETER_CHUNK_SIZE) || - (argument instanceof Set && argument.size <= DATABASE_PARAMETER_CHUNK_SIZE) - ) { - return await originalMethod.apply(this, arguments_); - } - - return Promise.all( - chunks(argument, DATABASE_PARAMETER_CHUNK_SIZE).map(async (chunk) => { - await Reflect.apply(originalMethod, this, [ - ...arguments_.slice(0, parameterIndex), - chunk, - ...arguments_.slice(parameterIndex + 1), - ]); - }), - ).then((results) => (options.mergeFn ? options.mergeFn(results) : results)); - }; - }; -} - -export function ChunkedArray(options?: { paramIndex?: number }): MethodDecorator { - return Chunked({ ...options, mergeFn: _.flatten }); -} - -export function ChunkedSet(options?: { paramIndex?: number }): MethodDecorator { - return Chunked({ ...options, mergeFn: setUnion }); -} - -// https://stackoverflow.com/a/74898678 -export function DecorateAll( - decorator: ( - target: any, - propertyKey: string, - descriptor: TypedPropertyDescriptor, - ) => TypedPropertyDescriptor | void, -) { - return (target: any) => { - const descriptors = Object.getOwnPropertyDescriptors(target.prototype); - for (const [propName, descriptor] of Object.entries(descriptors)) { - const isMethod = typeof descriptor.value == 'function' && propName !== 'constructor'; - if (!isMethod) { - continue; - } - decorator({ ...target, constructor: { ...target.constructor, name: target.name } as any }, propName, descriptor); - Object.defineProperty(target.prototype, propName, descriptor); - } - }; -} - export function searchAssetBuilder( builder: SelectQueryBuilder, options: AssetSearchBuilderOptions, diff --git a/server/src/infra/instrumentation.ts b/server/src/infra/instrumentation.ts index 2c912660e..a30f0523a 100644 --- a/server/src/infra/instrumentation.ts +++ b/server/src/infra/instrumentation.ts @@ -13,9 +13,9 @@ import { snakeCase, startCase } from 'lodash'; import { OpenTelemetryModuleOptions } from 'nestjs-otel/lib/interfaces'; import { copyMetadataFromFunctionToFunction } from 'nestjs-otel/lib/opentelemetry.utils'; import { performance } from 'node:perf_hooks'; +import { excludePaths } from 'src/config'; +import { DecorateAll } from 'src/decorators'; import { serverVersion } from 'src/domain/domain.constant'; -import { excludePaths } from 'src/infra/infra.config'; -import { DecorateAll } from 'src/infra/infra.utils'; let metricsEnabled = process.env.IMMICH_METRICS === 'true'; const hostMetrics = diff --git a/server/src/infra/repositories/access.repository.ts b/server/src/infra/repositories/access.repository.ts index 1f96226a6..d16d6a6aa 100644 --- a/server/src/infra/repositories/access.repository.ts +++ b/server/src/infra/repositories/access.repository.ts @@ -1,4 +1,5 @@ import { InjectRepository } from '@nestjs/typeorm'; +import { ChunkedSet, DummyValue, GenerateSql } from 'src/decorators'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { ActivityEntity } from 'src/infra/entities/activity.entity'; import { AlbumEntity } from 'src/infra/entities/album.entity'; @@ -9,8 +10,6 @@ import { PartnerEntity } from 'src/infra/entities/partner.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; -import { ChunkedSet } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; import { Brackets, In, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/activity.repository.ts b/server/src/infra/repositories/activity.repository.ts index afa52ec3a..1cfe3e264 100644 --- a/server/src/infra/repositories/activity.repository.ts +++ b/server/src/infra/repositories/activity.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { IActivityRepository } from 'src/domain/repositories/activity.repository'; import { ActivityEntity } from 'src/infra/entities/activity.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; import { Instrumentation } from 'src/infra/instrumentation'; import { IsNull, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/album.repository.ts b/server/src/infra/repositories/album.repository.ts index 86b73866f..b31a894b5 100644 --- a/server/src/infra/repositories/album.repository.ts +++ b/server/src/infra/repositories/album.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import _ from 'lodash'; -import { setUnion } from 'src/domain/domain.util'; +import { Chunked, ChunkedArray, DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from 'src/decorators'; import { AlbumAsset, AlbumAssetCount, @@ -12,9 +12,8 @@ import { import { dataSource } from 'src/infra/database.config'; import { AlbumEntity } from 'src/infra/entities/album.entity'; import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from 'src/infra/infra.util'; -import { Chunked, ChunkedArray } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; +import { setUnion } from 'src/utils'; import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/api-key.repository.ts b/server/src/infra/repositories/api-key.repository.ts index bdc9e6d0b..5bacfded5 100644 --- a/server/src/infra/repositories/api-key.repository.ts +++ b/server/src/infra/repositories/api-key.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/asset.repository.ts b/server/src/infra/repositories/asset.repository.ts index 93f2e42a1..a57e852d2 100644 --- a/server/src/infra/repositories/asset.repository.ts +++ b/server/src/infra/repositories/asset.repository.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DateTime } from 'luxon'; import path from 'node:path'; -import { Paginated, PaginationMode, PaginationOptions } from 'src/domain/domain.util'; +import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; import { AssetBuilderOptions, AssetCreate, @@ -30,16 +30,9 @@ import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; -import { - Chunked, - ChunkedArray, - OptionalBetween, - paginate, - paginatedBuilder, - searchAssetBuilder, -} from 'src/infra/infra.utils'; +import { OptionalBetween, paginate, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; +import { Paginated, PaginationMode, PaginationOptions } from 'src/utils'; import { Brackets, FindOptionsRelations, diff --git a/server/src/infra/repositories/database.repository.ts b/server/src/infra/repositories/database.repository.ts index a83bcf80f..8720ad8d7 100644 --- a/server/src/infra/repositories/database.repository.ts +++ b/server/src/infra/repositories/database.repository.ts @@ -12,9 +12,9 @@ import { extName, } from 'src/domain/repositories/database.repository'; import { vectorExt } from 'src/infra/database.config'; -import { isValidInteger } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; +import { isValidInteger } from 'src/validation'; import { DataSource, EntityManager, QueryRunner } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/job.repository.ts b/server/src/infra/repositories/job.repository.ts index eac535e36..856c7fae0 100644 --- a/server/src/infra/repositories/job.repository.ts +++ b/server/src/infra/repositories/job.repository.ts @@ -5,6 +5,7 @@ import { SchedulerRegistry } from '@nestjs/schedule'; import { Job, JobsOptions, Processor, Queue, Worker, WorkerOptions } from 'bullmq'; import { CronJob, CronTime } from 'cron'; import { setTimeout } from 'node:timers/promises'; +import { bullConfig } from 'src/config'; import { JOBS_TO_QUEUE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IJobRepository, @@ -13,7 +14,6 @@ import { QueueCleanType, QueueStatus, } from 'src/domain/repositories/job.repository'; -import { bullConfig } from 'src/infra/infra.config'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/infra/repositories/library.repository.ts b/server/src/infra/repositories/library.repository.ts index f61d4beb6..f9045b9c8 100644 --- a/server/src/infra/repositories/library.repository.ts +++ b/server/src/infra/repositories/library.repository.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { LibraryStatsResponseDto } from 'src/domain/library/library.dto'; import { ILibraryRepository } from 'src/domain/repositories/library.repository'; import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; import { Instrumentation } from 'src/infra/instrumentation'; import { IsNull, Not } from 'typeorm'; import { Repository } from 'typeorm/repository/Repository.js'; diff --git a/server/src/infra/repositories/media.repository.ts b/server/src/infra/repositories/media.repository.ts index 0088e312f..f2d59ea95 100644 --- a/server/src/infra/repositories/media.repository.ts +++ b/server/src/infra/repositories/media.repository.ts @@ -3,7 +3,6 @@ import fs from 'node:fs/promises'; import { Writable } from 'node:stream'; import { promisify } from 'node:util'; import sharp from 'sharp'; -import { handlePromiseError } from 'src/domain/domain.util'; import { CropOptions, IMediaRepository, @@ -14,6 +13,7 @@ import { import { Colorspace } from 'src/infra/entities/system-config.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; +import { handlePromiseError } from 'src/utils'; const probe = promisify(ffmpeg.ffprobe); sharp.concurrency(0); diff --git a/server/src/infra/repositories/metadata.repository.ts b/server/src/infra/repositories/metadata.repository.ts index e81ba8dcb..365a3543f 100644 --- a/server/src/infra/repositories/metadata.repository.ts +++ b/server/src/infra/repositories/metadata.repository.ts @@ -6,6 +6,7 @@ import { getName } from 'i18n-iso-countries'; import { createReadStream, existsSync } from 'node:fs'; import { readFile } from 'node:fs/promises'; import readLine from 'node:readline'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { citiesFile, geodataAdmin1Path, @@ -23,7 +24,6 @@ import { ISystemMetadataRepository } from 'src/domain/repositories/system-metada import { ExifEntity } from 'src/infra/entities/exif.entity'; import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; import { DataSource, QueryRunner, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/move.repository.ts b/server/src/infra/repositories/move.repository.ts index 04807db24..8482fc228 100644 --- a/server/src/infra/repositories/move.repository.ts +++ b/server/src/infra/repositories/move.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { IMoveRepository, MoveCreate } from 'src/domain/repositories/move.repository'; import { MoveEntity, PathType } from 'src/infra/entities/move.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/person.repository.ts b/server/src/infra/repositories/person.repository.ts index df76ad9d0..e0d707ca1 100644 --- a/server/src/infra/repositories/person.repository.ts +++ b/server/src/infra/repositories/person.repository.ts @@ -1,6 +1,6 @@ import { InjectRepository } from '@nestjs/typeorm'; import _ from 'lodash'; -import { Paginated, PaginationOptions } from 'src/domain/domain.util'; +import { ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; import { AssetFaceId, IPersonRepository, @@ -13,9 +13,9 @@ import { import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; -import { ChunkedArray, asVector, paginate } from 'src/infra/infra.utils'; +import { asVector, paginate } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; +import { Paginated, PaginationOptions } from 'src/utils'; import { FindManyOptions, FindOptionsRelations, FindOptionsSelect, In, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/search.repository.ts b/server/src/infra/repositories/search.repository.ts index 5676bd8b5..6ba546ea9 100644 --- a/server/src/infra/repositories/search.repository.ts +++ b/server/src/infra/repositories/search.repository.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { Paginated, PaginationMode, PaginationResult } from 'src/domain/domain.util'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { DatabaseExtension } from 'src/domain/repositories/database.repository'; import { AssetSearchOptions, @@ -18,10 +18,11 @@ import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; import { SmartSearchEntity } from 'src/infra/entities/smart-search.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; -import { asVector, isValidInteger, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; +import { asVector, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; +import { Paginated, PaginationMode, PaginationResult } from 'src/utils'; +import { isValidInteger } from 'src/validation'; import { Repository, SelectQueryBuilder } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/shared-link.repository.ts b/server/src/infra/repositories/shared-link.repository.ts index 1b1ed7fe2..e2878acf4 100644 --- a/server/src/infra/repositories/shared-link.repository.ts +++ b/server/src/infra/repositories/shared-link.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/system-config.repository.ts b/server/src/infra/repositories/system-config.repository.ts index f354c87e6..555a3c254 100644 --- a/server/src/infra/repositories/system-config.repository.ts +++ b/server/src/infra/repositories/system-config.repository.ts @@ -1,9 +1,8 @@ import { InjectRepository } from '@nestjs/typeorm'; import { readFile } from 'node:fs/promises'; +import { Chunked, DummyValue, GenerateSql } from 'src/decorators'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SystemConfigEntity } from 'src/infra/entities/system-config.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; -import { Chunked } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; import { In, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/user-token.repository.ts b/server/src/infra/repositories/user-token.repository.ts index f2b79a05f..7d16bd0cf 100644 --- a/server/src/infra/repositories/user-token.repository.ts +++ b/server/src/infra/repositories/user-token.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; import { Instrumentation } from 'src/infra/instrumentation'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/user.repository.ts b/server/src/infra/repositories/user.repository.ts index e71d62936..27692dd66 100644 --- a/server/src/infra/repositories/user.repository.ts +++ b/server/src/infra/repositories/user.repository.ts @@ -1,5 +1,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { DummyValue, GenerateSql } from 'src/decorators'; import { IUserRepository, UserFindOptions, @@ -8,7 +9,6 @@ import { } from 'src/domain/repositories/user.repository'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { UserEntity } from 'src/infra/entities/user.entity'; -import { DummyValue, GenerateSql } from 'src/infra/infra.util'; import { Instrumentation } from 'src/infra/instrumentation'; import { IsNull, Not, Repository } from 'typeorm'; diff --git a/server/src/infra/sql-generator/index.ts b/server/src/infra/sql-generator/index.ts index c365587a9..0821d53cd 100644 --- a/server/src/infra/sql-generator/index.ts +++ b/server/src/infra/sql-generator/index.ts @@ -5,10 +5,10 @@ import { Test } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; import { mkdir, rm, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; +import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { databaseConfig } from 'src/infra/database.config'; import { databaseEntities } from 'src/infra/entities'; -import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/infra/infra.util'; import { AccessRepository } from 'src/infra/repositories/access.repository'; import { AlbumRepository } from 'src/infra/repositories/album.repository'; import { ApiKeyRepository } from 'src/infra/repositories/api-key.repository'; diff --git a/server/src/microservices/utils/exif/coordinates.ts b/server/src/microservices/utils/exif/coordinates.ts deleted file mode 100644 index 7e0d81679..000000000 --- a/server/src/microservices/utils/exif/coordinates.ts +++ /dev/null @@ -1,26 +0,0 @@ -import { isNumberInRange } from 'src/microservices/utils/numbers'; - -export function parseLatitude(input: string | number | null): number | null { - if (input === null) { - return null; - } - const latitude = typeof input === 'string' ? Number.parseFloat(input) : input; - - if (isNumberInRange(latitude, -90, 90)) { - return latitude; - } - return null; -} - -export function parseLongitude(input: string | number | null): number | null { - if (input === null) { - return null; - } - - const longitude = typeof input === 'string' ? Number.parseFloat(input) : input; - - if (isNumberInRange(longitude, -180, 180)) { - return longitude; - } - return null; -} diff --git a/server/src/microservices/utils/numbers.spec.ts b/server/src/microservices/utils/numbers.spec.ts deleted file mode 100644 index 633b8b1d4..000000000 --- a/server/src/microservices/utils/numbers.spec.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { isDecimalNumber, isNumberInRange, toNumberOrNull } from 'src/microservices/utils/numbers'; - -describe('checks if a number is a decimal number', () => { - it('returns false for non-decimal numbers', () => { - expect(isDecimalNumber(Number.NaN)).toBe(false); - expect(isDecimalNumber(Number.POSITIVE_INFINITY)).toBe(false); - expect(isDecimalNumber(Number.NEGATIVE_INFINITY)).toBe(false); - }); - - it('returns true for decimal numbers', () => { - expect(isDecimalNumber(0)).toBe(true); - expect(isDecimalNumber(-0)).toBe(true); - expect(isDecimalNumber(10.123_45)).toBe(true); - expect(isDecimalNumber(Number.MAX_VALUE)).toBe(true); - expect(isDecimalNumber(Number.MIN_VALUE)).toBe(true); - }); -}); - -describe('checks if a number is within a range', () => { - it('returns false for numbers outside the range', () => { - expect(isNumberInRange(0, 10, 10)).toBe(false); - expect(isNumberInRange(0.01, 10, 10)).toBe(false); - expect(isNumberInRange(50.1, 0, 50)).toBe(false); - }); - - it('returns true for numbers inside the range', () => { - expect(isNumberInRange(0, 0, 50)).toBe(true); - expect(isNumberInRange(50, 0, 50)).toBe(true); - expect(isNumberInRange(-50.123_45, -50.123_45, 0)).toBe(true); - }); -}); - -describe('converts input to a number or null', () => { - it('returns null for invalid inputs', () => { - expect(toNumberOrNull(null)).toBeNull(); - // eslint-disable-next-line unicorn/no-useless-undefined - expect(toNumberOrNull(undefined)).toBeNull(); - expect(toNumberOrNull('')).toBeNull(); - expect(toNumberOrNull(Number.NaN)).toBeNull(); - }); - - it('returns a number for valid inputs', () => { - expect(toNumberOrNull(0)).toBeCloseTo(0); - expect(toNumberOrNull('0')).toBeCloseTo(0); - expect(toNumberOrNull('-123.45')).toBeCloseTo(-123.45); - }); -}); diff --git a/server/src/microservices/utils/numbers.ts b/server/src/microservices/utils/numbers.ts deleted file mode 100644 index cd6e81d2a..000000000 --- a/server/src/microservices/utils/numbers.ts +++ /dev/null @@ -1,19 +0,0 @@ -export function isDecimalNumber(number_: number): boolean { - return !Number.isNaN(number_) && Number.isFinite(number_); -} - -/** - * Check if `num` is a valid number and is between `start` and `end` (inclusive) - */ -export function isNumberInRange(number_: number, start: number, end: number): boolean { - return isDecimalNumber(number_) && number_ >= start && number_ <= end; -} - -export function toNumberOrNull(input: number | string | null | undefined): number | null { - if (input === null || input === undefined) { - return null; - } - - const number_ = typeof input === 'string' ? Number.parseFloat(input) : input; - return isDecimalNumber(number_) ? number_ : null; -} diff --git a/server/src/microservices/utils/exif/coordinates.spec.ts b/server/src/utils.spec.ts similarity index 53% rename from server/src/microservices/utils/exif/coordinates.spec.ts rename to server/src/utils.spec.ts index 083ea31bc..c5ae5f6e5 100644 --- a/server/src/microservices/utils/exif/coordinates.spec.ts +++ b/server/src/utils.spec.ts @@ -1,4 +1,50 @@ -import { parseLatitude, parseLongitude } from 'src/microservices/utils/exif/coordinates'; +import { isDecimalNumber, isNumberInRange, parseLatitude, parseLongitude, toNumberOrNull } from 'src/utils'; + +describe('checks if a number is a decimal number', () => { + it('returns false for non-decimal numbers', () => { + expect(isDecimalNumber(Number.NaN)).toBe(false); + expect(isDecimalNumber(Number.POSITIVE_INFINITY)).toBe(false); + expect(isDecimalNumber(Number.NEGATIVE_INFINITY)).toBe(false); + }); + + it('returns true for decimal numbers', () => { + expect(isDecimalNumber(0)).toBe(true); + expect(isDecimalNumber(-0)).toBe(true); + expect(isDecimalNumber(10.123_45)).toBe(true); + expect(isDecimalNumber(Number.MAX_VALUE)).toBe(true); + expect(isDecimalNumber(Number.MIN_VALUE)).toBe(true); + }); +}); + +describe('checks if a number is within a range', () => { + it('returns false for numbers outside the range', () => { + expect(isNumberInRange(0, 10, 10)).toBe(false); + expect(isNumberInRange(0.01, 10, 10)).toBe(false); + expect(isNumberInRange(50.1, 0, 50)).toBe(false); + }); + + it('returns true for numbers inside the range', () => { + expect(isNumberInRange(0, 0, 50)).toBe(true); + expect(isNumberInRange(50, 0, 50)).toBe(true); + expect(isNumberInRange(-50.123_45, -50.123_45, 0)).toBe(true); + }); +}); + +describe('converts input to a number or null', () => { + it('returns null for invalid inputs', () => { + expect(toNumberOrNull(null)).toBeNull(); + // eslint-disable-next-line unicorn/no-useless-undefined + expect(toNumberOrNull(undefined)).toBeNull(); + expect(toNumberOrNull('')).toBeNull(); + expect(toNumberOrNull(Number.NaN)).toBeNull(); + }); + + it('returns a number for valid inputs', () => { + expect(toNumberOrNull(0)).toBeCloseTo(0); + expect(toNumberOrNull('0')).toBeCloseTo(0); + expect(toNumberOrNull('-123.45')).toBeCloseTo(-123.45); + }); +}); describe('parsing latitude from string input', () => { it('returns null for invalid inputs', () => { diff --git a/server/src/utils.ts b/server/src/utils.ts new file mode 100644 index 000000000..863dde7ca --- /dev/null +++ b/server/src/utils.ts @@ -0,0 +1,181 @@ +import { basename, extname } from 'node:path'; +import { ImmichLogger } from 'src/infra/logger'; + +const KiB = Math.pow(1024, 1); +const MiB = Math.pow(1024, 2); +const GiB = Math.pow(1024, 3); +const TiB = Math.pow(1024, 4); +const PiB = Math.pow(1024, 5); + +export const HumanReadableSize = { KiB, MiB, GiB, TiB, PiB }; + +export function asHumanReadable(bytes: number, precision = 1): string { + const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']; + + let magnitude = 0; + let remainder = bytes; + while (remainder >= 1024) { + if (magnitude + 1 < units.length) { + magnitude++; + remainder /= 1024; + } else { + break; + } + } + + return `${remainder.toFixed(magnitude == 0 ? 0 : precision)} ${units[magnitude]}`; +} + +export const isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED'; + +export function isDecimalNumber(number_: number): boolean { + return !Number.isNaN(number_) && Number.isFinite(number_); +} + +/** + * Check if `num` is a valid number and is between `start` and `end` (inclusive) + */ +export function isNumberInRange(number_: number, start: number, end: number): boolean { + return isDecimalNumber(number_) && number_ >= start && number_ <= end; +} + +export function toNumberOrNull(input: number | string | null | undefined): number | null { + if (input === null || input === undefined) { + return null; + } + + const number_ = typeof input === 'string' ? Number.parseFloat(input) : input; + return isDecimalNumber(number_) ? number_ : null; +} + +export function parseLatitude(input: string | number | null): number | null { + if (input === null) { + return null; + } + const latitude = typeof input === 'string' ? Number.parseFloat(input) : input; + + if (isNumberInRange(latitude, -90, 90)) { + return latitude; + } + return null; +} + +export function parseLongitude(input: string | number | null): number | null { + if (input === null) { + return null; + } + + const longitude = typeof input === 'string' ? Number.parseFloat(input) : input; + + if (isNumberInRange(longitude, -180, 180)) { + return longitude; + } + return null; +} + +// NOTE: The following Set utils have been added here, to easily determine where they are used. +// They should be replaced with native Set operations, when they are added to the language. +// Proposal reference: https://github.com/tc39/proposal-set-methods + +export const setUnion = (...sets: Set[]): Set => { + const union = new Set(sets[0]); + for (const set of sets.slice(1)) { + for (const element of set) { + union.add(element); + } + } + return union; +}; + +export const setDifference = (setA: Set, ...sets: Set[]): Set => { + const difference = new Set(setA); + for (const set of sets) { + for (const element of set) { + difference.delete(element); + } + } + return difference; +}; + +export const setIsSuperset = (set: Set, subset: Set): boolean => { + for (const element of subset) { + if (!set.has(element)) { + return false; + } + } + return true; +}; + +export const setIsEqual = (setA: Set, setB: Set): boolean => { + return setA.size === setB.size && setIsSuperset(setA, setB); +}; + +export const handlePromiseError = (promise: Promise, logger: ImmichLogger): void => { + promise.catch((error: Error | any) => logger.error(`Promise error: ${error}`, error?.stack)); +}; + +export enum CacheControl { + PRIVATE_WITH_CACHE = 'private_with_cache', + PRIVATE_WITHOUT_CACHE = 'private_without_cache', + NONE = 'none', +} + +export class ImmichFileResponse { + public readonly path!: string; + public readonly contentType!: string; + public readonly cacheControl!: CacheControl; + + constructor(response: ImmichFileResponse) { + Object.assign(this, response); + } +} + +export interface OpenGraphTags { + title: string; + description: string; + imageUrl?: string; +} + +export function getFileNameWithoutExtension(path: string): string { + return basename(path, extname(path)); +} + +export function getLivePhotoMotionFilename(stillName: string, motionName: string) { + return getFileNameWithoutExtension(stillName) + extname(motionName); +} + +export interface PaginationOptions { + take: number; + skip?: number; +} + +export enum PaginationMode { + LIMIT_OFFSET = 'limit-offset', + SKIP_TAKE = 'skip-take', +} + +export interface PaginatedBuilderOptions { + take: number; + skip?: number; + mode?: PaginationMode; +} + +export interface PaginationResult { + items: T[]; + hasNextPage: boolean; +} + +export type Paginated = Promise>; + +export async function* usePagination( + pageSize: number, + getNextPage: (pagination: PaginationOptions) => PaginationResult | Paginated, +) { + let hasNextPage = true; + + for (let skip = 0; hasNextPage; skip += pageSize) { + const result = await getNextPage({ take: pageSize, skip }); + hasNextPage = result.hasNextPage; + yield result.items; + } +} diff --git a/server/src/validation.ts b/server/src/validation.ts new file mode 100644 index 000000000..bc1dbae81 --- /dev/null +++ b/server/src/validation.ts @@ -0,0 +1,164 @@ +import { + ArgumentMetadata, + BadRequestException, + FileValidator, + Injectable, + ParseUUIDPipe, + applyDecorators, +} from '@nestjs/common'; +import { ApiProperty } from '@nestjs/swagger'; +import { Transform } from 'class-transformer'; +import { + IsArray, + IsBoolean, + IsDate, + IsNotEmpty, + IsOptional, + IsString, + IsUUID, + ValidateIf, + ValidationOptions, + isDateString, +} from 'class-validator'; +import { CronJob } from 'cron'; +import sanitize from 'sanitize-filename'; + +@Injectable() +export class ParseMeUUIDPipe extends ParseUUIDPipe { + async transform(value: string, metadata: ArgumentMetadata) { + if (value == 'me') { + return value; + } + return super.transform(value, metadata); + } +} + +@Injectable() +export class FileNotEmptyValidator extends FileValidator { + constructor(private requiredFields: string[]) { + super({}); + this.requiredFields = requiredFields; + } + + isValid(files?: any): boolean { + if (!files) { + return false; + } + + return this.requiredFields.every((field) => files[field]); + } + + buildErrorMessage(): string { + return `Field(s) ${this.requiredFields.join(', ')} should not be empty`; + } +} + +export class UUIDParamDto { + @IsNotEmpty() + @IsUUID('4') + @ApiProperty({ format: 'uuid' }) + id!: string; +} + +export interface OptionalOptions extends ValidationOptions { + nullable?: boolean; +} + +/** + * Checks if value is missing and if so, ignores all validators. + * + * @param validationOptions {@link OptionalOptions} + * + * @see IsOptional exported from `class-validator. + */ +// https://stackoverflow.com/a/71353929 +export function Optional({ nullable, ...validationOptions }: OptionalOptions = {}) { + if (nullable === true) { + return IsOptional(validationOptions); + } + + return ValidateIf((object: any, v: any) => v !== undefined, validationOptions); +} + +type UUIDOptions = { optional?: boolean; each?: boolean }; +export const ValidateUUID = (options?: UUIDOptions) => { + const { optional, each } = { optional: false, each: false, ...options }; + return applyDecorators( + IsUUID('4', { each }), + ApiProperty({ format: 'uuid' }), + optional ? Optional() : IsNotEmpty(), + each ? IsArray() : IsString(), + ); +}; + +type DateOptions = { optional?: boolean; nullable?: boolean; format?: 'date' | 'date-time' }; +export const ValidateDate = (options?: DateOptions) => { + const { optional, nullable, format } = { optional: false, nullable: false, format: 'date-time', ...options }; + + const decorators = [ + ApiProperty({ format }), + IsDate(), + optional ? Optional({ nullable: true }) : IsNotEmpty(), + Transform(({ key, value }) => { + if (value === null || value === undefined) { + return value; + } + + if (!isDateString(value)) { + throw new BadRequestException(`${key} must be a date string`); + } + + return new Date(value as string); + }), + ]; + + if (optional) { + decorators.push(Optional({ nullable })); + } + + return applyDecorators(...decorators); +}; + +type BooleanOptions = { optional?: boolean }; +export const ValidateBoolean = (options?: BooleanOptions) => { + const { optional } = { optional: false, ...options }; + const decorators = [ + // ApiProperty(), + IsBoolean(), + Transform(({ value }) => { + if (value == 'true') { + return true; + } else if (value == 'false') { + return false; + } + return value; + }), + ]; + + if (optional) { + decorators.push(Optional()); + } + + return applyDecorators(...decorators); +}; + +export function validateCronExpression(expression: string) { + try { + new CronJob(expression, () => {}); + } catch { + return false; + } + + return true; +} + +type IValue = { value: string }; + +export const toEmail = ({ value }: IValue) => value?.toLowerCase(); + +export const toSanitized = ({ value }: IValue) => sanitize((value || '').replaceAll('.', '')); + +export const isValidInteger = (value: number, options: { min?: number; max?: number }): value is number => { + const { min = Number.MIN_SAFE_INTEGER, max = Number.MAX_SAFE_INTEGER } = options; + return Number.isInteger(value) && value >= min && value <= max; +}; From 40e079a247f29dedb7d3e55a7b7954a873300d28 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 20 Mar 2024 15:15:01 -0500 Subject: [PATCH 033/152] chore: move controllers and middleware (#8119) --- server/e2e/jobs/specs/library.e2e-spec.ts | 2 +- .../controllers/activity.controller.ts | 2 +- .../controllers/album.controller.ts | 2 +- .../controllers/api-key.controller.ts | 2 +- .../controllers/app.controller.ts | 2 +- .../controllers/asset.controller.ts | 4 +- .../controllers/audit.controller.ts | 2 +- .../controllers/auth.controller.ts | 2 +- .../controllers/download.controller.ts | 2 +- .../controllers/face.controller.ts | 2 +- .../controllers/job.controller.ts | 2 +- .../controllers/library.controller.ts | 2 +- .../controllers/oauth.controller.ts | 2 +- .../controllers/partner.controller.ts | 2 +- .../controllers/person.controller.ts | 2 +- .../controllers/search.controller.ts | 2 +- .../controllers/server-info.controller.ts | 2 +- .../controllers/shared-link.controller.ts | 2 +- .../controllers/system-config.controller.ts | 2 +- .../controllers/tag.controller.ts | 2 +- .../controllers/trash.controller.ts | 2 +- .../controllers/user.controller.ts | 4 +- .../immich/api-v1/asset/asset.controller.ts | 9 +--- server/src/immich/app.module.ts | 50 +++++++++---------- server/src/immich/app.utils.ts | 2 +- .../app.guard.ts => middleware/auth.guard.ts} | 4 +- .../error.interceptor.ts | 0 .../file-upload.interceptor.ts | 2 +- 28 files changed, 55 insertions(+), 60 deletions(-) rename server/src/{immich => }/controllers/activity.controller.ts (95%) rename server/src/{immich => }/controllers/album.controller.ts (97%) rename server/src/{immich => }/controllers/api-key.controller.ts (95%) rename server/src/{immich => }/controllers/app.controller.ts (91%) rename server/src/{immich => }/controllers/asset.controller.ts (96%) rename server/src/{immich => }/controllers/audit.controller.ts (93%) rename server/src/{immich => }/controllers/auth.controller.ts (98%) rename server/src/{immich => }/controllers/download.controller.ts (98%) rename server/src/{immich => }/controllers/face.controller.ts (93%) rename server/src/{immich => }/controllers/job.controller.ts (92%) rename server/src/{immich => }/controllers/library.controller.ts (96%) rename server/src/{immich => }/controllers/oauth.controller.ts (98%) rename server/src/{immich => }/controllers/partner.controller.ts (95%) rename server/src/{immich => }/controllers/person.controller.ts (97%) rename server/src/{immich => }/controllers/search.controller.ts (97%) rename server/src/{immich => }/controllers/server-info.controller.ts (95%) rename server/src/{immich => }/controllers/shared-link.controller.ts (97%) rename server/src/{immich => }/controllers/system-config.controller.ts (94%) rename server/src/{immich => }/controllers/tag.controller.ts (97%) rename server/src/{immich => }/controllers/trash.controller.ts (93%) rename server/src/{immich => }/controllers/user.controller.ts (96%) rename server/src/{immich/app.guard.ts => middleware/auth.guard.ts} (97%) rename server/src/{immich/interceptors => middleware}/error.interceptor.ts (100%) rename server/src/{immich/interceptors => middleware}/file-upload.interceptor.ts (98%) diff --git a/server/e2e/jobs/specs/library.e2e-spec.ts b/server/e2e/jobs/specs/library.e2e-spec.ts index 24d7a620b..f67dd9178 100644 --- a/server/e2e/jobs/specs/library.e2e-spec.ts +++ b/server/e2e/jobs/specs/library.e2e-spec.ts @@ -1,7 +1,7 @@ import { api } from 'e2e/client'; import fs from 'node:fs'; +import { LibraryController } from 'src/controllers/library.controller'; import { LoginResponseDto } from 'src/domain/auth/auth.dto'; -import { LibraryController } from 'src/immich/controllers/library.controller'; import { LibraryType } from 'src/infra/entities/library.entity'; import { IMMICH_TEST_ASSET_PATH, IMMICH_TEST_ASSET_TEMP_PATH, restoreTempFolder, testApp } from 'src/test-utils/utils'; import request from 'supertest'; diff --git a/server/src/immich/controllers/activity.controller.ts b/server/src/controllers/activity.controller.ts similarity index 95% rename from server/src/immich/controllers/activity.controller.ts rename to server/src/controllers/activity.controller.ts index 45f58e9f2..c405b0c6f 100644 --- a/server/src/immich/controllers/activity.controller.ts +++ b/server/src/controllers/activity.controller.ts @@ -10,7 +10,7 @@ import { } from 'src/domain/activity/activity.dto'; import { ActivityService } from 'src/domain/activity/activity.service'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { Auth, Authenticated } from 'src/immich/app.guard'; +import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Activity') diff --git a/server/src/immich/controllers/album.controller.ts b/server/src/controllers/album.controller.ts similarity index 97% rename from server/src/immich/controllers/album.controller.ts rename to server/src/controllers/album.controller.ts index 12e35a0f6..18fd549b6 100644 --- a/server/src/immich/controllers/album.controller.ts +++ b/server/src/controllers/album.controller.ts @@ -9,7 +9,7 @@ import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; import { BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; +import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; import { ParseMeUUIDPipe, UUIDParamDto } from 'src/validation'; @ApiTags('Album') diff --git a/server/src/immich/controllers/api-key.controller.ts b/server/src/controllers/api-key.controller.ts similarity index 95% rename from server/src/immich/controllers/api-key.controller.ts rename to server/src/controllers/api-key.controller.ts index 96afe676d..2d4f8db15 100644 --- a/server/src/immich/controllers/api-key.controller.ts +++ b/server/src/controllers/api-key.controller.ts @@ -8,7 +8,7 @@ import { } from 'src/domain/api-key/api-key.dto'; import { APIKeyService } from 'src/domain/api-key/api-key.service'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { Auth, Authenticated } from 'src/immich/app.guard'; +import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('API Key') diff --git a/server/src/immich/controllers/app.controller.ts b/server/src/controllers/app.controller.ts similarity index 91% rename from server/src/immich/controllers/app.controller.ts rename to server/src/controllers/app.controller.ts index 0e916cd25..d4c7ea5b4 100644 --- a/server/src/immich/controllers/app.controller.ts +++ b/server/src/controllers/app.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Header } from '@nestjs/common'; import { ApiExcludeEndpoint } from '@nestjs/swagger'; import { SystemConfigService } from 'src/domain/system-config/system-config.service'; -import { PublicRoute } from 'src/immich/app.guard'; +import { PublicRoute } from 'src/middleware/auth.guard'; @Controller() export class AppController { diff --git a/server/src/immich/controllers/asset.controller.ts b/server/src/controllers/asset.controller.ts similarity index 96% rename from server/src/immich/controllers/asset.controller.ts rename to server/src/controllers/asset.controller.ts index ee35c98dd..a6db59815 100644 --- a/server/src/immich/controllers/asset.controller.ts +++ b/server/src/controllers/asset.controller.ts @@ -20,8 +20,8 @@ import { TimeBucketResponseDto } from 'src/domain/asset/response-dto/time-bucket import { AuthDto } from 'src/domain/auth/auth.dto'; import { MetadataSearchDto } from 'src/domain/search/dto/search.dto'; import { SearchService } from 'src/domain/search/search.service'; -import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; -import { Route } from 'src/immich/interceptors/file-upload.interceptor'; +import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; +import { Route } from 'src/middleware/file-upload.interceptor'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Asset') diff --git a/server/src/immich/controllers/audit.controller.ts b/server/src/controllers/audit.controller.ts similarity index 93% rename from server/src/immich/controllers/audit.controller.ts rename to server/src/controllers/audit.controller.ts index 468257d26..bb92f990e 100644 --- a/server/src/immich/controllers/audit.controller.ts +++ b/server/src/controllers/audit.controller.ts @@ -10,7 +10,7 @@ import { } from 'src/domain/audit/audit.dto'; import { AuditService } from 'src/domain/audit/audit.service'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { AdminRoute, Auth, Authenticated } from 'src/immich/app.guard'; +import { AdminRoute, Auth, Authenticated } from 'src/middleware/auth.guard'; @ApiTags('Audit') @Controller('audit') diff --git a/server/src/immich/controllers/auth.controller.ts b/server/src/controllers/auth.controller.ts similarity index 98% rename from server/src/immich/controllers/auth.controller.ts rename to server/src/controllers/auth.controller.ts index 7f9fea47c..941002fe6 100644 --- a/server/src/immich/controllers/auth.controller.ts +++ b/server/src/controllers/auth.controller.ts @@ -14,7 +14,7 @@ import { } from 'src/domain/auth/auth.dto'; import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/immich/app.guard'; +import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Authentication') diff --git a/server/src/immich/controllers/download.controller.ts b/server/src/controllers/download.controller.ts similarity index 98% rename from server/src/immich/controllers/download.controller.ts rename to server/src/controllers/download.controller.ts index 0cfaa3ea8..0fb3520cf 100644 --- a/server/src/immich/controllers/download.controller.ts +++ b/server/src/controllers/download.controller.ts @@ -5,8 +5,8 @@ import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/download.dto'; import { DownloadService } from 'src/domain/download/download.service'; -import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/immich/app.guard'; import { asStreamableFile, sendFile } from 'src/immich/app.utils'; +import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Download') diff --git a/server/src/immich/controllers/face.controller.ts b/server/src/controllers/face.controller.ts similarity index 93% rename from server/src/immich/controllers/face.controller.ts rename to server/src/controllers/face.controller.ts index e7d1c3fba..c7caba016 100644 --- a/server/src/immich/controllers/face.controller.ts +++ b/server/src/controllers/face.controller.ts @@ -3,7 +3,7 @@ import { ApiTags } from '@nestjs/swagger'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { AssetFaceResponseDto, FaceDto, PersonResponseDto } from 'src/domain/person/person.dto'; import { PersonService } from 'src/domain/person/person.service'; -import { Auth, Authenticated } from 'src/immich/app.guard'; +import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Face') diff --git a/server/src/immich/controllers/job.controller.ts b/server/src/controllers/job.controller.ts similarity index 92% rename from server/src/immich/controllers/job.controller.ts rename to server/src/controllers/job.controller.ts index e5a8aac54..f0e9ed2be 100644 --- a/server/src/immich/controllers/job.controller.ts +++ b/server/src/controllers/job.controller.ts @@ -2,7 +2,7 @@ import { Body, Controller, Get, Param, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobStatusDto } from 'src/domain/job/job.dto'; import { JobService } from 'src/domain/job/job.service'; -import { Authenticated } from 'src/immich/app.guard'; +import { Authenticated } from 'src/middleware/auth.guard'; @ApiTags('Job') @Controller('jobs') diff --git a/server/src/immich/controllers/library.controller.ts b/server/src/controllers/library.controller.ts similarity index 96% rename from server/src/immich/controllers/library.controller.ts rename to server/src/controllers/library.controller.ts index 5e362f6d0..677773f2d 100644 --- a/server/src/immich/controllers/library.controller.ts +++ b/server/src/controllers/library.controller.ts @@ -11,7 +11,7 @@ import { ValidateLibraryResponseDto, } from 'src/domain/library/library.dto'; import { LibraryService } from 'src/domain/library/library.service'; -import { AdminRoute, Authenticated } from 'src/immich/app.guard'; +import { AdminRoute, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Library') diff --git a/server/src/immich/controllers/oauth.controller.ts b/server/src/controllers/oauth.controller.ts similarity index 98% rename from server/src/immich/controllers/oauth.controller.ts rename to server/src/controllers/oauth.controller.ts index 8d7ce9478..48b3eafd5 100644 --- a/server/src/immich/controllers/oauth.controller.ts +++ b/server/src/controllers/oauth.controller.ts @@ -10,7 +10,7 @@ import { } from 'src/domain/auth/auth.dto'; import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; -import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/immich/app.guard'; +import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard'; @ApiTags('OAuth') @Controller('oauth') diff --git a/server/src/immich/controllers/partner.controller.ts b/server/src/controllers/partner.controller.ts similarity index 95% rename from server/src/immich/controllers/partner.controller.ts rename to server/src/controllers/partner.controller.ts index c6bfea355..b756ade3e 100644 --- a/server/src/immich/controllers/partner.controller.ts +++ b/server/src/controllers/partner.controller.ts @@ -4,7 +4,7 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; import { PartnerService } from 'src/domain/partner/partner.service'; import { PartnerDirection } from 'src/domain/repositories/partner.repository'; -import { Auth, Authenticated } from 'src/immich/app.guard'; +import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Partner') diff --git a/server/src/immich/controllers/person.controller.ts b/server/src/controllers/person.controller.ts similarity index 97% rename from server/src/immich/controllers/person.controller.ts rename to server/src/controllers/person.controller.ts index 9ef791c3c..bc955fd2c 100644 --- a/server/src/immich/controllers/person.controller.ts +++ b/server/src/controllers/person.controller.ts @@ -16,8 +16,8 @@ import { PersonUpdateDto, } from 'src/domain/person/person.dto'; import { PersonService } from 'src/domain/person/person.service'; -import { Auth, Authenticated, FileResponse } from 'src/immich/app.guard'; import { sendFile } from 'src/immich/app.utils'; +import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Person') diff --git a/server/src/immich/controllers/search.controller.ts b/server/src/controllers/search.controller.ts similarity index 97% rename from server/src/immich/controllers/search.controller.ts rename to server/src/controllers/search.controller.ts index 4f8f19fd8..76fce1609 100644 --- a/server/src/immich/controllers/search.controller.ts +++ b/server/src/controllers/search.controller.ts @@ -15,7 +15,7 @@ import { import { SearchExploreResponseDto } from 'src/domain/search/response-dto/search-explore.response.dto'; import { SearchResponseDto } from 'src/domain/search/response-dto/search-response.dto'; import { SearchService } from 'src/domain/search/search.service'; -import { Auth, Authenticated } from 'src/immich/app.guard'; +import { Auth, Authenticated } from 'src/middleware/auth.guard'; @ApiTags('Search') @Controller('search') diff --git a/server/src/immich/controllers/server-info.controller.ts b/server/src/controllers/server-info.controller.ts similarity index 95% rename from server/src/immich/controllers/server-info.controller.ts rename to server/src/controllers/server-info.controller.ts index 5ff3de55e..aae617493 100644 --- a/server/src/immich/controllers/server-info.controller.ts +++ b/server/src/controllers/server-info.controller.ts @@ -11,7 +11,7 @@ import { ServerVersionResponseDto, } from 'src/domain/server-info/server-info.dto'; import { ServerInfoService } from 'src/domain/server-info/server-info.service'; -import { AdminRoute, Authenticated, PublicRoute } from 'src/immich/app.guard'; +import { AdminRoute, Authenticated, PublicRoute } from 'src/middleware/auth.guard'; @ApiTags('Server Info') @Controller('server-info') diff --git a/server/src/immich/controllers/shared-link.controller.ts b/server/src/controllers/shared-link.controller.ts similarity index 97% rename from server/src/immich/controllers/shared-link.controller.ts rename to server/src/controllers/shared-link.controller.ts index b0717026c..1e03a5c42 100644 --- a/server/src/immich/controllers/shared-link.controller.ts +++ b/server/src/controllers/shared-link.controller.ts @@ -8,7 +8,7 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; import { SharedLinkResponseDto } from 'src/domain/shared-link/shared-link-response.dto'; import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; -import { Auth, Authenticated, SharedLinkRoute } from 'src/immich/app.guard'; +import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Shared Link') diff --git a/server/src/immich/controllers/system-config.controller.ts b/server/src/controllers/system-config.controller.ts similarity index 94% rename from server/src/immich/controllers/system-config.controller.ts rename to server/src/controllers/system-config.controller.ts index 6d1ea8f1d..d10bccee0 100644 --- a/server/src/immich/controllers/system-config.controller.ts +++ b/server/src/controllers/system-config.controller.ts @@ -4,7 +4,7 @@ import { SystemConfigDto } from 'src/domain/system-config/dto/system-config.dto' import { SystemConfigTemplateStorageOptionDto } from 'src/domain/system-config/response-dto/system-config-template-storage-option.dto'; import { MapThemeDto } from 'src/domain/system-config/system-config-map-theme.dto'; import { SystemConfigService } from 'src/domain/system-config/system-config.service'; -import { AdminRoute, Authenticated } from 'src/immich/app.guard'; +import { AdminRoute, Authenticated } from 'src/middleware/auth.guard'; @ApiTags('System Config') @Controller('system-config') diff --git a/server/src/immich/controllers/tag.controller.ts b/server/src/controllers/tag.controller.ts similarity index 97% rename from server/src/immich/controllers/tag.controller.ts rename to server/src/controllers/tag.controller.ts index 99715d5c7..e914e577e 100644 --- a/server/src/immich/controllers/tag.controller.ts +++ b/server/src/controllers/tag.controller.ts @@ -7,7 +7,7 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; import { TagResponseDto } from 'src/domain/tag/tag-response.dto'; import { CreateTagDto, UpdateTagDto } from 'src/domain/tag/tag.dto'; import { TagService } from 'src/domain/tag/tag.service'; -import { Auth, Authenticated } from 'src/immich/app.guard'; +import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Tag') diff --git a/server/src/immich/controllers/trash.controller.ts b/server/src/controllers/trash.controller.ts similarity index 93% rename from server/src/immich/controllers/trash.controller.ts rename to server/src/controllers/trash.controller.ts index 44d68abbe..2c0b0c946 100644 --- a/server/src/immich/controllers/trash.controller.ts +++ b/server/src/controllers/trash.controller.ts @@ -3,7 +3,7 @@ import { ApiTags } from '@nestjs/swagger'; import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { TrashService } from 'src/domain/trash/trash.service'; -import { Auth, Authenticated } from 'src/immich/app.guard'; +import { Auth, Authenticated } from 'src/middleware/auth.guard'; @ApiTags('Trash') @Controller('trash') diff --git a/server/src/immich/controllers/user.controller.ts b/server/src/controllers/user.controller.ts similarity index 96% rename from server/src/immich/controllers/user.controller.ts rename to server/src/controllers/user.controller.ts index 3f80765a9..e573584ad 100644 --- a/server/src/immich/controllers/user.controller.ts +++ b/server/src/controllers/user.controller.ts @@ -24,9 +24,9 @@ import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; import { CreateProfileImageResponseDto } from 'src/domain/user/response-dto/create-profile-image-response.dto'; import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; import { UserService } from 'src/domain/user/user.service'; -import { AdminRoute, Auth, Authenticated, FileResponse } from 'src/immich/app.guard'; import { sendFile } from 'src/immich/app.utils'; -import { FileUploadInterceptor, Route } from 'src/immich/interceptors/file-upload.interceptor'; +import { AdminRoute, Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; +import { FileUploadInterceptor, Route } from 'src/middleware/file-upload.interceptor'; import { UUIDParamDto } from 'src/validation'; @ApiTags('User') diff --git a/server/src/immich/api-v1/asset/asset.controller.ts b/server/src/immich/api-v1/asset/asset.controller.ts index 0496c75be..d29f61fdd 100644 --- a/server/src/immich/api-v1/asset/asset.controller.ts +++ b/server/src/immich/api-v1/asset/asset.controller.ts @@ -29,14 +29,9 @@ import { AssetFileUploadResponseDto } from 'src/immich/api-v1/asset/response-dto import { CheckExistingAssetsResponseDto } from 'src/immich/api-v1/asset/response-dto/check-existing-assets-response.dto'; import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; -import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/immich/app.guard'; import { sendFile } from 'src/immich/app.utils'; -import { - FileUploadInterceptor, - ImmichFile, - Route, - mapToUploadFile, -} from 'src/immich/interceptors/file-upload.interceptor'; +import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/middleware/auth.guard'; +import { FileUploadInterceptor, ImmichFile, Route, mapToUploadFile } from 'src/middleware/file-upload.interceptor'; import { FileNotEmptyValidator, UUIDParamDto } from 'src/validation'; interface UploadFiles { diff --git a/server/src/immich/app.module.ts b/server/src/immich/app.module.ts index ba263622f..66edf2341 100644 --- a/server/src/immich/app.module.ts +++ b/server/src/immich/app.module.ts @@ -2,38 +2,38 @@ import { Module, OnModuleInit, ValidationPipe } from '@nestjs/common'; import { APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core'; import { ScheduleModule } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { ActivityController } from 'src/controllers/activity.controller'; +import { AlbumController } from 'src/controllers/album.controller'; +import { APIKeyController } from 'src/controllers/api-key.controller'; +import { AppController } from 'src/controllers/app.controller'; +import { AssetController, AssetsController } from 'src/controllers/asset.controller'; +import { AuditController } from 'src/controllers/audit.controller'; +import { AuthController } from 'src/controllers/auth.controller'; +import { DownloadController } from 'src/controllers/download.controller'; +import { FaceController } from 'src/controllers/face.controller'; +import { JobController } from 'src/controllers/job.controller'; +import { LibraryController } from 'src/controllers/library.controller'; +import { OAuthController } from 'src/controllers/oauth.controller'; +import { PartnerController } from 'src/controllers/partner.controller'; +import { PersonController } from 'src/controllers/person.controller'; +import { SearchController } from 'src/controllers/search.controller'; +import { ServerInfoController } from 'src/controllers/server-info.controller'; +import { SharedLinkController } from 'src/controllers/shared-link.controller'; +import { SystemConfigController } from 'src/controllers/system-config.controller'; +import { TagController } from 'src/controllers/tag.controller'; +import { TrashController } from 'src/controllers/trash.controller'; +import { UserController } from 'src/controllers/user.controller'; import { DomainModule } from 'src/domain/domain.module'; import { AssetRepositoryV1, IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; import { AssetController as AssetControllerV1 } from 'src/immich/api-v1/asset/asset.controller'; import { AssetService as AssetServiceV1 } from 'src/immich/api-v1/asset/asset.service'; -import { AppGuard } from 'src/immich/app.guard'; import { AppService } from 'src/immich/app.service'; -import { ActivityController } from 'src/immich/controllers/activity.controller'; -import { AlbumController } from 'src/immich/controllers/album.controller'; -import { APIKeyController } from 'src/immich/controllers/api-key.controller'; -import { AppController } from 'src/immich/controllers/app.controller'; -import { AssetController, AssetsController } from 'src/immich/controllers/asset.controller'; -import { AuditController } from 'src/immich/controllers/audit.controller'; -import { AuthController } from 'src/immich/controllers/auth.controller'; -import { DownloadController } from 'src/immich/controllers/download.controller'; -import { FaceController } from 'src/immich/controllers/face.controller'; -import { JobController } from 'src/immich/controllers/job.controller'; -import { LibraryController } from 'src/immich/controllers/library.controller'; -import { OAuthController } from 'src/immich/controllers/oauth.controller'; -import { PartnerController } from 'src/immich/controllers/partner.controller'; -import { PersonController } from 'src/immich/controllers/person.controller'; -import { SearchController } from 'src/immich/controllers/search.controller'; -import { ServerInfoController } from 'src/immich/controllers/server-info.controller'; -import { SharedLinkController } from 'src/immich/controllers/shared-link.controller'; -import { SystemConfigController } from 'src/immich/controllers/system-config.controller'; -import { TagController } from 'src/immich/controllers/tag.controller'; -import { TrashController } from 'src/immich/controllers/trash.controller'; -import { UserController } from 'src/immich/controllers/user.controller'; -import { ErrorInterceptor } from 'src/immich/interceptors/error.interceptor'; -import { FileUploadInterceptor } from 'src/immich/interceptors/file-upload.interceptor'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; import { InfraModule } from 'src/infra/infra.module'; +import { AuthGuard } from 'src/middleware/auth.guard'; +import { ErrorInterceptor } from 'src/middleware/error.interceptor'; +import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor'; @Module({ imports: [ @@ -71,7 +71,7 @@ import { InfraModule } from 'src/infra/infra.module'; providers: [ { provide: APP_PIPE, useValue: new ValidationPipe({ transform: true, whitelist: true }) }, { provide: APP_INTERCEPTOR, useClass: ErrorInterceptor }, - { provide: APP_GUARD, useClass: AppGuard }, + { provide: APP_GUARD, useClass: AuthGuard }, { provide: IAssetRepositoryV1, useClass: AssetRepositoryV1 }, AppService, AssetServiceV1, diff --git a/server/src/immich/app.utils.ts b/server/src/immich/app.utils.ts index 48f01d8dd..456c9cf4e 100644 --- a/server/src/immich/app.utils.ts +++ b/server/src/immich/app.utils.ts @@ -16,8 +16,8 @@ import { promisify } from 'node:util'; import { IMMICH_ACCESS_COOKIE, IMMICH_API_KEY_HEADER, IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; import { serverVersion } from 'src/domain/domain.constant'; import { ImmichReadStream } from 'src/domain/repositories/storage.repository'; -import { Metadata } from 'src/immich/app.guard'; import { ImmichLogger } from 'src/infra/logger'; +import { Metadata } from 'src/middleware/auth.guard'; import { CacheControl, ImmichFileResponse, isConnectionAborted } from 'src/utils'; type SendFile = Parameters; diff --git a/server/src/immich/app.guard.ts b/server/src/middleware/auth.guard.ts similarity index 97% rename from server/src/immich/app.guard.ts rename to server/src/middleware/auth.guard.ts index e465f1d40..070bf15e8 100644 --- a/server/src/immich/app.guard.ts +++ b/server/src/middleware/auth.guard.ts @@ -78,8 +78,8 @@ export interface AuthRequest extends Request { } @Injectable() -export class AppGuard implements CanActivate { - private logger = new ImmichLogger(AppGuard.name); +export class AuthGuard implements CanActivate { + private logger = new ImmichLogger(AuthGuard.name); constructor( private reflector: Reflector, diff --git a/server/src/immich/interceptors/error.interceptor.ts b/server/src/middleware/error.interceptor.ts similarity index 100% rename from server/src/immich/interceptors/error.interceptor.ts rename to server/src/middleware/error.interceptor.ts diff --git a/server/src/immich/interceptors/file-upload.interceptor.ts b/server/src/middleware/file-upload.interceptor.ts similarity index 98% rename from server/src/immich/interceptors/file-upload.interceptor.ts rename to server/src/middleware/file-upload.interceptor.ts index 9284ade39..a7598f99d 100644 --- a/server/src/immich/interceptors/file-upload.interceptor.ts +++ b/server/src/middleware/file-upload.interceptor.ts @@ -7,8 +7,8 @@ import multer, { StorageEngine, diskStorage } from 'multer'; import { createHash, randomUUID } from 'node:crypto'; import { Observable } from 'rxjs'; import { AssetService, UploadFieldName, UploadFile } from 'src/domain/asset/asset.service'; -import { AuthRequest } from 'src/immich/app.guard'; import { ImmichLogger } from 'src/infra/logger'; +import { AuthRequest } from 'src/middleware/auth.guard'; export enum Route { ASSET = 'asset', From 4b29bccc7c693983d25279e43cebf27ebd27f95f Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Wed, 20 Mar 2024 21:20:38 +0100 Subject: [PATCH 034/152] chore(server): move cores (#8120) move cores --- server/src/{domain/access => cores}/access.core.ts | 0 server/src/{domain/storage => cores}/storage.core.ts | 2 +- .../{domain/system-config => cores}/system-config.core.ts | 0 server/src/{domain/user => cores}/user.core.ts | 0 server/src/domain/activity/activity.service.ts | 2 +- server/src/domain/album/album.service.ts | 2 +- server/src/domain/asset/asset.service.ts | 6 +++--- server/src/domain/audit/audit.service.ts | 4 ++-- server/src/domain/auth/auth.service.ts | 6 +++--- server/src/domain/download/download.service.ts | 2 +- server/src/domain/job/job.service.spec.ts | 2 +- server/src/domain/job/job.service.ts | 2 +- server/src/domain/library/library.service.spec.ts | 2 +- server/src/domain/library/library.service.ts | 4 ++-- server/src/domain/media/media.service.ts | 4 ++-- server/src/domain/metadata/metadata.service.ts | 4 ++-- server/src/domain/partner/partner.service.ts | 2 +- server/src/domain/person/person.service.ts | 6 +++--- server/src/domain/search/search.service.ts | 2 +- server/src/domain/server-info/server-info.dto.ts | 2 +- server/src/domain/server-info/server-info.service.ts | 4 ++-- server/src/domain/shared-link/shared-link.service.ts | 2 +- server/src/domain/smart-info/smart-info.service.ts | 2 +- .../storage-template/storage-template.service.spec.ts | 2 +- .../src/domain/storage-template/storage-template.service.ts | 4 ++-- server/src/domain/storage/storage.service.ts | 2 +- .../src/domain/system-config/system-config.service.spec.ts | 2 +- server/src/domain/system-config/system-config.service.ts | 2 +- server/src/domain/trash/trash.service.ts | 2 +- server/src/domain/user/user.service.ts | 6 +++--- server/src/immich/api-v1/asset/asset.service.ts | 2 +- server/test/fixtures/library.stub.ts | 2 +- server/test/repositories/access.repository.mock.ts | 2 +- server/test/repositories/storage.repository.mock.ts | 2 +- server/test/repositories/system-config.repository.mock.ts | 2 +- server/test/repositories/user.repository.mock.ts | 2 +- 36 files changed, 47 insertions(+), 47 deletions(-) rename server/src/{domain/access => cores}/access.core.ts (100%) rename server/src/{domain/storage => cores}/storage.core.ts (99%) rename server/src/{domain/system-config => cores}/system-config.core.ts (100%) rename server/src/{domain/user => cores}/user.core.ts (100%) diff --git a/server/src/domain/access/access.core.ts b/server/src/cores/access.core.ts similarity index 100% rename from server/src/domain/access/access.core.ts rename to server/src/cores/access.core.ts diff --git a/server/src/domain/storage/storage.core.ts b/server/src/cores/storage.core.ts similarity index 99% rename from server/src/domain/storage/storage.core.ts rename to server/src/cores/storage.core.ts index 1768227ea..4e501dd83 100644 --- a/server/src/domain/storage/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -1,4 +1,5 @@ import { dirname, join, resolve } from 'node:path'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; @@ -6,7 +7,6 @@ import { IMoveRepository } from 'src/domain/repositories/move.repository'; import { IPersonRepository } from 'src/domain/repositories/person.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { AssetPathType, PathType, PersonPathType } from 'src/infra/entities/move.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; diff --git a/server/src/domain/system-config/system-config.core.ts b/server/src/cores/system-config.core.ts similarity index 100% rename from server/src/domain/system-config/system-config.core.ts rename to server/src/cores/system-config.core.ts diff --git a/server/src/domain/user/user.core.ts b/server/src/cores/user.core.ts similarity index 100% rename from server/src/domain/user/user.core.ts rename to server/src/cores/user.core.ts diff --git a/server/src/domain/activity/activity.service.ts b/server/src/domain/activity/activity.service.ts index f8727141c..cc1fef2c1 100644 --- a/server/src/domain/activity/activity.service.ts +++ b/server/src/domain/activity/activity.service.ts @@ -1,5 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; import { ActivityCreateDto, ActivityDto, diff --git a/server/src/domain/album/album.service.ts b/server/src/domain/album/album.service.ts index d54680fe4..5cd026cb3 100644 --- a/server/src/domain/album/album.service.ts +++ b/server/src/domain/album/album.service.ts @@ -1,5 +1,5 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; import { AlbumCountResponseDto, AlbumResponseDto, diff --git a/server/src/domain/asset/asset.service.ts b/server/src/domain/asset/asset.service.ts index 2d514a937..d6d2d76fb 100644 --- a/server/src/domain/asset/asset.service.ts +++ b/server/src/domain/asset/asset.service.ts @@ -3,7 +3,9 @@ import _ from 'lodash'; import { DateTime, Duration } from 'luxon'; import { extname } from 'node:path'; import sanitize from 'sanitize-filename'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; +import { StorageCore, StorageFolder } from 'src/cores/storage.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { AssetJobName, AssetJobsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { UpdateStackParentDto } from 'src/domain/asset/dto/asset-stack.dto'; import { AssetStatsDto, mapStats } from 'src/domain/asset/dto/asset-statistics.dto'; @@ -32,8 +34,6 @@ import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { IUserRepository } from 'src/domain/repositories/user.repository'; -import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/audit/audit.service.ts b/server/src/domain/audit/audit.service.ts index c72d1d8cf..d375aa082 100644 --- a/server/src/domain/audit/audit.service.ts +++ b/server/src/domain/audit/audit.service.ts @@ -1,7 +1,8 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; import { resolve } from 'node:path'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; +import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { AuditDeletesDto, AuditDeletesResponseDto, @@ -21,7 +22,6 @@ import { JobStatus } from 'src/domain/repositories/job.repository'; import { IPersonRepository } from 'src/domain/repositories/person.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { IUserRepository } from 'src/domain/repositories/user.repository'; -import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; import { DatabaseAction } from 'src/infra/entities/audit.entity'; import { AssetPathType, PersonPathType, UserPathType } from 'src/infra/entities/move.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/auth/auth.service.ts b/server/src/domain/auth/auth.service.ts index e66a6d0d7..bad578013 100644 --- a/server/src/domain/auth/auth.service.ts +++ b/server/src/domain/auth/auth.service.ts @@ -10,7 +10,9 @@ import cookieParser from 'cookie'; import { DateTime } from 'luxon'; import { IncomingHttpHeaders } from 'node:http'; import { ClientMetadata, Issuer, UserinfoResponse, custom, generators } from 'openid-client'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; +import { UserCore } from 'src/cores/user.core'; import { AuthType, IMMICH_ACCESS_COOKIE, @@ -42,9 +44,7 @@ import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repos import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; import { IUserRepository } from 'src/domain/repositories/user.repository'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { UserCore } from 'src/domain/user/user.core'; import { SystemConfig } from 'src/infra/entities/system-config.entity'; import { UserEntity } from 'src/infra/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/download/download.service.ts b/server/src/domain/download/download.service.ts index 13f513c9b..7a0fc2ca6 100644 --- a/server/src/domain/download/download.service.ts +++ b/server/src/domain/download/download.service.ts @@ -1,6 +1,6 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { parse } from 'node:path'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; diff --git a/server/src/domain/job/job.service.spec.ts b/server/src/domain/job/job.service.spec.ts index 7fc8cc86e..2dee51cd6 100644 --- a/server/src/domain/job/job.service.spec.ts +++ b/server/src/domain/job/job.service.spec.ts @@ -1,4 +1,5 @@ import { BadRequestException } from '@nestjs/common'; +import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; import { JobService } from 'src/domain/job/job.service'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; @@ -6,7 +7,6 @@ import { ICommunicationRepository } from 'src/domain/repositories/communication. import { IJobRepository, JobHandler, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; import { IPersonRepository } from 'src/domain/repositories/person.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; import { assetStub } from 'test/fixtures/asset.stub'; import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; diff --git a/server/src/domain/job/job.service.ts b/server/src/domain/job/job.service.ts index bccb897d3..b50d26de4 100644 --- a/server/src/domain/job/job.service.ts +++ b/server/src/domain/job/job.service.ts @@ -1,4 +1,5 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; +import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { ConcurrentQueueName, JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/domain/job/job.dto'; @@ -7,7 +8,6 @@ import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/c import { IJobRepository, JobHandler, JobItem, JobStatus, QueueCleanType } from 'src/domain/repositories/job.repository'; import { IPersonRepository } from 'src/domain/repositories/person.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetType } from 'src/infra/entities/asset.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/domain/library/library.service.spec.ts index bfa3102d9..c1f2cc38c 100644 --- a/server/src/domain/library/library.service.spec.ts +++ b/server/src/domain/library/library.service.spec.ts @@ -2,6 +2,7 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; import { R_OK } from 'node:constants'; import { Stats } from 'node:fs'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { JobName } from 'src/domain/job/job.constants'; import { ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; import { mapLibrary } from 'src/domain/library/library.dto'; @@ -13,7 +14,6 @@ import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repositor import { ILibraryRepository } from 'src/domain/repositories/library.repository'; import { IStorageRepository, StorageEventType } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetType } from 'src/infra/entities/asset.entity'; import { LibraryType } from 'src/infra/entities/library.entity'; import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts index 46b4d11f5..30b1d1975 100644 --- a/server/src/domain/library/library.service.ts +++ b/server/src/domain/library/library.service.ts @@ -6,6 +6,8 @@ import { EventEmitter } from 'node:events'; import { Stats } from 'node:fs'; import path, { basename, parse } from 'node:path'; import picomatch from 'picomatch'; +import { StorageCore } from 'src/cores/storage.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { mimeTypes } from 'src/domain/domain.constant'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob, ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; @@ -29,8 +31,6 @@ import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repositor import { ILibraryRepository } from 'src/domain/repositories/library.repository'; import { IStorageRepository, StorageEventType } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { StorageCore } from 'src/domain/storage/storage.core'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetType } from 'src/infra/entities/asset.entity'; import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index f06f9ed28..8678203d7 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -1,4 +1,6 @@ import { Inject, Injectable, UnsupportedMediaTypeException } from '@nestjs/common'; +import { StorageCore, StorageFolder } from 'src/cores/storage.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; import { @@ -24,9 +26,7 @@ import { IMoveRepository } from 'src/domain/repositories/move.repository'; import { IPersonRepository } from 'src/domain/repositories/person.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { AssetPathType } from 'src/infra/entities/move.entity'; import { diff --git a/server/src/domain/metadata/metadata.service.ts b/server/src/domain/metadata/metadata.service.ts index 360f916ac..68b813eae 100644 --- a/server/src/domain/metadata/metadata.service.ts +++ b/server/src/domain/metadata/metadata.service.ts @@ -6,6 +6,8 @@ import { Duration } from 'luxon'; import { constants } from 'node:fs/promises'; import path from 'node:path'; import { Subscription } from 'rxjs'; +import { StorageCore } from 'src/cores/storage.core'; +import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; import { IAlbumRepository } from 'src/domain/repositories/album.repository'; @@ -20,8 +22,6 @@ import { IMoveRepository } from 'src/domain/repositories/move.repository'; import { IPersonRepository } from 'src/domain/repositories/person.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { StorageCore } from 'src/domain/storage/storage.core'; -import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/partner/partner.service.ts b/server/src/domain/partner/partner.service.ts index 74cafbcba..9bf305b2b 100644 --- a/server/src/domain/partner/partner.service.ts +++ b/server/src/domain/partner/partner.service.ts @@ -1,5 +1,5 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; diff --git a/server/src/domain/person/person.service.ts b/server/src/domain/person/person.service.ts index 46538e04f..62b13452a 100644 --- a/server/src/domain/person/person.service.ts +++ b/server/src/domain/person/person.service.ts @@ -1,5 +1,7 @@ import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; +import { StorageCore } from 'src/cores/storage.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { BulkIdErrorReason, BulkIdResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; @@ -33,8 +35,6 @@ import { IPersonRepository, UpdateFacesData } from 'src/domain/repositories/pers import { ISearchRepository } from 'src/domain/repositories/search.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { StorageCore } from 'src/domain/storage/storage.core'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { PersonPathType } from 'src/infra/entities/move.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/search/search.service.ts b/server/src/domain/search/search.service.ts index bb7e31bfa..ae8738cb6 100644 --- a/server/src/domain/search/search.service.ts +++ b/server/src/domain/search/search.service.ts @@ -1,4 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; +import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { PersonResponseDto } from 'src/domain/person/person.dto'; @@ -20,7 +21,6 @@ import { mapPlaces, } from 'src/domain/search/dto/search.dto'; import { SearchResponseDto } from 'src/domain/search/response-dto/search-response.dto'; -import { FeatureFlag, SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetOrder } from 'src/infra/entities/album.entity'; import { AssetEntity } from 'src/infra/entities/asset.entity'; diff --git a/server/src/domain/server-info/server-info.dto.ts b/server/src/domain/server-info/server-info.dto.ts index 07f99a874..0cbfbe773 100644 --- a/server/src/domain/server-info/server-info.dto.ts +++ b/server/src/domain/server-info/server-info.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger'; import type { DateTime } from 'luxon'; +import { FeatureFlags } from 'src/cores/system-config.core'; import { IVersion, VersionType } from 'src/domain/domain.constant'; import { SystemConfigThemeDto } from 'src/domain/system-config/dto/system-config-theme.dto'; -import { FeatureFlags } from 'src/domain/system-config/system-config.core'; export class ServerPingResponse { @ApiResponseProperty({ type: String, example: 'pong' }) diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index 3ceb3039d..9e72c7108 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -1,5 +1,7 @@ import { Inject, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; +import { StorageCore, StorageFolder } from 'src/cores/storage.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { Version, isDev, mimeTypes, serverVersion } from 'src/domain/domain.constant'; import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; @@ -16,8 +18,6 @@ import { ServerStatsResponseDto, UsageByUserDto, } from 'src/domain/server-info/server-info.dto'; -import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; import { ImmichLogger } from 'src/infra/logger'; import { asHumanReadable } from 'src/utils'; diff --git a/server/src/domain/shared-link/shared-link.service.ts b/server/src/domain/shared-link/shared-link.service.ts index b55085492..a62acb6bf 100644 --- a/server/src/domain/shared-link/shared-link.service.ts +++ b/server/src/domain/shared-link/shared-link.service.ts @@ -1,5 +1,5 @@ import { BadRequestException, ForbiddenException, Inject, Injectable, UnauthorizedException } from '@nestjs/common'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; diff --git a/server/src/domain/smart-info/smart-info.service.ts b/server/src/domain/smart-info/smart-info.service.ts index fdf9862f8..333c8faaf 100644 --- a/server/src/domain/smart-info/smart-info.service.ts +++ b/server/src/domain/smart-info/smart-info.service.ts @@ -1,4 +1,5 @@ import { Inject, Injectable } from '@nestjs/common'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; @@ -7,7 +8,6 @@ import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repositor import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; import { ISearchRepository } from 'src/domain/repositories/search.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { ImmichLogger } from 'src/infra/logger'; import { usePagination } from 'src/utils'; diff --git a/server/src/domain/storage-template/storage-template.service.spec.ts b/server/src/domain/storage-template/storage-template.service.spec.ts index f73709035..ce378bf9b 100644 --- a/server/src/domain/storage-template/storage-template.service.spec.ts +++ b/server/src/domain/storage-template/storage-template.service.spec.ts @@ -1,5 +1,6 @@ import { when } from 'jest-when'; import { Stats } from 'node:fs'; +import { SystemConfigCore, defaults } from 'src/cores/system-config.core'; import { IAlbumRepository } from 'src/domain/repositories/album.repository'; import { IAssetRepository } from 'src/domain/repositories/asset.repository'; import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; @@ -11,7 +12,6 @@ import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { IUserRepository } from 'src/domain/repositories/user.repository'; import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; -import { SystemConfigCore, defaults } from 'src/domain/system-config/system-config.core'; import { AssetPathType } from 'src/infra/entities/move.entity'; import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/domain/storage-template/storage-template.service.ts b/server/src/domain/storage-template/storage-template.service.ts index f3e24c056..b79426b1f 100644 --- a/server/src/domain/storage-template/storage-template.service.ts +++ b/server/src/domain/storage-template/storage-template.service.ts @@ -4,6 +4,8 @@ import handlebar from 'handlebars'; import { DateTime } from 'luxon'; import path from 'node:path'; import sanitize from 'sanitize-filename'; +import { StorageCore, StorageFolder } from 'src/cores/storage.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; import { IEntityJob } from 'src/domain/job/job.interface'; import { IAlbumRepository } from 'src/domain/repositories/album.repository'; @@ -17,7 +19,6 @@ import { IPersonRepository } from 'src/domain/repositories/person.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { IUserRepository } from 'src/domain/repositories/user.repository'; -import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; import { supportedDayTokens, supportedHourTokens, @@ -27,7 +28,6 @@ import { supportedWeekTokens, supportedYearTokens, } from 'src/domain/system-config/system-config.constants'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { AssetPathType } from 'src/infra/entities/move.entity'; import { SystemConfig } from 'src/infra/entities/system-config.entity'; diff --git a/server/src/domain/storage/storage.service.ts b/server/src/domain/storage/storage.service.ts index 08010231e..5c75a9921 100644 --- a/server/src/domain/storage/storage.service.ts +++ b/server/src/domain/storage/storage.service.ts @@ -1,8 +1,8 @@ import { Inject, Injectable } from '@nestjs/common'; +import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { IDeleteFilesJob } from 'src/domain/job/job.interface'; import { JobStatus } from 'src/domain/repositories/job.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; import { ImmichLogger } from 'src/infra/logger'; @Injectable() diff --git a/server/src/domain/system-config/system-config.service.spec.ts b/server/src/domain/system-config/system-config.service.spec.ts index ccaea8421..4eb1619ee 100644 --- a/server/src/domain/system-config/system-config.service.spec.ts +++ b/server/src/domain/system-config/system-config.service.spec.ts @@ -1,9 +1,9 @@ import { BadRequestException } from '@nestjs/common'; +import { defaults } from 'src/cores/system-config.core'; import { QueueName } from 'src/domain/job/job.constants'; import { ICommunicationRepository, ServerEvent } from 'src/domain/repositories/communication.repository'; import { ISearchRepository } from 'src/domain/repositories/search.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { defaults } from 'src/domain/system-config/system-config.core'; import { SystemConfigService } from 'src/domain/system-config/system-config.service'; import { AudioCodec, diff --git a/server/src/domain/system-config/system-config.service.ts b/server/src/domain/system-config/system-config.service.ts index 2c4e1eacc..856e80d49 100644 --- a/server/src/domain/system-config/system-config.service.ts +++ b/server/src/domain/system-config/system-config.service.ts @@ -2,6 +2,7 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import { instanceToPlain } from 'class-transformer'; import _ from 'lodash'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { ClientEvent, ICommunicationRepository, @@ -23,7 +24,6 @@ import { supportedWeekTokens, supportedYearTokens, } from 'src/domain/system-config/system-config.constants'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { LogLevel, SystemConfig } from 'src/infra/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/trash/trash.service.ts b/server/src/domain/trash/trash.service.ts index aa95a4889..2ae09c104 100644 --- a/server/src/domain/trash/trash.service.ts +++ b/server/src/domain/trash/trash.service.ts @@ -1,6 +1,6 @@ import { Inject } from '@nestjs/common'; import { DateTime } from 'luxon'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; diff --git a/server/src/domain/user/user.service.ts b/server/src/domain/user/user.service.ts index 6eca5ff55..022b93492 100644 --- a/server/src/domain/user/user.service.ts +++ b/server/src/domain/user/user.service.ts @@ -1,6 +1,9 @@ import { BadRequestException, ForbiddenException, Inject, Injectable, NotFoundException } from '@nestjs/common'; import { DateTime } from 'luxon'; import { randomBytes } from 'node:crypto'; +import { StorageCore, StorageFolder } from 'src/cores/storage.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; +import { UserCore } from 'src/cores/user.core'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { JobName } from 'src/domain/job/job.constants'; import { IEntityJob } from 'src/domain/job/job.interface'; @@ -11,8 +14,6 @@ import { ILibraryRepository } from 'src/domain/repositories/library.repository'; import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { IUserRepository, UserFindOptions } from 'src/domain/repositories/user.repository'; -import { StorageCore, StorageFolder } from 'src/domain/storage/storage.core'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; import { CreateUserDto } from 'src/domain/user/dto/create-user.dto'; import { DeleteUserDto } from 'src/domain/user/dto/delete-user.dto'; import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; @@ -21,7 +22,6 @@ import { mapCreateProfileImageResponse, } from 'src/domain/user/response-dto/create-profile-image-response.dto'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { UserCore } from 'src/domain/user/user.core'; import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; import { CacheControl, ImmichFileResponse } from 'src/utils'; diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 613e8f2ed..aa157aaed 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -5,7 +5,7 @@ import { InternalServerErrorException, NotFoundException, } from '@nestjs/common'; -import { AccessCore, Permission } from 'src/domain/access/access.core'; +import { AccessCore, Permission } from 'src/cores/access.core'; import { UploadFile } from 'src/domain/asset/asset.service'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; diff --git a/server/test/fixtures/library.stub.ts b/server/test/fixtures/library.stub.ts index d112d0fb4..0c5296595 100644 --- a/server/test/fixtures/library.stub.ts +++ b/server/test/fixtures/library.stub.ts @@ -1,6 +1,6 @@ import { join } from 'node:path'; +import { THUMBNAIL_DIR } from 'src/cores/storage.core'; import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; -import { THUMBNAIL_DIR } from 'src/domain/storage/storage.core'; import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/test/repositories/access.repository.mock.ts b/server/test/repositories/access.repository.mock.ts index 4491d6e70..686d9bc85 100644 --- a/server/test/repositories/access.repository.mock.ts +++ b/server/test/repositories/access.repository.mock.ts @@ -1,4 +1,4 @@ -import { AccessCore } from 'src/domain/access/access.core'; +import { AccessCore } from 'src/cores/access.core'; import { IAccessRepository } from 'src/domain/repositories/access.repository'; export interface IAccessRepositoryMock { diff --git a/server/test/repositories/storage.repository.mock.ts b/server/test/repositories/storage.repository.mock.ts index a2851e9e1..071b733a8 100644 --- a/server/test/repositories/storage.repository.mock.ts +++ b/server/test/repositories/storage.repository.mock.ts @@ -1,6 +1,6 @@ import { WatchOptions } from 'chokidar'; +import { StorageCore } from 'src/cores/storage.core'; import { IStorageRepository, StorageEventType, WatchEvents } from 'src/domain/repositories/storage.repository'; -import { StorageCore } from 'src/domain/storage/storage.core'; interface MockWatcherOptions { items?: Array<{ event: 'change' | 'add' | 'unlink' | 'error'; value: string }>; diff --git a/server/test/repositories/system-config.repository.mock.ts b/server/test/repositories/system-config.repository.mock.ts index 6fb4520f8..537182b2e 100644 --- a/server/test/repositories/system-config.repository.mock.ts +++ b/server/test/repositories/system-config.repository.mock.ts @@ -1,5 +1,5 @@ +import { SystemConfigCore } from 'src/cores/system-config.core'; import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { SystemConfigCore } from 'src/domain/system-config/system-config.core'; export const newSystemConfigRepositoryMock = (reset = true): jest.Mocked => { if (reset) { diff --git a/server/test/repositories/user.repository.mock.ts b/server/test/repositories/user.repository.mock.ts index e6772d2b1..57e014830 100644 --- a/server/test/repositories/user.repository.mock.ts +++ b/server/test/repositories/user.repository.mock.ts @@ -1,5 +1,5 @@ +import { UserCore } from 'src/cores/user.core'; import { IUserRepository } from 'src/domain/repositories/user.repository'; -import { UserCore } from 'src/domain/user/user.core'; export const newUserRepositoryMock = (reset = true): jest.Mocked => { if (reset) { From 96a22ec3c1912766d46b1ddfabb17e4248523aa4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 16:21:27 -0400 Subject: [PATCH 035/152] chore(deps): update base-image to v20240319 (major) (#8115) chore(deps): update base-image to v20240319 Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- server/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/Dockerfile b/server/Dockerfile index c42153d76..be453bba8 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -1,5 +1,5 @@ # dev build -FROM ghcr.io/immich-app/base-server-dev:20240312@sha256:3cb168dd87a2b412b25c512ec638a1e7f362e1d3eb8dd19a38d92d4a7c47999c as dev +FROM ghcr.io/immich-app/base-server-dev:20240319@sha256:9c9492d59b51a0c340ea3f61a1c9a483122b86b008c7fbe1759d7b858c5e6af5 as dev RUN apt-get install --no-install-recommends -yqq tini WORKDIR /usr/src/app @@ -40,7 +40,7 @@ RUN npm run build # prod build -FROM ghcr.io/immich-app/base-server-prod:20240312@sha256:8359fb1acc56580f2b4835e273293fdaa99d273b210892e1485fc6f1e47cf2bb +FROM ghcr.io/immich-app/base-server-prod:20240319@sha256:6bfcb2f2b84d3070be95ab09ba614e2ff3e832e566a283f516a276a8ae6a147b WORKDIR /usr/src/app ENV NODE_ENV=production \ From 2dcce0335250a593e7990ad5717ec997cfc143a7 Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Wed, 20 Mar 2024 21:25:33 +0100 Subject: [PATCH 036/152] chore(server): move commands (#8121) move commands --- .../commands/list-users.command.ts | 13 +++++++++++-- .../src/{immich-admin => }/commands/oauth-login.ts | 0 .../{immich-admin => }/commands/password-login.ts | 0 .../commands/reset-admin-password.command.ts | 0 server/src/immich-admin/app.module.ts | 11 ++++------- server/src/immich-admin/constants.ts | 10 ---------- 6 files changed, 15 insertions(+), 19 deletions(-) rename server/src/{immich-admin => }/commands/list-users.command.ts (62%) rename server/src/{immich-admin => }/commands/oauth-login.ts (100%) rename server/src/{immich-admin => }/commands/password-login.ts (100%) rename server/src/{immich-admin => }/commands/reset-admin-password.command.ts (100%) delete mode 100644 server/src/immich-admin/constants.ts diff --git a/server/src/immich-admin/commands/list-users.command.ts b/server/src/commands/list-users.command.ts similarity index 62% rename from server/src/immich-admin/commands/list-users.command.ts rename to server/src/commands/list-users.command.ts index 8ab882396..eeda72d1c 100644 --- a/server/src/immich-admin/commands/list-users.command.ts +++ b/server/src/commands/list-users.command.ts @@ -1,6 +1,6 @@ import { Command, CommandRunner } from 'nest-commander'; import { UserService } from 'src/domain/user/user.service'; -import { CLI_USER } from 'src/immich-admin/constants'; +import { UserEntity } from 'src/infra/entities/user.entity'; @Command({ name: 'list-users', @@ -13,7 +13,16 @@ export class ListUsersCommand extends CommandRunner { async run(): Promise { try { - const users = await this.userService.getAll(CLI_USER, true); + const users = await this.userService.getAll( + { + user: { + id: 'cli', + email: 'cli@immich.app', + isAdmin: true, + } as UserEntity, + }, + true, + ); console.dir(users); } catch (error) { console.error(error); diff --git a/server/src/immich-admin/commands/oauth-login.ts b/server/src/commands/oauth-login.ts similarity index 100% rename from server/src/immich-admin/commands/oauth-login.ts rename to server/src/commands/oauth-login.ts diff --git a/server/src/immich-admin/commands/password-login.ts b/server/src/commands/password-login.ts similarity index 100% rename from server/src/immich-admin/commands/password-login.ts rename to server/src/commands/password-login.ts diff --git a/server/src/immich-admin/commands/reset-admin-password.command.ts b/server/src/commands/reset-admin-password.command.ts similarity index 100% rename from server/src/immich-admin/commands/reset-admin-password.command.ts rename to server/src/commands/reset-admin-password.command.ts diff --git a/server/src/immich-admin/app.module.ts b/server/src/immich-admin/app.module.ts index 277b39a90..b491fbb55 100644 --- a/server/src/immich-admin/app.module.ts +++ b/server/src/immich-admin/app.module.ts @@ -1,12 +1,9 @@ import { Module } from '@nestjs/common'; +import { ListUsersCommand } from 'src/commands/list-users.command'; +import { DisableOAuthLogin, EnableOAuthLogin } from 'src/commands/oauth-login'; +import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from 'src/commands/password-login'; +import { PromptPasswordQuestions, ResetAdminPasswordCommand } from 'src/commands/reset-admin-password.command'; import { DomainModule } from 'src/domain/domain.module'; -import { ListUsersCommand } from 'src/immich-admin/commands/list-users.command'; -import { DisableOAuthLogin, EnableOAuthLogin } from 'src/immich-admin/commands/oauth-login'; -import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from 'src/immich-admin/commands/password-login'; -import { - PromptPasswordQuestions, - ResetAdminPasswordCommand, -} from 'src/immich-admin/commands/reset-admin-password.command'; import { InfraModule } from 'src/infra/infra.module'; @Module({ diff --git a/server/src/immich-admin/constants.ts b/server/src/immich-admin/constants.ts deleted file mode 100644 index 237f66e63..000000000 --- a/server/src/immich-admin/constants.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { UserEntity } from 'src/infra/entities/user.entity'; - -export const CLI_USER: AuthDto = { - user: { - id: 'cli', - email: 'cli@immich.app', - isAdmin: true, - } as UserEntity, -}; From 84f7ca855a01c5c8d1bd2ce8c8355f17bb8a6125 Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Wed, 20 Mar 2024 21:42:58 +0100 Subject: [PATCH 037/152] chore(server): move domain interfaces (#8124) move domain interfaces --- .../jobs/specs/library-watcher.e2e-spec.ts | 2 +- server/src/controllers/partner.controller.ts | 2 +- server/src/cores/access.core.ts | 2 +- server/src/cores/storage.core.ts | 12 ++--- server/src/cores/system-config.core.ts | 2 +- server/src/cores/user.core.ts | 6 +-- .../src/domain/activity/activity.service.ts | 4 +- server/src/domain/activity/activity.spec.ts | 2 +- server/src/domain/album/album.service.spec.ts | 6 +-- server/src/domain/album/album.service.ts | 8 +-- .../domain/api-key/api-key.service.spec.ts | 4 +- server/src/domain/api-key/api-key.service.ts | 4 +- server/src/domain/asset/asset.service.spec.ts | 16 +++--- server/src/domain/asset/asset.service.ts | 18 +++---- .../domain/asset/dto/asset-statistics.dto.ts | 2 +- .../src/domain/asset/dto/time-bucket.dto.ts | 2 +- server/src/domain/audit/audit.service.spec.ts | 14 ++--- server/src/domain/audit/audit.service.ts | 16 +++--- server/src/domain/auth/auth.service.spec.ts | 14 ++--- server/src/domain/auth/auth.service.ts | 16 +++--- .../domain/database/database.service.spec.ts | 2 +- .../src/domain/database/database.service.ts | 4 +- .../domain/download/download.service.spec.ts | 4 +- .../src/domain/download/download.service.ts | 6 +-- server/src/domain/job/job.service.spec.ts | 10 ++-- server/src/domain/job/job.service.ts | 10 ++-- .../domain/library/library.service.spec.ts | 14 ++--- server/src/domain/library/library.service.ts | 16 +++--- server/src/domain/media/media.service.spec.ts | 16 +++--- server/src/domain/media/media.service.ts | 26 ++++----- server/src/domain/media/media.util.ts | 16 +++--- .../domain/metadata/metadata.service.spec.ts | 24 ++++----- .../src/domain/metadata/metadata.service.ts | 24 ++++----- .../domain/partner/partner.service.spec.ts | 4 +- server/src/domain/partner/partner.service.ts | 4 +- .../src/domain/person/person.service.spec.ts | 20 +++---- server/src/domain/person/person.service.ts | 22 ++++---- .../src/domain/search/search.service.spec.ts | 14 ++--- server/src/domain/search/search.service.ts | 14 ++--- .../server-info/server-info.service.spec.ts | 12 ++--- .../domain/server-info/server-info.service.ts | 12 ++--- .../shared-link/shared-link.service.spec.ts | 4 +- .../domain/shared-link/shared-link.service.ts | 6 +-- .../domain/smart-info/dto/model-config.dto.ts | 2 +- .../smart-info/smart-info.service.spec.ts | 12 ++--- .../domain/smart-info/smart-info.service.ts | 12 ++--- .../storage-template.service.spec.ts | 20 +++---- .../storage-template.service.ts | 22 ++++---- .../domain/storage/storage.service.spec.ts | 2 +- server/src/domain/storage/storage.service.ts | 4 +- .../system-config.service.spec.ts | 6 +-- .../system-config/system-config.service.ts | 18 +++---- server/src/domain/tag/tag.service.spec.ts | 2 +- server/src/domain/tag/tag.service.ts | 2 +- server/src/domain/trash/trash.service.spec.ts | 6 +-- server/src/domain/trash/trash.service.ts | 8 +-- server/src/domain/user/user.service.spec.ts | 14 ++--- server/src/domain/user/user.service.ts | 14 ++--- .../immich/api-v1/asset/asset.service.spec.ts | 10 ++-- .../src/immich/api-v1/asset/asset.service.ts | 12 ++--- server/src/immich/app.utils.ts | 2 +- server/src/infra/database.config.ts | 2 +- server/src/infra/infra.module.ts | 54 +++++++++---------- server/src/infra/infra.utils.ts | 2 +- .../1700713994428-AddCLIPEmbeddingIndex.ts | 2 +- .../1700714033632-AddFaceEmbeddingIndex.ts | 2 +- .../infra/repositories/access.repository.ts | 2 +- .../infra/repositories/activity.repository.ts | 2 +- .../infra/repositories/album.repository.ts | 10 ++-- .../infra/repositories/api-key.repository.ts | 2 +- .../repositories/asset-stack.repository.ts | 2 +- .../infra/repositories/asset.repository.ts | 18 +++---- .../infra/repositories/audit.repository.ts | 2 +- .../repositories/communication.repository.ts | 6 +-- .../infra/repositories/crypto.repository.ts | 2 +- .../infra/repositories/database.repository.ts | 8 +-- .../infra/repositories/filesystem.provider.ts | 6 +-- .../src/infra/repositories/job.repository.ts | 8 +-- .../infra/repositories/library.repository.ts | 2 +- .../machine-learning.repository.ts | 6 +-- .../infra/repositories/media.repository.ts | 8 +-- .../infra/repositories/metadata.repository.ts | 9 +--- .../src/infra/repositories/move.repository.ts | 2 +- .../infra/repositories/partner.repository.ts | 2 +- .../infra/repositories/person.repository.ts | 12 ++--- .../infra/repositories/search.repository.ts | 20 +++---- .../repositories/server-info.repository.ts | 2 +- .../repositories/shared-link.repository.ts | 2 +- .../repositories/system-config.repository.ts | 2 +- .../system-metadata.repository.ts | 2 +- .../src/infra/repositories/tag.repository.ts | 2 +- .../repositories/user-token.repository.ts | 2 +- .../src/infra/repositories/user.repository.ts | 8 +-- server/src/infra/sql-generator/index.ts | 2 +- .../access.repository.ts | 0 .../activity.repository.ts | 0 .../album.repository.ts | 0 .../api-key.repository.ts | 0 .../asset-stack.repository.ts | 0 .../asset.repository.ts | 4 +- .../audit.repository.ts | 0 .../communication.repository.ts | 0 .../crypto.repository.ts | 0 .../database.repository.ts | 0 .../job.repository.ts | 0 .../library.repository.ts | 0 .../machine-learning.repository.ts | 0 .../media.repository.ts | 0 .../metadata.repository.ts | 0 .../move.repository.ts | 0 .../partner.repository.ts | 0 .../person.repository.ts | 0 .../search.repository.ts | 0 .../server-info.repository.ts | 0 .../shared-link.repository.ts | 0 .../storage.repository.ts | 0 .../system-config.repository.ts | 0 .../system-metadata.repository.ts | 0 .../tag.repository.ts | 0 .../user-token.repository.ts | 0 .../user.repository.ts | 0 server/src/test-utils/utils.ts | 6 +-- server/test/fixtures/media.stub.ts | 2 +- .../repositories/access.repository.mock.ts | 2 +- .../repositories/activity.repository.mock.ts | 2 +- .../repositories/album.repository.mock.ts | 2 +- .../repositories/api-key.repository.mock.ts | 2 +- .../asset-stack.repository.mock.ts | 2 +- .../repositories/asset.repository.mock.ts | 2 +- .../repositories/audit.repository.mock.ts | 2 +- .../communication.repository.mock.ts | 2 +- .../repositories/crypto.repository.mock.ts | 2 +- .../repositories/database.repository.mock.ts | 2 +- .../test/repositories/job.repository.mock.ts | 2 +- .../repositories/library.repository.mock.ts | 2 +- .../machine-learning.repository.mock.ts | 2 +- .../repositories/media.repository.mock.ts | 2 +- .../repositories/metadata.repository.mock.ts | 2 +- .../test/repositories/move.repository.mock.ts | 2 +- .../repositories/partner.repository.mock.ts | 2 +- .../repositories/person.repository.mock.ts | 2 +- .../repositories/search.repository.mock.ts | 2 +- .../shared-link.repository.mock.ts | 2 +- .../repositories/storage.repository.mock.ts | 2 +- .../system-config.repository.mock.ts | 2 +- .../system-info.repository.mock.ts | 2 +- .../system-metadata.repository.mock.ts | 2 +- .../test/repositories/tag.repository.mock.ts | 2 +- .../user-token.repository.mock.ts | 2 +- .../test/repositories/user.repository.mock.ts | 2 +- 150 files changed, 436 insertions(+), 447 deletions(-) rename server/src/{domain/repositories => interfaces}/access.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/activity.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/album.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/api-key.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/asset-stack.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/asset.repository.ts (96%) rename server/src/{domain/repositories => interfaces}/audit.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/communication.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/crypto.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/database.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/job.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/library.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/machine-learning.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/media.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/metadata.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/move.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/partner.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/person.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/search.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/server-info.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/shared-link.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/storage.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/system-config.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/system-metadata.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/tag.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/user-token.repository.ts (100%) rename server/src/{domain/repositories => interfaces}/user.repository.ts (100%) diff --git a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts index 50d29f8ff..a146bc856 100644 --- a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts +++ b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts @@ -4,9 +4,9 @@ import path from 'node:path'; import { LoginResponseDto } from 'src/domain/auth/auth.dto'; import { LibraryResponseDto } from 'src/domain/library/library.dto'; import { LibraryService } from 'src/domain/library/library.service'; -import { StorageEventType } from 'src/domain/repositories/storage.repository'; import { AssetType } from 'src/infra/entities/asset.entity'; import { LibraryType } from 'src/infra/entities/library.entity'; +import { StorageEventType } from 'src/interfaces/storage.repository'; import { IMMICH_TEST_ASSET_PATH, IMMICH_TEST_ASSET_TEMP_PATH, diff --git a/server/src/controllers/partner.controller.ts b/server/src/controllers/partner.controller.ts index b756ade3e..8ca55e73c 100644 --- a/server/src/controllers/partner.controller.ts +++ b/server/src/controllers/partner.controller.ts @@ -3,7 +3,7 @@ import { ApiQuery, ApiTags } from '@nestjs/swagger'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; import { PartnerService } from 'src/domain/partner/partner.service'; -import { PartnerDirection } from 'src/domain/repositories/partner.repository'; +import { PartnerDirection } from 'src/interfaces/partner.repository'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/cores/access.core.ts b/server/src/cores/access.core.ts index eb4ff55d1..389647524 100644 --- a/server/src/cores/access.core.ts +++ b/server/src/cores/access.core.ts @@ -1,7 +1,7 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { IAccessRepository } from 'src/interfaces/access.repository'; import { setDifference, setIsEqual, setUnion } from 'src/utils'; export enum Permission { diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 4e501dd83..39d9e12c9 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -1,16 +1,16 @@ import { dirname, join, resolve } from 'node:path'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { AssetPathType, PathType, PersonPathType } from 'src/infra/entities/move.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; export enum StorageFolder { ENCODED_VIDEO = 'encoded-video', diff --git a/server/src/cores/system-config.core.ts b/server/src/cores/system-config.core.ts index 999ca3e5b..1bfab773d 100644 --- a/server/src/cores/system-config.core.ts +++ b/server/src/cores/system-config.core.ts @@ -6,7 +6,6 @@ import { load as loadYaml } from 'js-yaml'; import * as _ from 'lodash'; import { Subject } from 'rxjs'; import { QueueName } from 'src/domain/job/job.constants'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SystemConfigDto } from 'src/domain/system-config/dto/system-config.dto'; import { AudioCodec, @@ -23,6 +22,7 @@ import { VideoCodec, } from 'src/infra/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConfig) => void | Promise; diff --git a/server/src/cores/user.core.ts b/server/src/cores/user.core.ts index 0f9022a42..488c16036 100644 --- a/server/src/cores/user.core.ts +++ b/server/src/cores/user.core.ts @@ -1,11 +1,11 @@ import { BadRequestException, ForbiddenException } from '@nestjs/common'; import sanitize from 'sanitize-filename'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; import { LibraryType } from 'src/infra/entities/library.entity'; import { UserEntity } from 'src/infra/entities/user.entity'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; const SALT_ROUNDS = 10; diff --git a/server/src/domain/activity/activity.service.ts b/server/src/domain/activity/activity.service.ts index cc1fef2c1..9ed8946f5 100644 --- a/server/src/domain/activity/activity.service.ts +++ b/server/src/domain/activity/activity.service.ts @@ -12,9 +12,9 @@ import { mapActivity, } from 'src/domain/activity/activity.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IActivityRepository } from 'src/domain/repositories/activity.repository'; import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IActivityRepository } from 'src/interfaces/activity.repository'; @Injectable() export class ActivityService { diff --git a/server/src/domain/activity/activity.spec.ts b/server/src/domain/activity/activity.spec.ts index cd70572ca..467540be3 100644 --- a/server/src/domain/activity/activity.spec.ts +++ b/server/src/domain/activity/activity.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException } from '@nestjs/common'; import { ReactionType } from 'src/domain/activity/activity.dto'; import { ActivityService } from 'src/domain/activity/activity.service'; -import { IActivityRepository } from 'src/domain/repositories/activity.repository'; +import { IActivityRepository } from 'src/interfaces/activity.repository'; import { activityStub } from 'test/fixtures/activity.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; diff --git a/server/src/domain/album/album.service.spec.ts b/server/src/domain/album/album.service.spec.ts index e8122b73c..5b3a91ecf 100644 --- a/server/src/domain/album/album.service.spec.ts +++ b/server/src/domain/album/album.service.spec.ts @@ -2,9 +2,9 @@ import { BadRequestException } from '@nestjs/common'; import _ from 'lodash'; import { AlbumService } from 'src/domain/album/album.service'; import { BulkIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { albumStub } from 'test/fixtures/album.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/src/domain/album/album.service.ts b/server/src/domain/album/album.service.ts index 5cd026cb3..77a6c6c46 100644 --- a/server/src/domain/album/album.service.ts +++ b/server/src/domain/album/album.service.ts @@ -14,13 +14,13 @@ import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { AlbumEntity } from 'src/infra/entities/album.entity'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { UserEntity } from 'src/infra/entities/user.entity'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { setUnion } from 'src/utils'; @Injectable() diff --git a/server/src/domain/api-key/api-key.service.spec.ts b/server/src/domain/api-key/api-key.service.spec.ts index e50d0d9b3..0400c13a2 100644 --- a/server/src/domain/api-key/api-key.service.spec.ts +++ b/server/src/domain/api-key/api-key.service.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException } from '@nestjs/common'; import { APIKeyService } from 'src/domain/api-key/api-key.service'; -import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { IKeyRepository } from 'src/interfaces/api-key.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { keyStub } from 'test/fixtures/api-key.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { newKeyRepositoryMock } from 'test/repositories/api-key.repository.mock'; diff --git a/server/src/domain/api-key/api-key.service.ts b/server/src/domain/api-key/api-key.service.ts index 5a531e9d5..c8e7c5ec3 100644 --- a/server/src/domain/api-key/api-key.service.ts +++ b/server/src/domain/api-key/api-key.service.ts @@ -1,9 +1,9 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto } from 'src/domain/api-key/api-key.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { IKeyRepository } from 'src/interfaces/api-key.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; @Injectable() export class APIKeyService { diff --git a/server/src/domain/asset/asset.service.spec.ts b/server/src/domain/asset/asset.service.spec.ts index fdf89739f..9b59f4092 100644 --- a/server/src/domain/asset/asset.service.spec.ts +++ b/server/src/domain/asset/asset.service.spec.ts @@ -5,15 +5,15 @@ import { AssetJobName } from 'src/domain/asset/dto/asset-ids.dto'; import { AssetStatsResponseDto } from 'src/domain/asset/dto/asset-statistics.dto'; import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { JobName } from 'src/domain/job/job.constants'; -import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; -import { AssetStats, IAssetRepository, TimeBucketSize } from 'src/domain/repositories/asset.repository'; -import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { IJobRepository, JobItem } from 'src/domain/repositories/job.repository'; -import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; +import { AssetStats, IAssetRepository, TimeBucketSize } from 'src/interfaces/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { IJobRepository, JobItem } from 'src/interfaces/job.repository'; +import { IPartnerRepository } from 'src/interfaces/partner.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { assetStackStub, assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { faceStub } from 'test/fixtures/face.stub'; diff --git a/server/src/domain/asset/asset.service.ts b/server/src/domain/asset/asset.service.ts index d6d2d76fb..2594233c4 100644 --- a/server/src/domain/asset/asset.service.ts +++ b/server/src/domain/asset/asset.service.ts @@ -25,18 +25,18 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; import { IAssetDeletionJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; -import { IAssetRepository, TimeBucketOptions } from 'src/domain/repositories/asset.repository'; -import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { IJobRepository, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; -import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; +import { IAssetRepository, TimeBucketOptions } from 'src/interfaces/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { IJobRepository, JobItem, JobStatus } from 'src/interfaces/job.repository'; +import { IPartnerRepository } from 'src/interfaces/partner.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { usePagination } from 'src/utils'; export enum UploadFieldName { diff --git a/server/src/domain/asset/dto/asset-statistics.dto.ts b/server/src/domain/asset/dto/asset-statistics.dto.ts index 7694955c2..45bae1f5d 100644 --- a/server/src/domain/asset/dto/asset-statistics.dto.ts +++ b/server/src/domain/asset/dto/asset-statistics.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; -import { AssetStats } from 'src/domain/repositories/asset.repository'; import { AssetType } from 'src/infra/entities/asset.entity'; +import { AssetStats } from 'src/interfaces/asset.repository'; import { ValidateBoolean } from 'src/validation'; export class AssetStatsDto { diff --git a/server/src/domain/asset/dto/time-bucket.dto.ts b/server/src/domain/asset/dto/time-bucket.dto.ts index c9e104256..7b2ee24c0 100644 --- a/server/src/domain/asset/dto/time-bucket.dto.ts +++ b/server/src/domain/asset/dto/time-bucket.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { TimeBucketSize } from 'src/domain/repositories/asset.repository'; import { AssetOrder } from 'src/infra/entities/album.entity'; +import { TimeBucketSize } from 'src/interfaces/asset.repository'; import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class TimeBucketDto { diff --git a/server/src/domain/audit/audit.service.spec.ts b/server/src/domain/audit/audit.service.spec.ts index b8a4d2b2b..aa110dfb2 100644 --- a/server/src/domain/audit/audit.service.spec.ts +++ b/server/src/domain/audit/audit.service.spec.ts @@ -1,12 +1,12 @@ import { AuditService } from 'src/domain/audit/audit.service'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IAuditRepository } from 'src/domain/repositories/audit.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { JobStatus } from 'src/domain/repositories/job.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IAuditRepository } from 'src/interfaces/audit.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { JobStatus } from 'src/interfaces/job.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { auditStub } from 'test/fixtures/audit.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; diff --git a/server/src/domain/audit/audit.service.ts b/server/src/domain/audit/audit.service.ts index d375aa082..cf8b7f303 100644 --- a/server/src/domain/audit/audit.service.ts +++ b/server/src/domain/audit/audit.service.ts @@ -14,17 +14,17 @@ import { import { AuthDto } from 'src/domain/auth/auth.dto'; import { AUDIT_LOG_MAX_DURATION } from 'src/domain/domain.constant'; import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IAuditRepository } from 'src/domain/repositories/audit.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { JobStatus } from 'src/domain/repositories/job.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { DatabaseAction } from 'src/infra/entities/audit.entity'; import { AssetPathType, PersonPathType, UserPathType } from 'src/infra/entities/move.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IAuditRepository } from 'src/interfaces/audit.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { JobStatus } from 'src/interfaces/job.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { usePagination } from 'src/utils'; @Injectable() diff --git a/server/src/domain/auth/auth.service.spec.ts b/server/src/domain/auth/auth.service.spec.ts index 37941aa44..2cbc3cb6e 100644 --- a/server/src/domain/auth/auth.service.spec.ts +++ b/server/src/domain/auth/auth.service.spec.ts @@ -5,14 +5,14 @@ import { Socket } from 'socket.io'; import { AuthType } from 'src/domain/auth/auth.constant'; import { AuthDto, SignUpDto } from 'src/domain/auth/auth.dto'; import { AuthService } from 'src/domain/auth/auth.service'; -import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { UserEntity } from 'src/infra/entities/user.entity'; +import { IKeyRepository } from 'src/interfaces/api-key.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { keyStub } from 'test/fixtures/api-key.stub'; import { authStub, loginResponseStub } from 'test/fixtures/auth.stub'; import { sharedLinkStub } from 'test/fixtures/shared-link.stub'; diff --git a/server/src/domain/auth/auth.service.ts b/server/src/domain/auth/auth.service.ts index bad578013..0f2709307 100644 --- a/server/src/domain/auth/auth.service.ts +++ b/server/src/domain/auth/auth.service.ts @@ -36,18 +36,18 @@ import { mapLoginResponse, mapUserToken, } from 'src/domain/auth/auth.dto'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { SystemConfig } from 'src/infra/entities/system-config.entity'; import { UserEntity } from 'src/infra/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IKeyRepository } from 'src/interfaces/api-key.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { HumanReadableSize } from 'src/utils'; export interface LoginDetails { diff --git a/server/src/domain/database/database.service.spec.ts b/server/src/domain/database/database.service.spec.ts index 25ebe61af..191c0221b 100644 --- a/server/src/domain/database/database.service.spec.ts +++ b/server/src/domain/database/database.service.spec.ts @@ -1,7 +1,7 @@ import { DatabaseService } from 'src/domain/database/database.service'; import { Version, VersionType } from 'src/domain/domain.constant'; -import { DatabaseExtension, IDatabaseRepository, VectorIndex } from 'src/domain/repositories/database.repository'; import { ImmichLogger } from 'src/infra/logger'; +import { DatabaseExtension, IDatabaseRepository, VectorIndex } from 'src/interfaces/database.repository'; import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; describe(DatabaseService.name, () => { diff --git a/server/src/domain/database/database.service.ts b/server/src/domain/database/database.service.ts index 6e6ef98aa..7bb16a4e1 100644 --- a/server/src/domain/database/database.service.ts +++ b/server/src/domain/database/database.service.ts @@ -1,5 +1,6 @@ import { Inject, Injectable } from '@nestjs/common'; import { Version, VersionType } from 'src/domain/domain.constant'; +import { ImmichLogger } from 'src/infra/logger'; import { DatabaseExtension, DatabaseLock, @@ -7,8 +8,7 @@ import { VectorExtension, VectorIndex, extName, -} from 'src/domain/repositories/database.repository'; -import { ImmichLogger } from 'src/infra/logger'; +} from 'src/interfaces/database.repository'; @Injectable() export class DatabaseService { diff --git a/server/src/domain/download/download.service.spec.ts b/server/src/domain/download/download.service.spec.ts index 7c3ecbb02..6e1eafbec 100644 --- a/server/src/domain/download/download.service.spec.ts +++ b/server/src/domain/download/download.service.spec.ts @@ -2,8 +2,8 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; import { DownloadResponseDto } from 'src/domain/download/download.dto'; import { DownloadService } from 'src/domain/download/download.service'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; import { CacheControl, ImmichFileResponse } from 'src/utils'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/download/download.service.ts b/server/src/domain/download/download.service.ts index 7a0fc2ca6..5c790548d 100644 --- a/server/src/domain/download/download.service.ts +++ b/server/src/domain/download/download.service.ts @@ -5,10 +5,10 @@ import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/download.dto'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IStorageRepository, ImmichReadStream } from 'src/domain/repositories/storage.repository'; import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IStorageRepository, ImmichReadStream } from 'src/interfaces/storage.repository'; import { CacheControl, HumanReadableSize, ImmichFileResponse, usePagination } from 'src/utils'; @Injectable() diff --git a/server/src/domain/job/job.service.spec.ts b/server/src/domain/job/job.service.spec.ts index 2dee51cd6..1b46ec936 100644 --- a/server/src/domain/job/job.service.spec.ts +++ b/server/src/domain/job/job.service.spec.ts @@ -2,12 +2,12 @@ import { BadRequestException } from '@nestjs/common'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; import { JobService } from 'src/domain/job/job.service'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { IJobRepository, JobHandler, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { IJobRepository, JobHandler, JobItem, JobStatus } from 'src/interfaces/job.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; diff --git a/server/src/domain/job/job.service.ts b/server/src/domain/job/job.service.ts index b50d26de4..567603656 100644 --- a/server/src/domain/job/job.service.ts +++ b/server/src/domain/job/job.service.ts @@ -3,13 +3,13 @@ import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { ConcurrentQueueName, JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/domain/job/job.dto'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { IJobRepository, JobHandler, JobItem, JobStatus, QueueCleanType } from 'src/domain/repositories/job.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetType } from 'src/infra/entities/asset.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { IJobRepository, JobHandler, JobItem, JobStatus, QueueCleanType } from 'src/interfaces/job.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; @Injectable() export class JobService { diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/domain/library/library.service.spec.ts index c1f2cc38c..00592dc1e 100644 --- a/server/src/domain/library/library.service.spec.ts +++ b/server/src/domain/library/library.service.spec.ts @@ -7,17 +7,17 @@ import { JobName } from 'src/domain/job/job.constants'; import { ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; import { mapLibrary } from 'src/domain/library/library.dto'; import { LibraryService } from 'src/domain/library/library.service'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { IStorageRepository, StorageEventType } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetType } from 'src/infra/entities/asset.entity'; import { LibraryType } from 'src/infra/entities/library.entity'; import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; import { UserEntity } from 'src/infra/entities/user.entity'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IDatabaseRepository } from 'src/interfaces/database.repository'; +import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { IStorageRepository, StorageEventType } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { libraryStub } from 'test/fixtures/library.stub'; diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts index 30b1d1975..b859d0046 100644 --- a/server/src/domain/library/library.service.ts +++ b/server/src/domain/library/library.service.ts @@ -23,17 +23,17 @@ import { ValidateLibraryResponseDto, mapLibrary, } from 'src/domain/library/library.dto'; -import { IAssetRepository, WithProperty } from 'src/domain/repositories/asset.repository'; -import { InternalEvent, InternalEventMap } from 'src/domain/repositories/communication.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { DatabaseLock, IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { IStorageRepository, StorageEventType } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetType } from 'src/infra/entities/asset.entity'; import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAssetRepository, WithProperty } from 'src/interfaces/asset.repository'; +import { InternalEvent, InternalEventMap } from 'src/interfaces/communication.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { DatabaseLock, IDatabaseRepository } from 'src/interfaces/database.repository'; +import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { IStorageRepository, StorageEventType } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { handlePromiseError, usePagination } from 'src/utils'; import { validateCronExpression } from 'src/validation'; diff --git a/server/src/domain/media/media.service.spec.ts b/server/src/domain/media/media.service.spec.ts index 9a5727ef2..ad3ed3d22 100644 --- a/server/src/domain/media/media.service.spec.ts +++ b/server/src/domain/media/media.service.spec.ts @@ -1,14 +1,6 @@ import { Stats } from 'node:fs'; import { JobName } from 'src/domain/job/job.constants'; import { MediaService } from 'src/domain/media/media.service'; -import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; -import { IMediaRepository } from 'src/domain/repositories/media.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; import { @@ -20,6 +12,14 @@ import { TranscodePolicy, VideoCodec, } from 'src/infra/entities/system-config.entity'; +import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IMediaRepository } from 'src/interfaces/media.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { faceStub } from 'test/fixtures/face.stub'; import { probeStub } from 'test/fixtures/media.stub'; diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index 8678203d7..6807e962a 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -13,19 +13,6 @@ import { VAAPIConfig, VP9Config, } from 'src/domain/media/media.util'; -import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IJobRepository, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; -import { - AudioStreamInfo, - IMediaRepository, - VideoCodecHWConfig, - VideoStreamInfo, -} from 'src/domain/repositories/media.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { AssetPathType } from 'src/infra/entities/move.entity'; @@ -38,6 +25,19 @@ import { VideoCodec, } from 'src/infra/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IJobRepository, JobItem, JobStatus } from 'src/interfaces/job.repository'; +import { + AudioStreamInfo, + IMediaRepository, + VideoCodecHWConfig, + VideoStreamInfo, +} from 'src/interfaces/media.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { usePagination } from 'src/utils'; @Injectable() diff --git a/server/src/domain/media/media.util.ts b/server/src/domain/media/media.util.ts index 224e55a21..bc9fa4887 100644 --- a/server/src/domain/media/media.util.ts +++ b/server/src/domain/media/media.util.ts @@ -1,11 +1,3 @@ -import { - AudioStreamInfo, - BitrateDistribution, - TranscodeOptions, - VideoCodecHWConfig, - VideoCodecSWConfig, - VideoStreamInfo, -} from 'src/domain/repositories/media.repository'; import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; import { CQMode, @@ -14,6 +6,14 @@ import { TranscodeTarget, VideoCodec, } from 'src/infra/entities/system-config.entity'; +import { + AudioStreamInfo, + BitrateDistribution, + TranscodeOptions, + VideoCodecHWConfig, + VideoCodecSWConfig, + VideoStreamInfo, +} from 'src/interfaces/media.repository'; class BaseConfig implements VideoCodecSWConfig { presets = ['veryslow', 'slower', 'slow', 'medium', 'fast', 'faster', 'veryfast', 'superfast', 'ultrafast']; diff --git a/server/src/domain/metadata/metadata.service.spec.ts b/server/src/domain/metadata/metadata.service.spec.ts index e23da47ba..f8483d6ef 100644 --- a/server/src/domain/metadata/metadata.service.spec.ts +++ b/server/src/domain/metadata/metadata.service.spec.ts @@ -5,21 +5,21 @@ import { Stats } from 'node:fs'; import { constants } from 'node:fs/promises'; import { JobName } from 'src/domain/job/job.constants'; import { MetadataService, Orientation } from 'src/domain/metadata/metadata.service'; -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; -import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; -import { IMediaRepository } from 'src/domain/repositories/media.repository'; -import { IMetadataRepository, ImmichTags } from 'src/domain/repositories/metadata.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; +import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IDatabaseRepository } from 'src/interfaces/database.repository'; +import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IMediaRepository } from 'src/interfaces/media.repository'; +import { IMetadataRepository, ImmichTags } from 'src/interfaces/metadata.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { fileStub } from 'test/fixtures/file.stub'; import { probeStub } from 'test/fixtures/media.stub'; diff --git a/server/src/domain/metadata/metadata.service.ts b/server/src/domain/metadata/metadata.service.ts index 68b813eae..d7f98e245 100644 --- a/server/src/domain/metadata/metadata.service.ts +++ b/server/src/domain/metadata/metadata.service.ts @@ -10,21 +10,21 @@ import { StorageCore } from 'src/cores/storage.core'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; -import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { DatabaseLock, IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; -import { IMediaRepository } from 'src/domain/repositories/media.repository'; -import { IMetadataRepository, ImmichTags } from 'src/domain/repositories/metadata.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; +import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { DatabaseLock, IDatabaseRepository } from 'src/interfaces/database.repository'; +import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IMediaRepository } from 'src/interfaces/media.repository'; +import { IMetadataRepository, ImmichTags } from 'src/interfaces/metadata.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { handlePromiseError, usePagination } from 'src/utils'; /** look for a date from these tags (in order) */ diff --git a/server/src/domain/partner/partner.service.spec.ts b/server/src/domain/partner/partner.service.spec.ts index b1b7fb097..487818b3d 100644 --- a/server/src/domain/partner/partner.service.spec.ts +++ b/server/src/domain/partner/partner.service.spec.ts @@ -1,9 +1,9 @@ import { BadRequestException } from '@nestjs/common'; import { PartnerResponseDto } from 'src/domain/partner/partner.dto'; import { PartnerService } from 'src/domain/partner/partner.service'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IPartnerRepository, PartnerDirection } from 'src/domain/repositories/partner.repository'; import { UserAvatarColor } from 'src/infra/entities/user.entity'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IPartnerRepository, PartnerDirection } from 'src/interfaces/partner.repository'; import { authStub } from 'test/fixtures/auth.stub'; import { partnerStub } from 'test/fixtures/partner.stub'; import { newPartnerRepositoryMock } from 'test/repositories/partner.repository.mock'; diff --git a/server/src/domain/partner/partner.service.ts b/server/src/domain/partner/partner.service.ts index 9bf305b2b..2528b44be 100644 --- a/server/src/domain/partner/partner.service.ts +++ b/server/src/domain/partner/partner.service.ts @@ -2,10 +2,10 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { AccessCore, Permission } from 'src/cores/access.core'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IPartnerRepository, PartnerDirection, PartnerIds } from 'src/domain/repositories/partner.repository'; import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IPartnerRepository, PartnerDirection, PartnerIds } from 'src/interfaces/partner.repository'; @Injectable() export class PartnerService { diff --git a/server/src/domain/person/person.service.spec.ts b/server/src/domain/person/person.service.spec.ts index a4b1282d3..042469d7e 100644 --- a/server/src/domain/person/person.service.spec.ts +++ b/server/src/domain/person/person.service.spec.ts @@ -3,18 +3,18 @@ import { BulkIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-respo import { JobName } from 'src/domain/job/job.constants'; import { PersonResponseDto, mapFaces, mapPerson } from 'src/domain/person/person.dto'; import { PersonService } from 'src/domain/person/person.service'; -import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; -import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; -import { IMediaRepository } from 'src/domain/repositories/media.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { FaceSearchResult, ISearchRepository } from 'src/domain/repositories/search.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; import { Colorspace, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; +import { IMediaRepository } from 'src/interfaces/media.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { FaceSearchResult, ISearchRepository } from 'src/interfaces/search.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { CacheControl, ImmichFileResponse } from 'src/utils'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/person/person.service.ts b/server/src/domain/person/person.service.ts index 62b13452a..9e56e4b18 100644 --- a/server/src/domain/person/person.service.ts +++ b/server/src/domain/person/person.service.ts @@ -24,20 +24,20 @@ import { mapFaces, mapPerson, } from 'src/domain/person/person.dto'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IJobRepository, JobItem, JobStatus } from 'src/domain/repositories/job.repository'; -import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; -import { CropOptions, IMediaRepository } from 'src/domain/repositories/media.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository, UpdateFacesData } from 'src/domain/repositories/person.repository'; -import { ISearchRepository } from 'src/domain/repositories/search.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { PersonPathType } from 'src/infra/entities/move.entity'; import { PersonEntity } from 'src/infra/entities/person.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IJobRepository, JobItem, JobStatus } from 'src/interfaces/job.repository'; +import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; +import { CropOptions, IMediaRepository } from 'src/interfaces/media.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository, UpdateFacesData } from 'src/interfaces/person.repository'; +import { ISearchRepository } from 'src/interfaces/search.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { CacheControl, ImmichFileResponse, usePagination } from 'src/utils'; import { IsNull } from 'typeorm'; diff --git a/server/src/domain/search/search.service.spec.ts b/server/src/domain/search/search.service.spec.ts index ae5e94a76..f9313d277 100644 --- a/server/src/domain/search/search.service.spec.ts +++ b/server/src/domain/search/search.service.spec.ts @@ -1,14 +1,14 @@ import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; -import { IMetadataRepository } from 'src/domain/repositories/metadata.repository'; -import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { ISearchRepository } from 'src/domain/repositories/search.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SearchDto } from 'src/domain/search/dto/search.dto'; import { SearchService } from 'src/domain/search/search.service'; import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; +import { IMetadataRepository } from 'src/interfaces/metadata.repository'; +import { IPartnerRepository } from 'src/interfaces/partner.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { ISearchRepository } from 'src/interfaces/search.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { personStub } from 'test/fixtures/person.stub'; diff --git a/server/src/domain/search/search.service.ts b/server/src/domain/search/search.service.ts index ae8738cb6..9778c6d3d 100644 --- a/server/src/domain/search/search.service.ts +++ b/server/src/domain/search/search.service.ts @@ -3,13 +3,6 @@ import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { PersonResponseDto } from 'src/domain/person/person.dto'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; -import { IMetadataRepository } from 'src/domain/repositories/metadata.repository'; -import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { ISearchRepository, SearchExploreItem, SearchStrategy } from 'src/domain/repositories/search.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SearchSuggestionRequestDto, SearchSuggestionType } from 'src/domain/search/dto/search-suggestion.dto'; import { MetadataSearchDto, @@ -23,6 +16,13 @@ import { import { SearchResponseDto } from 'src/domain/search/response-dto/search-response.dto'; import { AssetOrder } from 'src/infra/entities/album.entity'; import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; +import { IMetadataRepository } from 'src/interfaces/metadata.repository'; +import { IPartnerRepository } from 'src/interfaces/partner.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { ISearchRepository, SearchExploreItem, SearchStrategy } from 'src/interfaces/search.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; @Injectable() export class SearchService { diff --git a/server/src/domain/server-info/server-info.service.spec.ts b/server/src/domain/server-info/server-info.service.spec.ts index 41bc8fb6f..05f05cc8f 100644 --- a/server/src/domain/server-info/server-info.service.spec.ts +++ b/server/src/domain/server-info/server-info.service.spec.ts @@ -1,12 +1,12 @@ import { serverVersion } from 'src/domain/domain.constant'; -import { ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { ServerInfoService } from 'src/domain/server-info/server-info.service'; import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; +import { ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index 9e72c7108..533bb42d9 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -3,12 +3,6 @@ import { DateTime } from 'luxon'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { Version, isDev, mimeTypes, serverVersion } from 'src/domain/domain.constant'; -import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; -import { IUserRepository, UserStatsQueryResponse } from 'src/domain/repositories/user.repository'; import { ServerConfigDto, ServerFeaturesDto, @@ -20,6 +14,12 @@ import { } from 'src/domain/server-info/server-info.dto'; import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; +import { IUserRepository, UserStatsQueryResponse } from 'src/interfaces/user.repository'; import { asHumanReadable } from 'src/utils'; @Injectable() diff --git a/server/src/domain/shared-link/shared-link.service.spec.ts b/server/src/domain/shared-link/shared-link.service.spec.ts index 6e2da5a64..3b15138f4 100644 --- a/server/src/domain/shared-link/shared-link.service.spec.ts +++ b/server/src/domain/shared-link/shared-link.service.spec.ts @@ -1,10 +1,10 @@ import { BadRequestException, ForbiddenException, UnauthorizedException } from '@nestjs/common'; import _ from 'lodash'; import { AssetIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; import { SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; import { albumStub } from 'test/fixtures/album.stub'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/shared-link/shared-link.service.ts b/server/src/domain/shared-link/shared-link.service.ts index a62acb6bf..34619cc5c 100644 --- a/server/src/domain/shared-link/shared-link.service.ts +++ b/server/src/domain/shared-link/shared-link.service.ts @@ -3,9 +3,6 @@ import { AccessCore, Permission } from 'src/cores/access.core'; import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; import { SharedLinkResponseDto, mapSharedLink, @@ -14,6 +11,9 @@ import { import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { SharedLinkEntity, SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; import { OpenGraphTags } from 'src/utils'; @Injectable() diff --git a/server/src/domain/smart-info/dto/model-config.dto.ts b/server/src/domain/smart-info/dto/model-config.dto.ts index e0977c4da..b63ec7414 100644 --- a/server/src/domain/smart-info/dto/model-config.dto.ts +++ b/server/src/domain/smart-info/dto/model-config.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsNotEmpty, IsNumber, IsString, Max, Min } from 'class-validator'; -import { CLIPMode, ModelType } from 'src/domain/repositories/machine-learning.repository'; +import { CLIPMode, ModelType } from 'src/interfaces/machine-learning.repository'; import { Optional, ValidateBoolean } from 'src/validation'; export class ModelConfig { diff --git a/server/src/domain/smart-info/smart-info.service.spec.ts b/server/src/domain/smart-info/smart-info.service.spec.ts index e83e823db..fec43eb08 100644 --- a/server/src/domain/smart-info/smart-info.service.spec.ts +++ b/server/src/domain/smart-info/smart-info.service.spec.ts @@ -1,14 +1,14 @@ import { JobName } from 'src/domain/job/job.constants'; -import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; -import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { IJobRepository } from 'src/domain/repositories/job.repository'; -import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; -import { ISearchRepository } from 'src/domain/repositories/search.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { cleanModelName, getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; +import { IDatabaseRepository } from 'src/interfaces/database.repository'; +import { IJobRepository } from 'src/interfaces/job.repository'; +import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; +import { ISearchRepository } from 'src/interfaces/search.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; diff --git a/server/src/domain/smart-info/smart-info.service.ts b/server/src/domain/smart-info/smart-info.service.ts index 333c8faaf..a7d470008 100644 --- a/server/src/domain/smart-info/smart-info.service.ts +++ b/server/src/domain/smart-info/smart-info.service.ts @@ -2,13 +2,13 @@ import { Inject, Injectable } from '@nestjs/common'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; -import { IAssetRepository, WithoutProperty } from 'src/domain/repositories/asset.repository'; -import { DatabaseLock, IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; -import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; -import { ISearchRepository } from 'src/domain/repositories/search.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { ImmichLogger } from 'src/infra/logger'; +import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; +import { DatabaseLock, IDatabaseRepository } from 'src/interfaces/database.repository'; +import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; +import { ISearchRepository } from 'src/interfaces/search.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { usePagination } from 'src/utils'; @Injectable() diff --git a/server/src/domain/storage-template/storage-template.service.spec.ts b/server/src/domain/storage-template/storage-template.service.spec.ts index ce378bf9b..c73dfbdcf 100644 --- a/server/src/domain/storage-template/storage-template.service.spec.ts +++ b/server/src/domain/storage-template/storage-template.service.spec.ts @@ -1,19 +1,19 @@ import { when } from 'jest-when'; import { Stats } from 'node:fs'; import { SystemConfigCore, defaults } from 'src/cores/system-config.core'; -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { JobStatus } from 'src/domain/repositories/job.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; import { AssetPathType } from 'src/infra/entities/move.entity'; import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IDatabaseRepository } from 'src/interfaces/database.repository'; +import { JobStatus } from 'src/interfaces/job.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { userStub } from 'test/fixtures/user.stub'; import { newAlbumRepositoryMock } from 'test/repositories/album.repository.mock'; diff --git a/server/src/domain/storage-template/storage-template.service.ts b/server/src/domain/storage-template/storage-template.service.ts index b79426b1f..480f97368 100644 --- a/server/src/domain/storage-template/storage-template.service.ts +++ b/server/src/domain/storage-template/storage-template.service.ts @@ -8,17 +8,6 @@ import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; import { IEntityJob } from 'src/domain/job/job.interface'; -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { InternalEvent, InternalEventMap } from 'src/domain/repositories/communication.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { DatabaseLock, IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { JobStatus } from 'src/domain/repositories/job.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { supportedDayTokens, supportedHourTokens, @@ -32,6 +21,17 @@ import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { AssetPathType } from 'src/infra/entities/move.entity'; import { SystemConfig } from 'src/infra/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { InternalEvent, InternalEventMap } from 'src/interfaces/communication.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { DatabaseLock, IDatabaseRepository } from 'src/interfaces/database.repository'; +import { JobStatus } from 'src/interfaces/job.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { getLivePhotoMotionFilename, usePagination } from 'src/utils'; export interface MoveAssetMetadata { diff --git a/server/src/domain/storage/storage.service.spec.ts b/server/src/domain/storage/storage.service.spec.ts index 9181af76e..2791c9630 100644 --- a/server/src/domain/storage/storage.service.spec.ts +++ b/server/src/domain/storage/storage.service.spec.ts @@ -1,5 +1,5 @@ -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { StorageService } from 'src/domain/storage/storage.service'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; describe(StorageService.name, () => { diff --git a/server/src/domain/storage/storage.service.ts b/server/src/domain/storage/storage.service.ts index 5c75a9921..9df3dd778 100644 --- a/server/src/domain/storage/storage.service.ts +++ b/server/src/domain/storage/storage.service.ts @@ -1,9 +1,9 @@ import { Inject, Injectable } from '@nestjs/common'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { IDeleteFilesJob } from 'src/domain/job/job.interface'; -import { JobStatus } from 'src/domain/repositories/job.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; import { ImmichLogger } from 'src/infra/logger'; +import { JobStatus } from 'src/interfaces/job.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; @Injectable() export class StorageService { diff --git a/server/src/domain/system-config/system-config.service.spec.ts b/server/src/domain/system-config/system-config.service.spec.ts index 4eb1619ee..94db09bab 100644 --- a/server/src/domain/system-config/system-config.service.spec.ts +++ b/server/src/domain/system-config/system-config.service.spec.ts @@ -1,9 +1,6 @@ import { BadRequestException } from '@nestjs/common'; import { defaults } from 'src/cores/system-config.core'; import { QueueName } from 'src/domain/job/job.constants'; -import { ICommunicationRepository, ServerEvent } from 'src/domain/repositories/communication.repository'; -import { ISearchRepository } from 'src/domain/repositories/search.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SystemConfigService } from 'src/domain/system-config/system-config.service'; import { AudioCodec, @@ -19,6 +16,9 @@ import { VideoCodec, } from 'src/infra/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { ICommunicationRepository, ServerEvent } from 'src/interfaces/communication.repository'; +import { ISearchRepository } from 'src/interfaces/search.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; diff --git a/server/src/domain/system-config/system-config.service.ts b/server/src/domain/system-config/system-config.service.ts index 856e80d49..bd2c30805 100644 --- a/server/src/domain/system-config/system-config.service.ts +++ b/server/src/domain/system-config/system-config.service.ts @@ -3,15 +3,6 @@ import { OnEvent } from '@nestjs/event-emitter'; import { instanceToPlain } from 'class-transformer'; import _ from 'lodash'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { - ClientEvent, - ICommunicationRepository, - InternalEvent, - InternalEventMap, - ServerEvent, -} from 'src/domain/repositories/communication.repository'; -import { ISearchRepository } from 'src/domain/repositories/search.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SystemConfigDto, mapConfig } from 'src/domain/system-config/dto/system-config.dto'; import { SystemConfigTemplateStorageOptionDto } from 'src/domain/system-config/response-dto/system-config-template-storage-option.dto'; import { @@ -26,6 +17,15 @@ import { } from 'src/domain/system-config/system-config.constants'; import { LogLevel, SystemConfig } from 'src/infra/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { + ClientEvent, + ICommunicationRepository, + InternalEvent, + InternalEventMap, + ServerEvent, +} from 'src/interfaces/communication.repository'; +import { ISearchRepository } from 'src/interfaces/search.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; @Injectable() export class SystemConfigService { diff --git a/server/src/domain/tag/tag.service.spec.ts b/server/src/domain/tag/tag.service.spec.ts index ae578068a..012a745ee 100644 --- a/server/src/domain/tag/tag.service.spec.ts +++ b/server/src/domain/tag/tag.service.spec.ts @@ -1,9 +1,9 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; import { AssetIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { ITagRepository } from 'src/domain/repositories/tag.repository'; import { TagService } from 'src/domain/tag/tag.service'; import { TagType } from 'src/infra/entities/tag.entity'; +import { ITagRepository } from 'src/interfaces/tag.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { tagResponseStub, tagStub } from 'test/fixtures/tag.stub'; diff --git a/server/src/domain/tag/tag.service.ts b/server/src/domain/tag/tag.service.ts index 3a7a5b579..b04e251f7 100644 --- a/server/src/domain/tag/tag.service.ts +++ b/server/src/domain/tag/tag.service.ts @@ -3,9 +3,9 @@ import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { ITagRepository } from 'src/domain/repositories/tag.repository'; import { TagResponseDto, mapTag } from 'src/domain/tag/tag-response.dto'; import { CreateTagDto, UpdateTagDto } from 'src/domain/tag/tag.dto'; +import { ITagRepository } from 'src/interfaces/tag.repository'; @Injectable() export class TagService { diff --git a/server/src/domain/trash/trash.service.spec.ts b/server/src/domain/trash/trash.service.spec.ts index 90320326f..021c8e526 100644 --- a/server/src/domain/trash/trash.service.spec.ts +++ b/server/src/domain/trash/trash.service.spec.ts @@ -1,9 +1,9 @@ import { BadRequestException } from '@nestjs/common'; import { JobName } from 'src/domain/job/job.constants'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { IJobRepository } from 'src/domain/repositories/job.repository'; import { TrashService } from 'src/domain/trash/trash.service'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { IJobRepository } from 'src/interfaces/job.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; diff --git a/server/src/domain/trash/trash.service.ts b/server/src/domain/trash/trash.service.ts index 2ae09c104..2043b4248 100644 --- a/server/src/domain/trash/trash.service.ts +++ b/server/src/domain/trash/trash.service.ts @@ -4,10 +4,10 @@ import { AccessCore, Permission } from 'src/cores/access.core'; import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { ClientEvent, ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { IJobRepository } from 'src/interfaces/job.repository'; import { usePagination } from 'src/utils'; export class TrashService { diff --git a/server/src/domain/user/user.service.spec.ts b/server/src/domain/user/user.service.spec.ts index d590d7fda..c187e71cc 100644 --- a/server/src/domain/user/user.service.spec.ts +++ b/server/src/domain/user/user.service.spec.ts @@ -6,17 +6,17 @@ import { } from '@nestjs/common'; import { when } from 'jest-when'; import { JobName } from 'src/domain/job/job.constants'; -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IJobRepository } from 'src/domain/repositories/job.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { UserService } from 'src/domain/user/user.service'; import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IJobRepository } from 'src/interfaces/job.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { CacheControl, ImmichFileResponse } from 'src/utils'; import { authStub } from 'test/fixtures/auth.stub'; import { systemConfigStub } from 'test/fixtures/system-config.stub'; diff --git a/server/src/domain/user/user.service.ts b/server/src/domain/user/user.service.ts index 022b93492..3b2bbf370 100644 --- a/server/src/domain/user/user.service.ts +++ b/server/src/domain/user/user.service.ts @@ -7,13 +7,6 @@ import { UserCore } from 'src/cores/user.core'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { JobName } from 'src/domain/job/job.constants'; import { IEntityJob } from 'src/domain/job/job.interface'; -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IJobRepository, JobStatus } from 'src/domain/repositories/job.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { IUserRepository, UserFindOptions } from 'src/domain/repositories/user.repository'; import { CreateUserDto } from 'src/domain/user/dto/create-user.dto'; import { DeleteUserDto } from 'src/domain/user/dto/delete-user.dto'; import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; @@ -24,6 +17,13 @@ import { import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { IUserRepository, UserFindOptions } from 'src/interfaces/user.repository'; import { CacheControl, ImmichFileResponse } from 'src/utils'; @Injectable() diff --git a/server/src/immich/api-v1/asset/asset.service.spec.ts b/server/src/immich/api-v1/asset/asset.service.spec.ts index fff1c0e1e..37f1a540f 100644 --- a/server/src/immich/api-v1/asset/asset.service.spec.ts +++ b/server/src/immich/api-v1/asset/asset.service.spec.ts @@ -1,16 +1,16 @@ import { when } from 'jest-when'; import { JobName } from 'src/domain/job/job.constants'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IJobRepository } from 'src/domain/repositories/job.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; import { AssetService } from 'src/immich/api-v1/asset/asset.service'; import { CreateAssetDto } from 'src/immich/api-v1/asset/dto/create-asset.dto'; import { AssetRejectReason, AssetUploadAction } from 'src/immich/api-v1/asset/response-dto/asset-check-response.dto'; import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IJobRepository } from 'src/interfaces/job.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { fileStub } from 'test/fixtures/file.stub'; diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index aa157aaed..879128077 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -11,12 +11,6 @@ import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset- import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; import { JobName } from 'src/domain/job/job.constants'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IJobRepository } from 'src/domain/repositories/job.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; import { AssetBulkUploadCheckDto } from 'src/immich/api-v1/asset/dto/asset-check.dto'; import { AssetSearchDto } from 'src/immich/api-v1/asset/dto/asset-search.dto'; @@ -36,6 +30,12 @@ import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/ import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IJobRepository } from 'src/interfaces/job.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/utils'; import { QueryFailedError } from 'typeorm'; diff --git a/server/src/immich/app.utils.ts b/server/src/immich/app.utils.ts index 456c9cf4e..f0e4ba661 100644 --- a/server/src/immich/app.utils.ts +++ b/server/src/immich/app.utils.ts @@ -15,8 +15,8 @@ import path, { isAbsolute } from 'node:path'; import { promisify } from 'node:util'; import { IMMICH_ACCESS_COOKIE, IMMICH_API_KEY_HEADER, IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; import { serverVersion } from 'src/domain/domain.constant'; -import { ImmichReadStream } from 'src/domain/repositories/storage.repository'; import { ImmichLogger } from 'src/infra/logger'; +import { ImmichReadStream } from 'src/interfaces/storage.repository'; import { Metadata } from 'src/middleware/auth.guard'; import { CacheControl, ImmichFileResponse, isConnectionAborted } from 'src/utils'; diff --git a/server/src/infra/database.config.ts b/server/src/infra/database.config.ts index ccb0f6a32..fd6286f1b 100644 --- a/server/src/infra/database.config.ts +++ b/server/src/infra/database.config.ts @@ -1,4 +1,4 @@ -import { DatabaseExtension } from 'src/domain/repositories/database.repository'; +import { DatabaseExtension } from 'src/interfaces/database.repository'; import { DataSource } from 'typeorm'; import { PostgresConnectionOptions } from 'typeorm/driver/postgres/PostgresConnectionOptions.js'; diff --git a/server/src/infra/infra.module.ts b/server/src/infra/infra.module.ts index b1636c5e2..9864a0191 100644 --- a/server/src/infra/infra.module.ts +++ b/server/src/infra/infra.module.ts @@ -6,33 +6,6 @@ import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpenTelemetryModule } from 'nestjs-otel'; import { bullConfig, bullQueues, immichAppConfig } from 'src/config'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; -import { IActivityRepository } from 'src/domain/repositories/activity.repository'; -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; -import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; -import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; -import { IAuditRepository } from 'src/domain/repositories/audit.repository'; -import { ICommunicationRepository } from 'src/domain/repositories/communication.repository'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; -import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; -import { IJobRepository } from 'src/domain/repositories/job.repository'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; -import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; -import { IMediaRepository } from 'src/domain/repositories/media.repository'; -import { IMetadataRepository } from 'src/domain/repositories/metadata.repository'; -import { IMoveRepository } from 'src/domain/repositories/move.repository'; -import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; -import { IPersonRepository } from 'src/domain/repositories/person.repository'; -import { ISearchRepository } from 'src/domain/repositories/search.repository'; -import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; -import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; -import { IStorageRepository } from 'src/domain/repositories/storage.repository'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; -import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; -import { ITagRepository } from 'src/domain/repositories/tag.repository'; -import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; import { databaseConfig } from 'src/infra/database.config'; import { databaseEntities } from 'src/infra/entities'; import { otelConfig } from 'src/infra/instrumentation'; @@ -63,6 +36,33 @@ import { SystemMetadataRepository } from 'src/infra/repositories/system-metadata import { TagRepository } from 'src/infra/repositories/tag.repository'; import { UserTokenRepository } from 'src/infra/repositories/user-token.repository'; import { UserRepository } from 'src/infra/repositories/user.repository'; +import { IAccessRepository } from 'src/interfaces/access.repository'; +import { IActivityRepository } from 'src/interfaces/activity.repository'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; +import { IKeyRepository } from 'src/interfaces/api-key.repository'; +import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; +import { IAuditRepository } from 'src/interfaces/audit.repository'; +import { ICommunicationRepository } from 'src/interfaces/communication.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { IDatabaseRepository } from 'src/interfaces/database.repository'; +import { IJobRepository } from 'src/interfaces/job.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; +import { IMediaRepository } from 'src/interfaces/media.repository'; +import { IMetadataRepository } from 'src/interfaces/metadata.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; +import { IPartnerRepository } from 'src/interfaces/partner.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; +import { ISearchRepository } from 'src/interfaces/search.repository'; +import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; +import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; +import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; +import { ITagRepository } from 'src/interfaces/tag.repository'; +import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; const providers: Provider[] = [ { provide: IActivityRepository, useClass: ActivityRepository }, diff --git a/server/src/infra/infra.utils.ts b/server/src/infra/infra.utils.ts index 41c57904b..36f1ef4bf 100644 --- a/server/src/infra/infra.utils.ts +++ b/server/src/infra/infra.utils.ts @@ -1,6 +1,6 @@ import _ from 'lodash'; -import { AssetSearchBuilderOptions } from 'src/domain/repositories/search.repository'; import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetSearchBuilderOptions } from 'src/interfaces/search.repository'; import { Paginated, PaginatedBuilderOptions, PaginationMode, PaginationOptions, PaginationResult } from 'src/utils'; import { Between, diff --git a/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts b/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts index 505b4dbcb..b045ba62b 100644 --- a/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts +++ b/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts @@ -1,5 +1,5 @@ -import { DatabaseExtension } from 'src/domain/repositories/database.repository'; import { vectorExt } from 'src/infra/database.config'; +import { DatabaseExtension } from 'src/interfaces/database.repository'; import { MigrationInterface, QueryRunner } from 'typeorm'; export class AddCLIPEmbeddingIndex1700713994428 implements MigrationInterface { diff --git a/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts b/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts index e79c22045..e77ce3b0b 100644 --- a/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts +++ b/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts @@ -1,5 +1,5 @@ -import { DatabaseExtension } from 'src/domain/repositories/database.repository'; import { vectorExt } from 'src/infra/database.config'; +import { DatabaseExtension } from 'src/interfaces/database.repository'; import { MigrationInterface, QueryRunner } from 'typeorm'; export class AddFaceEmbeddingIndex1700714033632 implements MigrationInterface { diff --git a/server/src/infra/repositories/access.repository.ts b/server/src/infra/repositories/access.repository.ts index d16d6a6aa..c6b7bc0fd 100644 --- a/server/src/infra/repositories/access.repository.ts +++ b/server/src/infra/repositories/access.repository.ts @@ -1,6 +1,5 @@ import { InjectRepository } from '@nestjs/typeorm'; import { ChunkedSet, DummyValue, GenerateSql } from 'src/decorators'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; import { ActivityEntity } from 'src/infra/entities/activity.entity'; import { AlbumEntity } from 'src/infra/entities/album.entity'; import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; @@ -11,6 +10,7 @@ import { PersonEntity } from 'src/infra/entities/person.entity'; import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { IAccessRepository } from 'src/interfaces/access.repository'; import { Brackets, In, Repository } from 'typeorm'; type IActivityAccess = IAccessRepository['activity']; diff --git a/server/src/infra/repositories/activity.repository.ts b/server/src/infra/repositories/activity.repository.ts index 1cfe3e264..4c1cec6d6 100644 --- a/server/src/infra/repositories/activity.repository.ts +++ b/server/src/infra/repositories/activity.repository.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { IActivityRepository } from 'src/domain/repositories/activity.repository'; import { ActivityEntity } from 'src/infra/entities/activity.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { IActivityRepository } from 'src/interfaces/activity.repository'; import { IsNull, Repository } from 'typeorm'; export interface ActivitySearch { diff --git a/server/src/infra/repositories/album.repository.ts b/server/src/infra/repositories/album.repository.ts index b31a894b5..ca4d4a913 100644 --- a/server/src/infra/repositories/album.repository.ts +++ b/server/src/infra/repositories/album.repository.ts @@ -2,17 +2,17 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import _ from 'lodash'; import { Chunked, ChunkedArray, DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from 'src/decorators'; +import { dataSource } from 'src/infra/database.config'; +import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; import { AlbumAsset, AlbumAssetCount, AlbumAssets, AlbumInfoOptions, IAlbumRepository, -} from 'src/domain/repositories/album.repository'; -import { dataSource } from 'src/infra/database.config'; -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; +} from 'src/interfaces/album.repository'; import { setUnion } from 'src/utils'; import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/api-key.repository.ts b/server/src/infra/repositories/api-key.repository.ts index 5bacfded5..0add8512a 100644 --- a/server/src/infra/repositories/api-key.repository.ts +++ b/server/src/infra/repositories/api-key.repository.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { IKeyRepository } from 'src/interfaces/api-key.repository'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/asset-stack.repository.ts b/server/src/infra/repositories/asset-stack.repository.ts index 556098ff1..0f984f4ea 100644 --- a/server/src/infra/repositories/asset-stack.repository.ts +++ b/server/src/infra/repositories/asset-stack.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/asset.repository.ts b/server/src/infra/repositories/asset.repository.ts index a57e852d2..3026c5386 100644 --- a/server/src/infra/repositories/asset.repository.ts +++ b/server/src/infra/repositories/asset.repository.ts @@ -3,6 +3,13 @@ import { InjectRepository } from '@nestjs/typeorm'; import { DateTime } from 'luxon'; import path from 'node:path'; import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; +import { AssetOrder } from 'src/infra/entities/album.entity'; +import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; +import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { OptionalBetween, paginate, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; import { AssetBuilderOptions, AssetCreate, @@ -23,15 +30,8 @@ import { TimeBucketSize, WithProperty, WithoutProperty, -} from 'src/domain/repositories/asset.repository'; -import { AssetSearchOptions, SearchExploreItem } from 'src/domain/repositories/search.repository'; -import { AssetOrder } from 'src/infra/entities/album.entity'; -import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; -import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; -import { OptionalBetween, paginate, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; -import { Instrumentation } from 'src/infra/instrumentation'; +} from 'src/interfaces/asset.repository'; +import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.repository'; import { Paginated, PaginationMode, PaginationOptions } from 'src/utils'; import { Brackets, diff --git a/server/src/infra/repositories/audit.repository.ts b/server/src/infra/repositories/audit.repository.ts index 71c89c8d0..bfd55336d 100644 --- a/server/src/infra/repositories/audit.repository.ts +++ b/server/src/infra/repositories/audit.repository.ts @@ -1,7 +1,7 @@ import { InjectRepository } from '@nestjs/typeorm'; -import { AuditSearch, IAuditRepository } from 'src/domain/repositories/audit.repository'; import { AuditEntity } from 'src/infra/entities/audit.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { AuditSearch, IAuditRepository } from 'src/interfaces/audit.repository'; import { LessThan, MoreThan, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/communication.repository.ts b/server/src/infra/repositories/communication.repository.ts index 854c6d1f3..e92fe1387 100644 --- a/server/src/infra/repositories/communication.repository.ts +++ b/server/src/infra/repositories/communication.repository.ts @@ -8,6 +8,8 @@ import { } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; import { AuthService } from 'src/domain/auth/auth.service'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; import { ClientEvent, ICommunicationRepository, @@ -15,9 +17,7 @@ import { OnConnectCallback, OnServerEventCallback, ServerEvent, -} from 'src/domain/repositories/communication.repository'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; +} from 'src/interfaces/communication.repository'; @Instrumentation() @WebSocketGateway({ diff --git a/server/src/infra/repositories/crypto.repository.ts b/server/src/infra/repositories/crypto.repository.ts index f7bf63f2c..121943af3 100644 --- a/server/src/infra/repositories/crypto.repository.ts +++ b/server/src/infra/repositories/crypto.repository.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { compareSync, hash } from 'bcrypt'; import { createHash, randomBytes, randomUUID } from 'node:crypto'; import { createReadStream } from 'node:fs'; -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; import { Instrumentation } from 'src/infra/instrumentation'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/database.repository.ts b/server/src/infra/repositories/database.repository.ts index 8720ad8d7..60586edc5 100644 --- a/server/src/infra/repositories/database.repository.ts +++ b/server/src/infra/repositories/database.repository.ts @@ -2,6 +2,9 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource } from '@nestjs/typeorm'; import AsyncLock from 'async-lock'; import { Version, VersionType } from 'src/domain/domain.constant'; +import { vectorExt } from 'src/infra/database.config'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; import { DatabaseExtension, DatabaseLock, @@ -10,10 +13,7 @@ import { VectorIndex, VectorUpdateResult, extName, -} from 'src/domain/repositories/database.repository'; -import { vectorExt } from 'src/infra/database.config'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; +} from 'src/interfaces/database.repository'; import { isValidInteger } from 'src/validation'; import { DataSource, EntityManager, QueryRunner } from 'typeorm'; diff --git a/server/src/infra/repositories/filesystem.provider.ts b/server/src/infra/repositories/filesystem.provider.ts index c88b0c83a..2da49625e 100644 --- a/server/src/infra/repositories/filesystem.provider.ts +++ b/server/src/infra/repositories/filesystem.provider.ts @@ -6,6 +6,8 @@ import fs from 'node:fs/promises'; import path from 'node:path'; import { mimeTypes } from 'src/domain/domain.constant'; import { CrawlOptionsDto } from 'src/domain/library/library.dto'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; import { DiskUsage, IStorageRepository, @@ -13,9 +15,7 @@ import { ImmichZipStream, StorageEventType, WatchEvents, -} from 'src/domain/repositories/storage.repository'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; +} from 'src/interfaces/storage.repository'; @Instrumentation() export class FilesystemProvider implements IStorageRepository { diff --git a/server/src/infra/repositories/job.repository.ts b/server/src/infra/repositories/job.repository.ts index 856c7fae0..a7637e0e6 100644 --- a/server/src/infra/repositories/job.repository.ts +++ b/server/src/infra/repositories/job.repository.ts @@ -7,15 +7,9 @@ import { CronJob, CronTime } from 'cron'; import { setTimeout } from 'node:timers/promises'; import { bullConfig } from 'src/config'; import { JOBS_TO_QUEUE, JobName, QueueName } from 'src/domain/job/job.constants'; -import { - IJobRepository, - JobCounts, - JobItem, - QueueCleanType, - QueueStatus, -} from 'src/domain/repositories/job.repository'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; +import { IJobRepository, JobCounts, JobItem, QueueCleanType, QueueStatus } from 'src/interfaces/job.repository'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/library.repository.ts b/server/src/infra/repositories/library.repository.ts index f9045b9c8..ae6a1e343 100644 --- a/server/src/infra/repositories/library.repository.ts +++ b/server/src/infra/repositories/library.repository.ts @@ -2,9 +2,9 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { LibraryStatsResponseDto } from 'src/domain/library/library.dto'; -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IsNull, Not } from 'typeorm'; import { Repository } from 'typeorm/repository/Repository.js'; diff --git a/server/src/infra/repositories/machine-learning.repository.ts b/server/src/infra/repositories/machine-learning.repository.ts index edf067905..46d16dcd7 100644 --- a/server/src/infra/repositories/machine-learning.repository.ts +++ b/server/src/infra/repositories/machine-learning.repository.ts @@ -1,5 +1,7 @@ import { Injectable } from '@nestjs/common'; import { readFile } from 'node:fs/promises'; +import { CLIPConfig, ModelConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; +import { Instrumentation } from 'src/infra/instrumentation'; import { CLIPMode, DetectFaceResult, @@ -7,9 +9,7 @@ import { ModelType, TextModelInput, VisionModelInput, -} from 'src/domain/repositories/machine-learning.repository'; -import { CLIPConfig, ModelConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; -import { Instrumentation } from 'src/infra/instrumentation'; +} from 'src/interfaces/machine-learning.repository'; const errorPrefix = 'Machine learning request'; diff --git a/server/src/infra/repositories/media.repository.ts b/server/src/infra/repositories/media.repository.ts index f2d59ea95..8c143d049 100644 --- a/server/src/infra/repositories/media.repository.ts +++ b/server/src/infra/repositories/media.repository.ts @@ -3,16 +3,16 @@ import fs from 'node:fs/promises'; import { Writable } from 'node:stream'; import { promisify } from 'node:util'; import sharp from 'sharp'; +import { Colorspace } from 'src/infra/entities/system-config.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; import { CropOptions, IMediaRepository, ResizeOptions, TranscodeOptions, VideoInfo, -} from 'src/domain/repositories/media.repository'; -import { Colorspace } from 'src/infra/entities/system-config.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; +} from 'src/interfaces/media.repository'; import { handlePromiseError } from 'src/utils'; const probe = promisify(ffmpeg.ffprobe); diff --git a/server/src/infra/repositories/metadata.repository.ts b/server/src/infra/repositories/metadata.repository.ts index 365a3543f..a5e82535c 100644 --- a/server/src/infra/repositories/metadata.repository.ts +++ b/server/src/infra/repositories/metadata.repository.ts @@ -14,18 +14,13 @@ import { geodataCities500Path, geodataDatePath, } from 'src/domain/domain.constant'; -import { - GeoPoint, - IMetadataRepository, - ImmichTags, - ReverseGeocodeResult, -} from 'src/domain/repositories/metadata.repository'; -import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; import { ExifEntity } from 'src/infra/entities/exif.entity'; import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; +import { GeoPoint, IMetadataRepository, ImmichTags, ReverseGeocodeResult } from 'src/interfaces/metadata.repository'; +import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; import { DataSource, QueryRunner, Repository } from 'typeorm'; import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; diff --git a/server/src/infra/repositories/move.repository.ts b/server/src/infra/repositories/move.repository.ts index 8482fc228..7f7595125 100644 --- a/server/src/infra/repositories/move.repository.ts +++ b/server/src/infra/repositories/move.repository.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { IMoveRepository, MoveCreate } from 'src/domain/repositories/move.repository'; import { MoveEntity, PathType } from 'src/infra/entities/move.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { IMoveRepository, MoveCreate } from 'src/interfaces/move.repository'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/partner.repository.ts b/server/src/infra/repositories/partner.repository.ts index cd39a8f9d..f8b9866ca 100644 --- a/server/src/infra/repositories/partner.repository.ts +++ b/server/src/infra/repositories/partner.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { IPartnerRepository, PartnerIds } from 'src/domain/repositories/partner.repository'; import { PartnerEntity } from 'src/infra/entities/partner.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { IPartnerRepository, PartnerIds } from 'src/interfaces/partner.repository'; import { DeepPartial, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/person.repository.ts b/server/src/infra/repositories/person.repository.ts index e0d707ca1..5096032da 100644 --- a/server/src/infra/repositories/person.repository.ts +++ b/server/src/infra/repositories/person.repository.ts @@ -1,6 +1,11 @@ import { InjectRepository } from '@nestjs/typeorm'; import _ from 'lodash'; import { ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; +import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { PersonEntity } from 'src/infra/entities/person.entity'; +import { asVector, paginate } from 'src/infra/infra.utils'; +import { Instrumentation } from 'src/infra/instrumentation'; import { AssetFaceId, IPersonRepository, @@ -9,12 +14,7 @@ import { PersonSearchOptions, PersonStatistics, UpdateFacesData, -} from 'src/domain/repositories/person.repository'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; -import { asVector, paginate } from 'src/infra/infra.utils'; -import { Instrumentation } from 'src/infra/instrumentation'; +} from 'src/interfaces/person.repository'; import { Paginated, PaginationOptions } from 'src/utils'; import { FindManyOptions, FindOptionsRelations, FindOptionsSelect, In, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/search.repository.ts b/server/src/infra/repositories/search.repository.ts index 6ba546ea9..83bbef667 100644 --- a/server/src/infra/repositories/search.repository.ts +++ b/server/src/infra/repositories/search.repository.ts @@ -1,16 +1,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { DatabaseExtension } from 'src/domain/repositories/database.repository'; -import { - AssetSearchOptions, - Embedding, - FaceEmbeddingSearch, - FaceSearchResult, - ISearchRepository, - SearchPaginationOptions, - SmartSearchOptions, -} from 'src/domain/repositories/search.repository'; import { getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; import { vectorExt } from 'src/infra/database.config'; import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; @@ -21,6 +11,16 @@ import { SmartSearchEntity } from 'src/infra/entities/smart-search.entity'; import { asVector, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; +import { DatabaseExtension } from 'src/interfaces/database.repository'; +import { + AssetSearchOptions, + Embedding, + FaceEmbeddingSearch, + FaceSearchResult, + ISearchRepository, + SearchPaginationOptions, + SmartSearchOptions, +} from 'src/interfaces/search.repository'; import { Paginated, PaginationMode, PaginationResult } from 'src/utils'; import { isValidInteger } from 'src/validation'; import { Repository, SelectQueryBuilder } from 'typeorm'; diff --git a/server/src/infra/repositories/server-info.repository.ts b/server/src/infra/repositories/server-info.repository.ts index 50ee3bc8d..fcef0a396 100644 --- a/server/src/infra/repositories/server-info.repository.ts +++ b/server/src/infra/repositories/server-info.repository.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { GitHubRelease, IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; import { Instrumentation } from 'src/infra/instrumentation'; +import { GitHubRelease, IServerInfoRepository } from 'src/interfaces/server-info.repository'; @Instrumentation() @Injectable() diff --git a/server/src/infra/repositories/shared-link.repository.ts b/server/src/infra/repositories/shared-link.repository.ts index e2878acf4..93aacf1f2 100644 --- a/server/src/infra/repositories/shared-link.repository.ts +++ b/server/src/infra/repositories/shared-link.repository.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/system-config.repository.ts b/server/src/infra/repositories/system-config.repository.ts index 555a3c254..ba3ee0aa0 100644 --- a/server/src/infra/repositories/system-config.repository.ts +++ b/server/src/infra/repositories/system-config.repository.ts @@ -1,9 +1,9 @@ import { InjectRepository } from '@nestjs/typeorm'; import { readFile } from 'node:fs/promises'; import { Chunked, DummyValue, GenerateSql } from 'src/decorators'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { SystemConfigEntity } from 'src/infra/entities/system-config.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { In, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/system-metadata.repository.ts b/server/src/infra/repositories/system-metadata.repository.ts index b0ace1b91..12c72c090 100644 --- a/server/src/infra/repositories/system-metadata.repository.ts +++ b/server/src/infra/repositories/system-metadata.repository.ts @@ -1,7 +1,7 @@ import { InjectRepository } from '@nestjs/typeorm'; -import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; import { SystemMetadata, SystemMetadataEntity } from 'src/infra/entities/system-metadata.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/tag.repository.ts b/server/src/infra/repositories/tag.repository.ts index 3de70aa10..c44b0763a 100644 --- a/server/src/infra/repositories/tag.repository.ts +++ b/server/src/infra/repositories/tag.repository.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { ITagRepository } from 'src/domain/repositories/tag.repository'; import { AssetEntity } from 'src/infra/entities/asset.entity'; import { TagEntity } from 'src/infra/entities/tag.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { ITagRepository } from 'src/interfaces/tag.repository'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/user-token.repository.ts b/server/src/infra/repositories/user-token.repository.ts index 7d16bd0cf..19dcafc1e 100644 --- a/server/src/infra/repositories/user-token.repository.ts +++ b/server/src/infra/repositories/user-token.repository.ts @@ -1,9 +1,9 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; import { Instrumentation } from 'src/infra/instrumentation'; +import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/repositories/user.repository.ts b/server/src/infra/repositories/user.repository.ts index 27692dd66..743293766 100644 --- a/server/src/infra/repositories/user.repository.ts +++ b/server/src/infra/repositories/user.repository.ts @@ -1,15 +1,15 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; +import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { UserEntity } from 'src/infra/entities/user.entity'; +import { Instrumentation } from 'src/infra/instrumentation'; import { IUserRepository, UserFindOptions, UserListFilter, UserStatsQueryResponse, -} from 'src/domain/repositories/user.repository'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; +} from 'src/interfaces/user.repository'; import { IsNull, Not, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/infra/sql-generator/index.ts b/server/src/infra/sql-generator/index.ts index 0821d53cd..a117568d8 100644 --- a/server/src/infra/sql-generator/index.ts +++ b/server/src/infra/sql-generator/index.ts @@ -6,7 +6,6 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { mkdir, rm, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; import { databaseConfig } from 'src/infra/database.config'; import { databaseEntities } from 'src/infra/entities'; import { AccessRepository } from 'src/infra/repositories/access.repository'; @@ -26,6 +25,7 @@ import { TagRepository } from 'src/infra/repositories/tag.repository'; import { UserTokenRepository } from 'src/infra/repositories/user-token.repository'; import { UserRepository } from 'src/infra/repositories/user.repository'; import { SqlLogger } from 'src/infra/sql-generator/sql.logger'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; const reflector = new Reflector(); const repositories = [ diff --git a/server/src/domain/repositories/access.repository.ts b/server/src/interfaces/access.repository.ts similarity index 100% rename from server/src/domain/repositories/access.repository.ts rename to server/src/interfaces/access.repository.ts diff --git a/server/src/domain/repositories/activity.repository.ts b/server/src/interfaces/activity.repository.ts similarity index 100% rename from server/src/domain/repositories/activity.repository.ts rename to server/src/interfaces/activity.repository.ts diff --git a/server/src/domain/repositories/album.repository.ts b/server/src/interfaces/album.repository.ts similarity index 100% rename from server/src/domain/repositories/album.repository.ts rename to server/src/interfaces/album.repository.ts diff --git a/server/src/domain/repositories/api-key.repository.ts b/server/src/interfaces/api-key.repository.ts similarity index 100% rename from server/src/domain/repositories/api-key.repository.ts rename to server/src/interfaces/api-key.repository.ts diff --git a/server/src/domain/repositories/asset-stack.repository.ts b/server/src/interfaces/asset-stack.repository.ts similarity index 100% rename from server/src/domain/repositories/asset-stack.repository.ts rename to server/src/interfaces/asset-stack.repository.ts diff --git a/server/src/domain/repositories/asset.repository.ts b/server/src/interfaces/asset.repository.ts similarity index 96% rename from server/src/domain/repositories/asset.repository.ts rename to server/src/interfaces/asset.repository.ts index 336db8d70..a362d2349 100644 --- a/server/src/domain/repositories/asset.repository.ts +++ b/server/src/interfaces/asset.repository.ts @@ -1,9 +1,9 @@ -import { ReverseGeocodeResult } from 'src/domain/repositories/metadata.repository'; -import { AssetSearchOptions, SearchExploreItem } from 'src/domain/repositories/search.repository'; import { AssetOrder } from 'src/infra/entities/album.entity'; import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { ReverseGeocodeResult } from 'src/interfaces/metadata.repository'; +import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.repository'; import { Paginated, PaginationOptions } from 'src/utils'; import { FindOptionsRelations, FindOptionsSelect } from 'typeorm'; diff --git a/server/src/domain/repositories/audit.repository.ts b/server/src/interfaces/audit.repository.ts similarity index 100% rename from server/src/domain/repositories/audit.repository.ts rename to server/src/interfaces/audit.repository.ts diff --git a/server/src/domain/repositories/communication.repository.ts b/server/src/interfaces/communication.repository.ts similarity index 100% rename from server/src/domain/repositories/communication.repository.ts rename to server/src/interfaces/communication.repository.ts diff --git a/server/src/domain/repositories/crypto.repository.ts b/server/src/interfaces/crypto.repository.ts similarity index 100% rename from server/src/domain/repositories/crypto.repository.ts rename to server/src/interfaces/crypto.repository.ts diff --git a/server/src/domain/repositories/database.repository.ts b/server/src/interfaces/database.repository.ts similarity index 100% rename from server/src/domain/repositories/database.repository.ts rename to server/src/interfaces/database.repository.ts diff --git a/server/src/domain/repositories/job.repository.ts b/server/src/interfaces/job.repository.ts similarity index 100% rename from server/src/domain/repositories/job.repository.ts rename to server/src/interfaces/job.repository.ts diff --git a/server/src/domain/repositories/library.repository.ts b/server/src/interfaces/library.repository.ts similarity index 100% rename from server/src/domain/repositories/library.repository.ts rename to server/src/interfaces/library.repository.ts diff --git a/server/src/domain/repositories/machine-learning.repository.ts b/server/src/interfaces/machine-learning.repository.ts similarity index 100% rename from server/src/domain/repositories/machine-learning.repository.ts rename to server/src/interfaces/machine-learning.repository.ts diff --git a/server/src/domain/repositories/media.repository.ts b/server/src/interfaces/media.repository.ts similarity index 100% rename from server/src/domain/repositories/media.repository.ts rename to server/src/interfaces/media.repository.ts diff --git a/server/src/domain/repositories/metadata.repository.ts b/server/src/interfaces/metadata.repository.ts similarity index 100% rename from server/src/domain/repositories/metadata.repository.ts rename to server/src/interfaces/metadata.repository.ts diff --git a/server/src/domain/repositories/move.repository.ts b/server/src/interfaces/move.repository.ts similarity index 100% rename from server/src/domain/repositories/move.repository.ts rename to server/src/interfaces/move.repository.ts diff --git a/server/src/domain/repositories/partner.repository.ts b/server/src/interfaces/partner.repository.ts similarity index 100% rename from server/src/domain/repositories/partner.repository.ts rename to server/src/interfaces/partner.repository.ts diff --git a/server/src/domain/repositories/person.repository.ts b/server/src/interfaces/person.repository.ts similarity index 100% rename from server/src/domain/repositories/person.repository.ts rename to server/src/interfaces/person.repository.ts diff --git a/server/src/domain/repositories/search.repository.ts b/server/src/interfaces/search.repository.ts similarity index 100% rename from server/src/domain/repositories/search.repository.ts rename to server/src/interfaces/search.repository.ts diff --git a/server/src/domain/repositories/server-info.repository.ts b/server/src/interfaces/server-info.repository.ts similarity index 100% rename from server/src/domain/repositories/server-info.repository.ts rename to server/src/interfaces/server-info.repository.ts diff --git a/server/src/domain/repositories/shared-link.repository.ts b/server/src/interfaces/shared-link.repository.ts similarity index 100% rename from server/src/domain/repositories/shared-link.repository.ts rename to server/src/interfaces/shared-link.repository.ts diff --git a/server/src/domain/repositories/storage.repository.ts b/server/src/interfaces/storage.repository.ts similarity index 100% rename from server/src/domain/repositories/storage.repository.ts rename to server/src/interfaces/storage.repository.ts diff --git a/server/src/domain/repositories/system-config.repository.ts b/server/src/interfaces/system-config.repository.ts similarity index 100% rename from server/src/domain/repositories/system-config.repository.ts rename to server/src/interfaces/system-config.repository.ts diff --git a/server/src/domain/repositories/system-metadata.repository.ts b/server/src/interfaces/system-metadata.repository.ts similarity index 100% rename from server/src/domain/repositories/system-metadata.repository.ts rename to server/src/interfaces/system-metadata.repository.ts diff --git a/server/src/domain/repositories/tag.repository.ts b/server/src/interfaces/tag.repository.ts similarity index 100% rename from server/src/domain/repositories/tag.repository.ts rename to server/src/interfaces/tag.repository.ts diff --git a/server/src/domain/repositories/user-token.repository.ts b/server/src/interfaces/user-token.repository.ts similarity index 100% rename from server/src/domain/repositories/user-token.repository.ts rename to server/src/interfaces/user-token.repository.ts diff --git a/server/src/domain/repositories/user.repository.ts b/server/src/interfaces/user.repository.ts similarity index 100% rename from server/src/domain/repositories/user.repository.ts rename to server/src/interfaces/user.repository.ts diff --git a/server/src/test-utils/utils.ts b/server/src/test-utils/utils.ts index 5b4f17baf..b9e74f767 100644 --- a/server/src/test-utils/utils.ts +++ b/server/src/test-utils/utils.ts @@ -7,14 +7,14 @@ import { join } from 'node:path'; import { EventEmitter } from 'node:stream'; import { Server } from 'node:tls'; import { QueueName } from 'src/domain/job/job.constants'; -import { IJobRepository, JobItem, JobItemHandler } from 'src/domain/repositories/job.repository'; -import { IMediaRepository } from 'src/domain/repositories/media.repository'; -import { StorageEventType } from 'src/domain/repositories/storage.repository'; import { AppModule } from 'src/immich/app.module'; import { AppService } from 'src/immich/app.service'; import { dataSource } from 'src/infra/database.config'; import { InfraModule, InfraTestModule } from 'src/infra/infra.module'; import { MediaRepository } from 'src/infra/repositories/media.repository'; +import { IJobRepository, JobItem, JobItemHandler } from 'src/interfaces/job.repository'; +import { IMediaRepository } from 'src/interfaces/media.repository'; +import { StorageEventType } from 'src/interfaces/storage.repository'; import { AppService as MicroAppService } from 'src/microservices/app.service'; import { EntityTarget, ObjectLiteral } from 'typeorm'; diff --git a/server/test/fixtures/media.stub.ts b/server/test/fixtures/media.stub.ts index b4c74b34d..1be792c25 100644 --- a/server/test/fixtures/media.stub.ts +++ b/server/test/fixtures/media.stub.ts @@ -1,4 +1,4 @@ -import { AudioStreamInfo, VideoFormat, VideoInfo, VideoStreamInfo } from 'src/domain/repositories/media.repository'; +import { AudioStreamInfo, VideoFormat, VideoInfo, VideoStreamInfo } from 'src/interfaces/media.repository'; const probeStubDefaultFormat: VideoFormat = { formatName: 'mov,mp4,m4a,3gp,3g2,mj2', diff --git a/server/test/repositories/access.repository.mock.ts b/server/test/repositories/access.repository.mock.ts index 686d9bc85..8d2233cf6 100644 --- a/server/test/repositories/access.repository.mock.ts +++ b/server/test/repositories/access.repository.mock.ts @@ -1,5 +1,5 @@ import { AccessCore } from 'src/cores/access.core'; -import { IAccessRepository } from 'src/domain/repositories/access.repository'; +import { IAccessRepository } from 'src/interfaces/access.repository'; export interface IAccessRepositoryMock { activity: jest.Mocked; diff --git a/server/test/repositories/activity.repository.mock.ts b/server/test/repositories/activity.repository.mock.ts index 166690b5f..84cf7e124 100644 --- a/server/test/repositories/activity.repository.mock.ts +++ b/server/test/repositories/activity.repository.mock.ts @@ -1,4 +1,4 @@ -import { IActivityRepository } from 'src/domain/repositories/activity.repository'; +import { IActivityRepository } from 'src/interfaces/activity.repository'; export const newActivityRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/album.repository.mock.ts b/server/test/repositories/album.repository.mock.ts index 8259ac456..b50fe6750 100644 --- a/server/test/repositories/album.repository.mock.ts +++ b/server/test/repositories/album.repository.mock.ts @@ -1,4 +1,4 @@ -import { IAlbumRepository } from 'src/domain/repositories/album.repository'; +import { IAlbumRepository } from 'src/interfaces/album.repository'; export const newAlbumRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/api-key.repository.mock.ts b/server/test/repositories/api-key.repository.mock.ts index 471b4bb94..d74a41028 100644 --- a/server/test/repositories/api-key.repository.mock.ts +++ b/server/test/repositories/api-key.repository.mock.ts @@ -1,4 +1,4 @@ -import { IKeyRepository } from 'src/domain/repositories/api-key.repository'; +import { IKeyRepository } from 'src/interfaces/api-key.repository'; export const newKeyRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/asset-stack.repository.mock.ts b/server/test/repositories/asset-stack.repository.mock.ts index cb935a17e..cf38d045f 100644 --- a/server/test/repositories/asset-stack.repository.mock.ts +++ b/server/test/repositories/asset-stack.repository.mock.ts @@ -1,4 +1,4 @@ -import { IAssetStackRepository } from 'src/domain/repositories/asset-stack.repository'; +import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; export const newAssetStackRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/asset.repository.mock.ts b/server/test/repositories/asset.repository.mock.ts index ab933e785..c72d00414 100644 --- a/server/test/repositories/asset.repository.mock.ts +++ b/server/test/repositories/asset.repository.mock.ts @@ -1,4 +1,4 @@ -import { IAssetRepository } from 'src/domain/repositories/asset.repository'; +import { IAssetRepository } from 'src/interfaces/asset.repository'; export const newAssetRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/audit.repository.mock.ts b/server/test/repositories/audit.repository.mock.ts index 87a83787b..654f67794 100644 --- a/server/test/repositories/audit.repository.mock.ts +++ b/server/test/repositories/audit.repository.mock.ts @@ -1,4 +1,4 @@ -import { IAuditRepository } from 'src/domain/repositories/audit.repository'; +import { IAuditRepository } from 'src/interfaces/audit.repository'; export const newAuditRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/communication.repository.mock.ts b/server/test/repositories/communication.repository.mock.ts index 8ba1e370c..3d4eaeb37 100644 --- a/server/test/repositories/communication.repository.mock.ts +++ b/server/test/repositories/communication.repository.mock.ts @@ -1,4 +1,4 @@ -import { ICommunicationRepository } from 'src/domain/repositories/communication.repository'; +import { ICommunicationRepository } from 'src/interfaces/communication.repository'; export const newCommunicationRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/crypto.repository.mock.ts b/server/test/repositories/crypto.repository.mock.ts index 015593a88..6cf4adffd 100644 --- a/server/test/repositories/crypto.repository.mock.ts +++ b/server/test/repositories/crypto.repository.mock.ts @@ -1,4 +1,4 @@ -import { ICryptoRepository } from 'src/domain/repositories/crypto.repository'; +import { ICryptoRepository } from 'src/interfaces/crypto.repository'; export const newCryptoRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/database.repository.mock.ts b/server/test/repositories/database.repository.mock.ts index 5cf2960d2..82abe16a8 100644 --- a/server/test/repositories/database.repository.mock.ts +++ b/server/test/repositories/database.repository.mock.ts @@ -1,5 +1,5 @@ import { Version } from 'src/domain/domain.constant'; -import { IDatabaseRepository } from 'src/domain/repositories/database.repository'; +import { IDatabaseRepository } from 'src/interfaces/database.repository'; export const newDatabaseRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/job.repository.mock.ts b/server/test/repositories/job.repository.mock.ts index 216287343..851da70da 100644 --- a/server/test/repositories/job.repository.mock.ts +++ b/server/test/repositories/job.repository.mock.ts @@ -1,4 +1,4 @@ -import { IJobRepository } from 'src/domain/repositories/job.repository'; +import { IJobRepository } from 'src/interfaces/job.repository'; export const newJobRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/library.repository.mock.ts b/server/test/repositories/library.repository.mock.ts index 79d95cbb5..b3c62d681 100644 --- a/server/test/repositories/library.repository.mock.ts +++ b/server/test/repositories/library.repository.mock.ts @@ -1,4 +1,4 @@ -import { ILibraryRepository } from 'src/domain/repositories/library.repository'; +import { ILibraryRepository } from 'src/interfaces/library.repository'; export const newLibraryRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/machine-learning.repository.mock.ts b/server/test/repositories/machine-learning.repository.mock.ts index 2266dedae..50da10cb4 100644 --- a/server/test/repositories/machine-learning.repository.mock.ts +++ b/server/test/repositories/machine-learning.repository.mock.ts @@ -1,4 +1,4 @@ -import { IMachineLearningRepository } from 'src/domain/repositories/machine-learning.repository'; +import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; export const newMachineLearningRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/media.repository.mock.ts b/server/test/repositories/media.repository.mock.ts index 8b21aad10..d1806c636 100644 --- a/server/test/repositories/media.repository.mock.ts +++ b/server/test/repositories/media.repository.mock.ts @@ -1,4 +1,4 @@ -import { IMediaRepository } from 'src/domain/repositories/media.repository'; +import { IMediaRepository } from 'src/interfaces/media.repository'; export const newMediaRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/metadata.repository.mock.ts b/server/test/repositories/metadata.repository.mock.ts index ff2bb53fb..a5f13daf5 100644 --- a/server/test/repositories/metadata.repository.mock.ts +++ b/server/test/repositories/metadata.repository.mock.ts @@ -1,4 +1,4 @@ -import { IMetadataRepository } from 'src/domain/repositories/metadata.repository'; +import { IMetadataRepository } from 'src/interfaces/metadata.repository'; export const newMetadataRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/move.repository.mock.ts b/server/test/repositories/move.repository.mock.ts index b42dc8610..265799ab6 100644 --- a/server/test/repositories/move.repository.mock.ts +++ b/server/test/repositories/move.repository.mock.ts @@ -1,4 +1,4 @@ -import { IMoveRepository } from 'src/domain/repositories/move.repository'; +import { IMoveRepository } from 'src/interfaces/move.repository'; export const newMoveRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/partner.repository.mock.ts b/server/test/repositories/partner.repository.mock.ts index c70147139..74c42ba8d 100644 --- a/server/test/repositories/partner.repository.mock.ts +++ b/server/test/repositories/partner.repository.mock.ts @@ -1,4 +1,4 @@ -import { IPartnerRepository } from 'src/domain/repositories/partner.repository'; +import { IPartnerRepository } from 'src/interfaces/partner.repository'; export const newPartnerRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/person.repository.mock.ts b/server/test/repositories/person.repository.mock.ts index c370241b7..b4b817535 100644 --- a/server/test/repositories/person.repository.mock.ts +++ b/server/test/repositories/person.repository.mock.ts @@ -1,4 +1,4 @@ -import { IPersonRepository } from 'src/domain/repositories/person.repository'; +import { IPersonRepository } from 'src/interfaces/person.repository'; export const newPersonRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/search.repository.mock.ts b/server/test/repositories/search.repository.mock.ts index e86b83350..eb6c13ea4 100644 --- a/server/test/repositories/search.repository.mock.ts +++ b/server/test/repositories/search.repository.mock.ts @@ -1,4 +1,4 @@ -import { ISearchRepository } from 'src/domain/repositories/search.repository'; +import { ISearchRepository } from 'src/interfaces/search.repository'; export const newSearchRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/shared-link.repository.mock.ts b/server/test/repositories/shared-link.repository.mock.ts index 2cdf0e2b2..ea084c1ed 100644 --- a/server/test/repositories/shared-link.repository.mock.ts +++ b/server/test/repositories/shared-link.repository.mock.ts @@ -1,4 +1,4 @@ -import { ISharedLinkRepository } from 'src/domain/repositories/shared-link.repository'; +import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; export const newSharedLinkRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/storage.repository.mock.ts b/server/test/repositories/storage.repository.mock.ts index 071b733a8..72b87aed1 100644 --- a/server/test/repositories/storage.repository.mock.ts +++ b/server/test/repositories/storage.repository.mock.ts @@ -1,6 +1,6 @@ import { WatchOptions } from 'chokidar'; import { StorageCore } from 'src/cores/storage.core'; -import { IStorageRepository, StorageEventType, WatchEvents } from 'src/domain/repositories/storage.repository'; +import { IStorageRepository, StorageEventType, WatchEvents } from 'src/interfaces/storage.repository'; interface MockWatcherOptions { items?: Array<{ event: 'change' | 'add' | 'unlink' | 'error'; value: string }>; diff --git a/server/test/repositories/system-config.repository.mock.ts b/server/test/repositories/system-config.repository.mock.ts index 537182b2e..89ce6a050 100644 --- a/server/test/repositories/system-config.repository.mock.ts +++ b/server/test/repositories/system-config.repository.mock.ts @@ -1,5 +1,5 @@ import { SystemConfigCore } from 'src/cores/system-config.core'; -import { ISystemConfigRepository } from 'src/domain/repositories/system-config.repository'; +import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; export const newSystemConfigRepositoryMock = (reset = true): jest.Mocked => { if (reset) { diff --git a/server/test/repositories/system-info.repository.mock.ts b/server/test/repositories/system-info.repository.mock.ts index a392818ed..93ec9c7dd 100644 --- a/server/test/repositories/system-info.repository.mock.ts +++ b/server/test/repositories/system-info.repository.mock.ts @@ -1,4 +1,4 @@ -import { IServerInfoRepository } from 'src/domain/repositories/server-info.repository'; +import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; export const newServerInfoRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/system-metadata.repository.mock.ts b/server/test/repositories/system-metadata.repository.mock.ts index f031740a4..f93278aaa 100644 --- a/server/test/repositories/system-metadata.repository.mock.ts +++ b/server/test/repositories/system-metadata.repository.mock.ts @@ -1,4 +1,4 @@ -import { ISystemMetadataRepository } from 'src/domain/repositories/system-metadata.repository'; +import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; export const newSystemMetadataRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/tag.repository.mock.ts b/server/test/repositories/tag.repository.mock.ts index 611e773ef..9f5283664 100644 --- a/server/test/repositories/tag.repository.mock.ts +++ b/server/test/repositories/tag.repository.mock.ts @@ -1,4 +1,4 @@ -import { ITagRepository } from 'src/domain/repositories/tag.repository'; +import { ITagRepository } from 'src/interfaces/tag.repository'; export const newTagRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/user-token.repository.mock.ts b/server/test/repositories/user-token.repository.mock.ts index c11cc5ed9..23de88d35 100644 --- a/server/test/repositories/user-token.repository.mock.ts +++ b/server/test/repositories/user-token.repository.mock.ts @@ -1,4 +1,4 @@ -import { IUserTokenRepository } from 'src/domain/repositories/user-token.repository'; +import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; export const newUserTokenRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/repositories/user.repository.mock.ts b/server/test/repositories/user.repository.mock.ts index 57e014830..4db0b16af 100644 --- a/server/test/repositories/user.repository.mock.ts +++ b/server/test/repositories/user.repository.mock.ts @@ -1,5 +1,5 @@ import { UserCore } from 'src/cores/user.core'; -import { IUserRepository } from 'src/domain/repositories/user.repository'; +import { IUserRepository } from 'src/interfaces/user.repository'; export const newUserRepositoryMock = (reset = true): jest.Mocked => { if (reset) { From c1402eee8e0020994c488c22b175fd693e40be3d Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 20 Mar 2024 16:02:51 -0500 Subject: [PATCH 038/152] chore: migrate database files (#8126) --- .github/workflows/test.yml | 4 +- docs/docs/developer/database-migrations.md | 4 +- server/e2e/jobs/jest-e2e.json | 6 +- .../jobs/specs/library-watcher.e2e-spec.ts | 4 +- server/e2e/jobs/specs/library.e2e-spec.ts | 2 +- server/package.json | 2 + server/src/commands/list-users.command.ts | 2 +- server/src/config.ts | 2 +- server/src/cores/access.core.ts | 2 +- server/src/cores/storage.core.ts | 6 +- server/src/cores/system-config.core.ts | 2 +- server/src/cores/user.core.ts | 4 +- server/src/domain/activity/activity.dto.ts | 2 +- .../src/domain/activity/activity.service.ts | 2 +- server/src/domain/album/album-response.dto.ts | 2 +- server/src/domain/album/album.service.ts | 6 +- .../src/domain/album/dto/album-update.dto.ts | 2 +- server/src/domain/api-key/api-key.service.ts | 2 +- server/src/domain/asset/asset.service.spec.ts | 2 +- server/src/domain/asset/asset.service.ts | 4 +- .../domain/asset/dto/asset-statistics.dto.ts | 2 +- .../src/domain/asset/dto/time-bucket.dto.ts | 2 +- .../asset/response-dto/asset-response.dto.ts | 4 +- .../asset/response-dto/exif-response.dto.ts | 2 +- .../response-dto/smart-info-response.dto.ts | 2 +- server/src/domain/audit/audit.dto.ts | 4 +- server/src/domain/audit/audit.service.spec.ts | 2 +- server/src/domain/audit/audit.service.ts | 4 +- server/src/domain/auth/auth.dto.ts | 8 +-- server/src/domain/auth/auth.service.spec.ts | 2 +- server/src/domain/auth/auth.service.ts | 4 +- server/src/domain/domain.constant.ts | 2 +- .../src/domain/download/download.service.ts | 2 +- server/src/domain/job/job.service.spec.ts | 2 +- server/src/domain/job/job.service.ts | 2 +- server/src/domain/library/library.dto.ts | 2 +- .../domain/library/library.service.spec.ts | 8 +-- server/src/domain/library/library.service.ts | 4 +- server/src/domain/media/media.service.spec.ts | 6 +- server/src/domain/media/media.service.ts | 6 +- server/src/domain/media/media.util.ts | 8 +-- .../domain/metadata/metadata.service.spec.ts | 6 +- .../src/domain/metadata/metadata.service.ts | 4 +- .../domain/partner/partner.service.spec.ts | 2 +- server/src/domain/partner/partner.service.ts | 2 +- server/src/domain/person/person.dto.ts | 4 +- .../src/domain/person/person.service.spec.ts | 4 +- server/src/domain/person/person.service.ts | 4 +- server/src/domain/search/dto/search.dto.ts | 6 +- .../src/domain/search/search.service.spec.ts | 2 +- server/src/domain/search/search.service.ts | 4 +- .../server-info/server-info.service.spec.ts | 2 +- .../domain/server-info/server-info.service.ts | 2 +- .../shared-link/shared-link-response.dto.ts | 2 +- .../src/domain/shared-link/shared-link.dto.ts | 2 +- .../shared-link/shared-link.service.spec.ts | 2 +- .../domain/shared-link/shared-link.service.ts | 4 +- .../smart-info/smart-info.service.spec.ts | 4 +- .../storage-template.service.spec.ts | 4 +- .../storage-template.service.ts | 6 +- .../dto/system-config-ffmpeg.dto.ts | 2 +- .../dto/system-config-logging.dto.ts | 2 +- .../dto/system-config-thumbnail.dto.ts | 2 +- .../system-config/dto/system-config.dto.ts | 2 +- .../system-config.service.spec.ts | 2 +- .../system-config/system-config.service.ts | 2 +- server/src/domain/tag/tag-response.dto.ts | 2 +- server/src/domain/tag/tag.dto.ts | 2 +- server/src/domain/tag/tag.service.spec.ts | 2 +- server/src/domain/user/dto/update-user.dto.ts | 2 +- .../user/response-dto/user-response.dto.ts | 2 +- server/src/domain/user/user.service.spec.ts | 2 +- server/src/domain/user/user.service.ts | 2 +- .../{infra => }/entities/activity.entity.ts | 6 +- .../src/{infra => }/entities/album.entity.ts | 6 +- .../{infra => }/entities/api-key.entity.ts | 2 +- .../{infra => }/entities/asset-face.entity.ts | 4 +- .../entities/asset-job-status.entity.ts | 2 +- .../entities/asset-stack.entity.ts | 2 +- .../src/{infra => }/entities/asset.entity.ts | 22 ++++---- .../src/{infra => }/entities/audit.entity.ts | 0 .../src/{infra => }/entities/exif.entity.ts | 2 +- .../entities/geodata-places.entity.ts | 0 server/src/entities/index.ts | 47 ++++++++++++++++ .../{infra => }/entities/library.entity.ts | 4 +- .../src/{infra => }/entities/move.entity.ts | 0 .../{infra => }/entities/partner.entity.ts | 2 +- .../src/{infra => }/entities/person.entity.ts | 4 +- .../entities/shared-link.entity.ts | 6 +- .../{infra => }/entities/smart-info.entity.ts | 2 +- .../entities/smart-search.entity.ts | 2 +- .../entities/system-config.entity.ts | 0 .../entities/system-metadata.entity.ts | 0 server/src/{infra => }/entities/tag.entity.ts | 4 +- .../{infra => }/entities/user-token.entity.ts | 2 +- .../src/{infra => }/entities/user.entity.ts | 4 +- server/src/immich-admin/main.ts | 2 +- .../immich/api-v1/asset/asset-repository.ts | 4 +- .../immich/api-v1/asset/asset.service.spec.ts | 4 +- .../src/immich/api-v1/asset/asset.service.ts | 4 +- server/src/immich/app.module.ts | 4 +- server/src/infra/database.config.ts | 8 +-- server/src/infra/entities/index.ts | 47 ---------------- server/src/infra/infra.module.ts | 56 +++++++++---------- server/src/infra/infra.utils.ts | 2 +- server/src/infra/logger.ts | 2 +- server/src/infra/sql-generator/index.ts | 34 +++++------ server/src/interfaces/activity.repository.ts | 4 +- server/src/interfaces/album.repository.ts | 2 +- server/src/interfaces/api-key.repository.ts | 2 +- .../src/interfaces/asset-stack.repository.ts | 2 +- server/src/interfaces/asset.repository.ts | 8 +-- server/src/interfaces/audit.repository.ts | 2 +- .../interfaces/communication.repository.ts | 2 +- server/src/interfaces/library.repository.ts | 2 +- server/src/interfaces/media.repository.ts | 2 +- server/src/interfaces/move.repository.ts | 2 +- server/src/interfaces/partner.repository.ts | 2 +- server/src/interfaces/person.repository.ts | 6 +- server/src/interfaces/search.repository.ts | 8 +-- .../src/interfaces/shared-link.repository.ts | 2 +- .../interfaces/system-config.repository.ts | 2 +- .../interfaces/system-metadata.repository.ts | 2 +- server/src/interfaces/tag.repository.ts | 4 +- .../src/interfaces/user-token.repository.ts | 2 +- server/src/interfaces/user.repository.ts | 2 +- .../1645130759468-CreateUserTable.ts | 0 .../1645130777674-CreateDeviceInfoTable.ts | 0 .../1645130805273-CreateAssetsTable.ts | 0 .../1645130817965-CreateExifTable.ts | 0 .../1645130870184-CreateSmartInfoTable.ts | 0 .../1646249209023-AddExifTextSearchColumn.ts | 0 ...1646249734844-CreateExifTextSearchIndex.ts | 0 .../1646709533213-AddRegionCityToExIf.ts | 0 ...46710459852-AddLocationToExifTextSearch.ts | 0 ...648317474768-AddObjectColumnToSmartInfo.ts | 0 ...16111-CreateSharedAlbumAndRelatedTables.ts | 0 ...3525943-UpdateUserTableWithAdminAndName.ts | 0 ...3214255670-UpdateAssetTableWithWebpPath.ts | 0 ...583-UpdateAssetTableWithEncodeVideoPath.ts | 0 .../1655401127251-RenameSharedAlbums.ts | 0 ...56338626260-RenameIsFirstLoggedInColumn.ts | 0 ...656888591977-RenameAssetAlbumIdSequence.ts | 0 ...6888918620-DropExifTextSearchableColumn.ts | 0 ...1566-MatchMigrationsWithTypeORMEntities.ts | 0 ...470248-AddExifImageNameAsSearchableText.ts | 0 .../migrations/1661011331242-AddCaption.ts | 0 ...919411-ChangeExifFileSizeInByteToBigInt.ts | 0 .../1661881837496-AddAssetChecksum.ts | 0 ...UpdateAssetTableWithNewUniqueConstraint.ts | 0 ...365521-FixTimestampDataTypeInAssetTable.ts | 0 .../1665540663419-CreateSystemConfigTable.ts | 0 ...60744-AddingDeletedAtColumnInUserEntity.ts | 0 ...-AddLivePhotosRelatedColumnToAssetTable.ts | 0 .../1668835311083-UpdateUserTableForOIDC.ts | 0 .../migrations/1670104716264-OAuthId.ts | 0 .../1670257571385-CreateTagsTable.ts | 0 .../1670607437008-TruncateOldConfigItems.ts | 0 ...0633210032-AddUserEmailUniqueConstraint.ts | 0 .../1672109862870-DropSaltColumn.ts | 0 .../migrations/1672502270115-AddAPIKeys.ts | 0 .../1673150490490-AddSharedLinkTable.ts | 0 ...907194740-AddMorePermissionToSharedLink.ts | 0 ...4263302005-RemoveVideoCodecConfigOption.ts | 0 .../1674342044239-CreateUserTokenEntity.ts | 0 ...757936889-AlterExifExposureTimeToString.ts | 0 .../1674774248319-TruncateAPIKeys.ts | 0 ...9-AddSharedLinkUserForeignKeyConstraint.ts | 0 ...2-AddUpdatedAtColumnToAlbumsUsersAssets.ts | 0 ...909594-AddAlbumUserForeignKeyConstraint.ts | 0 .../1675808874445-APIKeyUUIDPrimaryKey.ts | 0 .../1675812532822-FixAlbumEntityTypeORM.ts | 0 .../1676437878377-AppleContentIdentifier.ts | 0 .../1676680127415-FixAssetRelations.ts | 0 .../1676721296440-AssetCreatedAtField.ts | 0 ...1676848629119-ExifEntityDefinitionFixes.ts | 0 ...8694786-SharedLinkEntityDefinitionFixes.ts | 0 ...52143506-SmartInfoEntityDefinitionFixes.ts | 0 .../1677497925328-AddExifTimeZone.ts | 0 ...43119-AddIndexForAlbumInSharedLinkTable.ts | 0 .../1677613712565-AlbumThumbnailRelation.ts | 0 .../1677971458822-AddCLIPEncodeDataColumn.ts | 0 .../1679751316282-UpdateTranscodeOption.ts | 0 .../1679901204458-ClipEmbeddingFloat4.ts | 0 .../1680632845740-AddIsArchivedColumn.ts | 0 ...680694465853-RemoveRedundantConstraints.ts | 0 ...4628393-AddOriginalFileNameToAssetTable.ts | 0 ...1159594469-RemoveImageNameFromEXIFTable.ts | 0 .../1682371561743-FixNullableRelations.ts | 0 .../1682371791038-AddDeviceInfoToUserToken.ts | 0 .../1682710252424-DropDeviceInfoTable.ts | 0 .../1683808254676-AddPartnersTable.ts | 0 .../1684255168091-AddFacialTables.ts | 0 .../1684273840676-AddSidecarFile.ts | 0 .../1684328185099-RequireChecksumNotNull.ts | 0 .../1684410565398-AddStorageLabel.ts | 0 ...867360825-AddUserTokenAndAPIKeyCascades.ts | 0 .../1685044328272-AddSharedLinkCascade.ts | 0 .../1685370430343-UserDatesTimestamptz.ts | 0 .../1685731372040-RemoveInvalidCoordinates.ts | 0 .../migrations/1686584273471-ImportAsset.ts | 0 .../1686762895180-AddThumbhashColumn.ts | 0 .../1688241394489-AddDetectFaceResultInfo.ts | 0 .../1688392120838-AddLibraryTable.ts | 0 .../1689001889950-DropMimeTypeColumn.ts | 0 .../1689281196844-AddHiddenFaces.ts | 0 .../migrations/1690469489288-Panoramas.ts | 0 .../1691209138541-AddAlbumDescription.ts | 0 .../1691600216749-UserMemoryPreference.ts | 0 .../1692057328660-fixGPSNullIsland.ts | 0 .../1692112147855-AddPersonBirthDate.ts | 0 .../migrations/1692804658140-AddAuditTable.ts | 0 .../1693236627291-RenameMLEnableFlags.ts | 0 .../1693833336881-AddPersonFaceAssetId.ts | 0 .../1694204416744-AddAssetDeletedAtColumn.ts | 0 .../1694525143117-AddLocalDateTime.ts | 0 .../1694638413248-AddDeletedAtToAlbums.ts | 0 .../1694750975773-AddExifColorSpace.ts | 0 .../1694758412194-UpdateOpusCodecToLibopus.ts | 0 .../1695354433573-AddStackParentIdToAssets.ts | 0 .../1695660378655-RemoveInvalidCoordinates.ts | 0 .../1696888644031-AddOriginalPathIndex.ts | 0 .../migrations/1696968880063-AddMoveTable.ts | 0 .../migrations/1697272818851-UnassignFace.ts | 0 .../1698290827089-AddPasswordToSharedLinks.ts | 0 .../migrations/1698693294632-AddActivity.ts | 0 .../1699268680508-DisableActivity.ts | 0 .../1699322864544-UserNameConsolidation.ts | 0 .../migrations/1699345863886-AddJobStatus.ts | 0 ...562570201-AdddInTimelineToPartnersTable.ts | 0 .../1699727044012-EditFaceAssetForeignKey.ts | 0 .../1699889987493-AddAvatarColor.ts | 0 .../1700345818045-SystemMetadata.ts | 0 .../migrations/1700362016675-Geodata.ts | 0 .../migrations/1700713871511-UsePgVectors.ts | 0 .../1700713994428-AddCLIPEmbeddingIndex.ts | 0 .../1700714033632-AddFaceEmbeddingIndex.ts | 0 .../1700714072055-AddSmartInfoTagsIndex.ts | 0 ...14140297-CreateSmartInfoTextSearchIndex.ts | 0 .../1700752078178-AddAssetFaceIndicies.ts | 0 .../1701665867595-AddExifCityIndex.ts | 0 ...02084989965-AddWebSocketAttachmentTable.ts | 0 .../1702257380990-DropNullIslandLatLong.ts | 0 ...fyFutureBirthDatesAndAddCheckConstraint.ts | 0 ...702942303661-FixRemovedAssetsSharedLink.ts | 0 .../1703035138085-AddAutoStackId.ts | 0 ...orageTemplateOnForExistingInstallations.ts | 0 .../1704382918223-AddQuotaColumnsToUser.ts | 0 ...faultOnboardingForExistingInstallations.ts | 0 ...43345360-SetAssetFaceNullOnPersonDelete.ts | 0 .../1705094221536-AddMetadataExtractedAt.ts | 0 .../1705306747072-AddOriginalFileNameIndex.ts | 0 .../1705363967169-CreateAssetStackTable.ts | 0 .../1707000751533-AddVectorsToSearchPath.ts | 0 .../1708059341865-GeodataLocationSearch.ts | 0 .../1708116312820-GeonamesEnhancement.ts | 0 .../1708227417898-AddFileCreatedAtIndex.ts | 0 .../1708425975121-RemoveExternalPath.ts | 0 ...0004123-RemoveLibraryWatchPollingOption.ts | 0 ...140355-AddAssetOriginalPathTrigramIndex.ts | 0 ...63765506-AddExtensionToOriginalFileName.ts | 0 .../1709825430031-CascadeSharedLinksDelete.ts | 0 .../migrations/1709870213078-AddUserStatus.ts | 0 .../1710182081326-AscendingOrderAlbum.ts | 0 .../1710293990203-AddAssetRelationIndices.ts | 0 .../repositories/access.repository.ts | 18 +++--- .../repositories/activity.repository.ts | 2 +- .../repositories/album.repository.ts | 4 +- .../repositories/api-key.repository.ts | 2 +- .../repositories/asset-stack.repository.ts | 2 +- .../repositories/asset.repository.ts | 10 ++-- .../repositories/audit.repository.ts | 2 +- .../repositories/communication.repository.ts | 0 .../repositories/crypto.repository.ts | 0 .../repositories/database.repository.ts | 0 .../repositories/filesystem.provider.spec.ts | 2 +- .../repositories/filesystem.provider.ts | 0 .../repositories/job.repository.ts | 0 .../repositories/library.repository.ts | 2 +- .../machine-learning.repository.ts | 0 .../repositories/media.repository.ts | 2 +- .../repositories/metadata.repository.ts | 6 +- .../repositories/move.repository.ts | 2 +- .../repositories/partner.repository.ts | 2 +- .../repositories/person.repository.ts | 6 +- .../repositories/search.repository.ts | 10 ++-- .../repositories/server-info.repository.ts | 0 .../repositories/shared-link.repository.ts | 2 +- .../repositories/system-config.repository.ts | 2 +- .../system-metadata.repository.ts | 2 +- .../repositories/tag.repository.ts | 4 +- .../repositories/user-token.repository.ts | 2 +- .../repositories/user.repository.ts | 4 +- .../subscribers/audit.subscriber.ts | 6 +- server/src/test-utils/utils.ts | 2 +- server/test/fixtures/activity.stub.ts | 2 +- server/test/fixtures/album.stub.ts | 2 +- server/test/fixtures/api-key.stub.ts | 2 +- server/test/fixtures/asset.stub.ts | 6 +- server/test/fixtures/audit.stub.ts | 2 +- server/test/fixtures/auth.stub.ts | 6 +- server/test/fixtures/face.stub.ts | 2 +- server/test/fixtures/library.stub.ts | 2 +- server/test/fixtures/partner.stub.ts | 2 +- server/test/fixtures/person.stub.ts | 2 +- server/test/fixtures/shared-link.stub.ts | 8 +-- server/test/fixtures/system-config.stub.ts | 2 +- server/test/fixtures/tag.stub.ts | 2 +- server/test/fixtures/user-token.stub.ts | 2 +- server/test/fixtures/user.stub.ts | 2 +- 310 files changed, 358 insertions(+), 362 deletions(-) rename server/src/{infra => }/entities/activity.entity.ts (86%) rename server/src/{infra => }/entities/album.entity.ts (88%) rename server/src/{infra => }/entities/api-key.entity.ts (90%) rename server/src/{infra => }/entities/asset-face.entity.ts (91%) rename server/src/{infra => }/entities/asset-job-status.entity.ts (88%) rename server/src/{infra => }/entities/asset-stack.entity.ts (88%) rename server/src/{infra => }/entities/asset.entity.ts (85%) rename server/src/{infra => }/entities/audit.entity.ts (100%) rename server/src/{infra => }/entities/exif.entity.ts (98%) rename server/src/{infra => }/entities/geodata-places.entity.ts (100%) create mode 100644 server/src/entities/index.ts rename server/src/{infra => }/entities/library.entity.ts (90%) rename server/src/{infra => }/entities/move.entity.ts (100%) rename server/src/{infra => }/entities/partner.entity.ts (92%) rename server/src/{infra => }/entities/person.entity.ts (88%) rename server/src/{infra => }/entities/shared-link.entity.ts (89%) rename server/src/{infra => }/entities/smart-info.entity.ts (89%) rename server/src/{infra => }/entities/smart-search.entity.ts (89%) rename server/src/{infra => }/entities/system-config.entity.ts (100%) rename server/src/{infra => }/entities/system-metadata.entity.ts (100%) rename server/src/{infra => }/entities/tag.entity.ts (88%) rename server/src/{infra => }/entities/user-token.entity.ts (91%) rename server/src/{infra => }/entities/user.entity.ts (93%) delete mode 100644 server/src/infra/entities/index.ts rename server/src/{infra => }/migrations/1645130759468-CreateUserTable.ts (100%) rename server/src/{infra => }/migrations/1645130777674-CreateDeviceInfoTable.ts (100%) rename server/src/{infra => }/migrations/1645130805273-CreateAssetsTable.ts (100%) rename server/src/{infra => }/migrations/1645130817965-CreateExifTable.ts (100%) rename server/src/{infra => }/migrations/1645130870184-CreateSmartInfoTable.ts (100%) rename server/src/{infra => }/migrations/1646249209023-AddExifTextSearchColumn.ts (100%) rename server/src/{infra => }/migrations/1646249734844-CreateExifTextSearchIndex.ts (100%) rename server/src/{infra => }/migrations/1646709533213-AddRegionCityToExIf.ts (100%) rename server/src/{infra => }/migrations/1646710459852-AddLocationToExifTextSearch.ts (100%) rename server/src/{infra => }/migrations/1648317474768-AddObjectColumnToSmartInfo.ts (100%) rename server/src/{infra => }/migrations/1649643216111-CreateSharedAlbumAndRelatedTables.ts (100%) rename server/src/{infra => }/migrations/1652633525943-UpdateUserTableWithAdminAndName.ts (100%) rename server/src/{infra => }/migrations/1653214255670-UpdateAssetTableWithWebpPath.ts (100%) rename server/src/{infra => }/migrations/1654299904583-UpdateAssetTableWithEncodeVideoPath.ts (100%) rename server/src/{infra => }/migrations/1655401127251-RenameSharedAlbums.ts (100%) rename server/src/{infra => }/migrations/1656338626260-RenameIsFirstLoggedInColumn.ts (100%) rename server/src/{infra => }/migrations/1656888591977-RenameAssetAlbumIdSequence.ts (100%) rename server/src/{infra => }/migrations/1656888918620-DropExifTextSearchableColumn.ts (100%) rename server/src/{infra => }/migrations/1656889061566-MatchMigrationsWithTypeORMEntities.ts (100%) rename server/src/{infra => }/migrations/1658860470248-AddExifImageNameAsSearchableText.ts (100%) rename server/src/{infra => }/migrations/1661011331242-AddCaption.ts (100%) rename server/src/{infra => }/migrations/1661528919411-ChangeExifFileSizeInByteToBigInt.ts (100%) rename server/src/{infra => }/migrations/1661881837496-AddAssetChecksum.ts (100%) rename server/src/{infra => }/migrations/1661971370662-UpdateAssetTableWithNewUniqueConstraint.ts (100%) rename server/src/{infra => }/migrations/1662427365521-FixTimestampDataTypeInAssetTable.ts (100%) rename server/src/{infra => }/migrations/1665540663419-CreateSystemConfigTable.ts (100%) rename server/src/{infra => }/migrations/1667762360744-AddingDeletedAtColumnInUserEntity.ts (100%) rename server/src/{infra => }/migrations/1668383120461-AddLivePhotosRelatedColumnToAssetTable.ts (100%) rename server/src/{infra => }/migrations/1668835311083-UpdateUserTableForOIDC.ts (100%) rename server/src/{infra => }/migrations/1670104716264-OAuthId.ts (100%) rename server/src/{infra => }/migrations/1670257571385-CreateTagsTable.ts (100%) rename server/src/{infra => }/migrations/1670607437008-TruncateOldConfigItems.ts (100%) rename server/src/{infra => }/migrations/1670633210032-AddUserEmailUniqueConstraint.ts (100%) rename server/src/{infra => }/migrations/1672109862870-DropSaltColumn.ts (100%) rename server/src/{infra => }/migrations/1672502270115-AddAPIKeys.ts (100%) rename server/src/{infra => }/migrations/1673150490490-AddSharedLinkTable.ts (100%) rename server/src/{infra => }/migrations/1673907194740-AddMorePermissionToSharedLink.ts (100%) rename server/src/{infra => }/migrations/1674263302005-RemoveVideoCodecConfigOption.ts (100%) rename server/src/{infra => }/migrations/1674342044239-CreateUserTokenEntity.ts (100%) rename server/src/{infra => }/migrations/1674757936889-AlterExifExposureTimeToString.ts (100%) rename server/src/{infra => }/migrations/1674774248319-TruncateAPIKeys.ts (100%) rename server/src/{infra => }/migrations/1674939383309-AddSharedLinkUserForeignKeyConstraint.ts (100%) rename server/src/{infra => }/migrations/1675667878312-AddUpdatedAtColumnToAlbumsUsersAssets.ts (100%) rename server/src/{infra => }/migrations/1675701909594-AddAlbumUserForeignKeyConstraint.ts (100%) rename server/src/{infra => }/migrations/1675808874445-APIKeyUUIDPrimaryKey.ts (100%) rename server/src/{infra => }/migrations/1675812532822-FixAlbumEntityTypeORM.ts (100%) rename server/src/{infra => }/migrations/1676437878377-AppleContentIdentifier.ts (100%) rename server/src/{infra => }/migrations/1676680127415-FixAssetRelations.ts (100%) rename server/src/{infra => }/migrations/1676721296440-AssetCreatedAtField.ts (100%) rename server/src/{infra => }/migrations/1676848629119-ExifEntityDefinitionFixes.ts (100%) rename server/src/{infra => }/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts (100%) rename server/src/{infra => }/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts (100%) rename server/src/{infra => }/migrations/1677497925328-AddExifTimeZone.ts (100%) rename server/src/{infra => }/migrations/1677535643119-AddIndexForAlbumInSharedLinkTable.ts (100%) rename server/src/{infra => }/migrations/1677613712565-AlbumThumbnailRelation.ts (100%) rename server/src/{infra => }/migrations/1677971458822-AddCLIPEncodeDataColumn.ts (100%) rename server/src/{infra => }/migrations/1679751316282-UpdateTranscodeOption.ts (100%) rename server/src/{infra => }/migrations/1679901204458-ClipEmbeddingFloat4.ts (100%) rename server/src/{infra => }/migrations/1680632845740-AddIsArchivedColumn.ts (100%) rename server/src/{infra => }/migrations/1680694465853-RemoveRedundantConstraints.ts (100%) rename server/src/{infra => }/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts (100%) rename server/src/{infra => }/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts (100%) rename server/src/{infra => }/migrations/1682371561743-FixNullableRelations.ts (100%) rename server/src/{infra => }/migrations/1682371791038-AddDeviceInfoToUserToken.ts (100%) rename server/src/{infra => }/migrations/1682710252424-DropDeviceInfoTable.ts (100%) rename server/src/{infra => }/migrations/1683808254676-AddPartnersTable.ts (100%) rename server/src/{infra => }/migrations/1684255168091-AddFacialTables.ts (100%) rename server/src/{infra => }/migrations/1684273840676-AddSidecarFile.ts (100%) rename server/src/{infra => }/migrations/1684328185099-RequireChecksumNotNull.ts (100%) rename server/src/{infra => }/migrations/1684410565398-AddStorageLabel.ts (100%) rename server/src/{infra => }/migrations/1684867360825-AddUserTokenAndAPIKeyCascades.ts (100%) rename server/src/{infra => }/migrations/1685044328272-AddSharedLinkCascade.ts (100%) rename server/src/{infra => }/migrations/1685370430343-UserDatesTimestamptz.ts (100%) rename server/src/{infra => }/migrations/1685731372040-RemoveInvalidCoordinates.ts (100%) rename server/src/{infra => }/migrations/1686584273471-ImportAsset.ts (100%) rename server/src/{infra => }/migrations/1686762895180-AddThumbhashColumn.ts (100%) rename server/src/{infra => }/migrations/1688241394489-AddDetectFaceResultInfo.ts (100%) rename server/src/{infra => }/migrations/1688392120838-AddLibraryTable.ts (100%) rename server/src/{infra => }/migrations/1689001889950-DropMimeTypeColumn.ts (100%) rename server/src/{infra => }/migrations/1689281196844-AddHiddenFaces.ts (100%) rename server/src/{infra => }/migrations/1690469489288-Panoramas.ts (100%) rename server/src/{infra => }/migrations/1691209138541-AddAlbumDescription.ts (100%) rename server/src/{infra => }/migrations/1691600216749-UserMemoryPreference.ts (100%) rename server/src/{infra => }/migrations/1692057328660-fixGPSNullIsland.ts (100%) rename server/src/{infra => }/migrations/1692112147855-AddPersonBirthDate.ts (100%) rename server/src/{infra => }/migrations/1692804658140-AddAuditTable.ts (100%) rename server/src/{infra => }/migrations/1693236627291-RenameMLEnableFlags.ts (100%) rename server/src/{infra => }/migrations/1693833336881-AddPersonFaceAssetId.ts (100%) rename server/src/{infra => }/migrations/1694204416744-AddAssetDeletedAtColumn.ts (100%) rename server/src/{infra => }/migrations/1694525143117-AddLocalDateTime.ts (100%) rename server/src/{infra => }/migrations/1694638413248-AddDeletedAtToAlbums.ts (100%) rename server/src/{infra => }/migrations/1694750975773-AddExifColorSpace.ts (100%) rename server/src/{infra => }/migrations/1694758412194-UpdateOpusCodecToLibopus.ts (100%) rename server/src/{infra => }/migrations/1695354433573-AddStackParentIdToAssets.ts (100%) rename server/src/{infra => }/migrations/1695660378655-RemoveInvalidCoordinates.ts (100%) rename server/src/{infra => }/migrations/1696888644031-AddOriginalPathIndex.ts (100%) rename server/src/{infra => }/migrations/1696968880063-AddMoveTable.ts (100%) rename server/src/{infra => }/migrations/1697272818851-UnassignFace.ts (100%) rename server/src/{infra => }/migrations/1698290827089-AddPasswordToSharedLinks.ts (100%) rename server/src/{infra => }/migrations/1698693294632-AddActivity.ts (100%) rename server/src/{infra => }/migrations/1699268680508-DisableActivity.ts (100%) rename server/src/{infra => }/migrations/1699322864544-UserNameConsolidation.ts (100%) rename server/src/{infra => }/migrations/1699345863886-AddJobStatus.ts (100%) rename server/src/{infra => }/migrations/1699562570201-AdddInTimelineToPartnersTable.ts (100%) rename server/src/{infra => }/migrations/1699727044012-EditFaceAssetForeignKey.ts (100%) rename server/src/{infra => }/migrations/1699889987493-AddAvatarColor.ts (100%) rename server/src/{infra => }/migrations/1700345818045-SystemMetadata.ts (100%) rename server/src/{infra => }/migrations/1700362016675-Geodata.ts (100%) rename server/src/{infra => }/migrations/1700713871511-UsePgVectors.ts (100%) rename server/src/{infra => }/migrations/1700713994428-AddCLIPEmbeddingIndex.ts (100%) rename server/src/{infra => }/migrations/1700714033632-AddFaceEmbeddingIndex.ts (100%) rename server/src/{infra => }/migrations/1700714072055-AddSmartInfoTagsIndex.ts (100%) rename server/src/{infra => }/migrations/1700714140297-CreateSmartInfoTextSearchIndex.ts (100%) rename server/src/{infra => }/migrations/1700752078178-AddAssetFaceIndicies.ts (100%) rename server/src/{infra => }/migrations/1701665867595-AddExifCityIndex.ts (100%) rename server/src/{infra => }/migrations/1702084989965-AddWebSocketAttachmentTable.ts (100%) rename server/src/{infra => }/migrations/1702257380990-DropNullIslandLatLong.ts (100%) rename server/src/{infra => }/migrations/1702938928766-NullifyFutureBirthDatesAndAddCheckConstraint.ts (100%) rename server/src/{infra => }/migrations/1702942303661-FixRemovedAssetsSharedLink.ts (100%) rename server/src/{infra => }/migrations/1703035138085-AddAutoStackId.ts (100%) rename server/src/{infra => }/migrations/1703288449127-DefaultStorageTemplateOnForExistingInstallations.ts (100%) rename server/src/{infra => }/migrations/1704382918223-AddQuotaColumnsToUser.ts (100%) rename server/src/{infra => }/migrations/1704571051932-DefaultOnboardingForExistingInstallations.ts (100%) rename server/src/{infra => }/migrations/1704943345360-SetAssetFaceNullOnPersonDelete.ts (100%) rename server/src/{infra => }/migrations/1705094221536-AddMetadataExtractedAt.ts (100%) rename server/src/{infra => }/migrations/1705306747072-AddOriginalFileNameIndex.ts (100%) rename server/src/{infra => }/migrations/1705363967169-CreateAssetStackTable.ts (100%) rename server/src/{infra => }/migrations/1707000751533-AddVectorsToSearchPath.ts (100%) rename server/src/{infra => }/migrations/1708059341865-GeodataLocationSearch.ts (100%) rename server/src/{infra => }/migrations/1708116312820-GeonamesEnhancement.ts (100%) rename server/src/{infra => }/migrations/1708227417898-AddFileCreatedAtIndex.ts (100%) rename server/src/{infra => }/migrations/1708425975121-RemoveExternalPath.ts (100%) rename server/src/{infra => }/migrations/1709150004123-RemoveLibraryWatchPollingOption.ts (100%) rename server/src/{infra => }/migrations/1709608140355-AddAssetOriginalPathTrigramIndex.ts (100%) rename server/src/{infra => }/migrations/1709763765506-AddExtensionToOriginalFileName.ts (100%) rename server/src/{infra => }/migrations/1709825430031-CascadeSharedLinksDelete.ts (100%) rename server/src/{infra => }/migrations/1709870213078-AddUserStatus.ts (100%) rename server/src/{infra => }/migrations/1710182081326-AscendingOrderAlbum.ts (100%) rename server/src/{infra => }/migrations/1710293990203-AddAssetRelationIndices.ts (100%) rename server/src/{infra => }/repositories/access.repository.ts (95%) rename server/src/{infra => }/repositories/activity.repository.ts (96%) rename server/src/{infra => }/repositories/album.repository.ts (98%) rename server/src/{infra => }/repositories/api-key.repository.ts (96%) rename server/src/{infra => }/repositories/asset-stack.repository.ts (94%) rename server/src/{infra => }/repositories/asset.repository.ts (98%) rename server/src/{infra => }/repositories/audit.repository.ts (94%) rename server/src/{infra => }/repositories/communication.repository.ts (100%) rename server/src/{infra => }/repositories/crypto.repository.ts (100%) rename server/src/{infra => }/repositories/database.repository.ts (100%) rename server/src/{infra => }/repositories/filesystem.provider.spec.ts (98%) rename server/src/{infra => }/repositories/filesystem.provider.ts (100%) rename server/src/{infra => }/repositories/job.repository.ts (100%) rename server/src/{infra => }/repositories/library.repository.ts (98%) rename server/src/{infra => }/repositories/machine-learning.repository.ts (100%) rename server/src/{infra => }/repositories/media.repository.ts (98%) rename server/src/{infra => }/repositories/metadata.repository.ts (97%) rename server/src/{infra => }/repositories/move.repository.ts (93%) rename server/src/{infra => }/repositories/partner.repository.ts (95%) rename server/src/{infra => }/repositories/person.repository.ts (97%) rename server/src/{infra => }/repositories/search.repository.ts (97%) rename server/src/{infra => }/repositories/server-info.repository.ts (100%) rename server/src/{infra => }/repositories/shared-link.repository.ts (96%) rename server/src/{infra => }/repositories/system-config.repository.ts (94%) rename server/src/{infra => }/repositories/system-metadata.repository.ts (90%) rename server/src/{infra => }/repositories/tag.repository.ts (96%) rename server/src/{infra => }/repositories/user-token.repository.ts (95%) rename server/src/{infra => }/repositories/user.repository.ts (97%) rename server/src/{infra => }/subscribers/audit.subscriber.ts (84%) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 1d57b3a84..13f5a73a1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -329,14 +329,14 @@ jobs: - name: Generate new migrations continue-on-error: true - run: npm run typeorm:migrations:generate ./src/infra/migrations/TestMigration + run: npm run typeorm:migrations:generate ./src/migrations/TestMigration - name: Find file changes uses: tj-actions/verify-changed-files@v19 id: verify-changed-files with: files: | - server/src/infra/migrations/ + server/src/migrations/ - name: Verify migration files have not changed if: steps.verify-changed-files.outputs.files_changed == 'true' run: | diff --git a/docs/docs/developer/database-migrations.md b/docs/docs/developer/database-migrations.md index a78274a61..eccf78b44 100644 --- a/docs/docs/developer/database-migrations.md +++ b/docs/docs/developer/database-migrations.md @@ -1,6 +1,6 @@ # Database Migrations -After making any changes in the `server/src/infra/entities`, a database migration need to run in order to register the changes in the database. Follow the steps below to create a new migration. +After making any changes in the `server/src/entities`, a database migration need to run in order to register the changes in the database. Follow the steps below to create a new migration. 1. Run the command @@ -9,6 +9,6 @@ npm run typeorm:migrations:generate ./src/infra/ ``` 2. Check if the migration file makes sense. -3. Move the migration file to folder `./server/src/infra/migrations` in your code editor. +3. Move the migration file to folder `./server/src/migrations` in your code editor. The server will automatically detect `*.ts` file changes and restart. Part of the server start-up process includes running any new migrations, so it will be applied immediately. diff --git a/server/e2e/jobs/jest-e2e.json b/server/e2e/jobs/jest-e2e.json index b9a238d83..b7e62d5f4 100644 --- a/server/e2e/jobs/jest-e2e.json +++ b/server/e2e/jobs/jest-e2e.json @@ -12,11 +12,11 @@ "collectCoverageFrom": [ "/src/**/*.(t|j)s", "!/src/**/*.spec.(t|s)s", - "!/src/infra/migrations/**" + "!/src/migrations/**" ], "coverageDirectory": "./coverage", "moduleNameMapper": { - "^test(|/.*)$": "/test/$1", - "^src(|/.*)$": "/src/$1" + "^test(|/.*)$": "/test/$1", + "^src(|/.*)$": "/src/$1" } } diff --git a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts index a146bc856..e8be570ca 100644 --- a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts +++ b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts @@ -4,8 +4,8 @@ import path from 'node:path'; import { LoginResponseDto } from 'src/domain/auth/auth.dto'; import { LibraryResponseDto } from 'src/domain/library/library.dto'; import { LibraryService } from 'src/domain/library/library.service'; -import { AssetType } from 'src/infra/entities/asset.entity'; -import { LibraryType } from 'src/infra/entities/library.entity'; +import { AssetType } from 'src/entities/asset.entity'; +import { LibraryType } from 'src/entities/library.entity'; import { StorageEventType } from 'src/interfaces/storage.repository'; import { IMMICH_TEST_ASSET_PATH, diff --git a/server/e2e/jobs/specs/library.e2e-spec.ts b/server/e2e/jobs/specs/library.e2e-spec.ts index f67dd9178..c2839a7d1 100644 --- a/server/e2e/jobs/specs/library.e2e-spec.ts +++ b/server/e2e/jobs/specs/library.e2e-spec.ts @@ -2,7 +2,7 @@ import { api } from 'e2e/client'; import fs from 'node:fs'; import { LibraryController } from 'src/controllers/library.controller'; import { LoginResponseDto } from 'src/domain/auth/auth.dto'; -import { LibraryType } from 'src/infra/entities/library.entity'; +import { LibraryType } from 'src/entities/library.entity'; import { IMMICH_TEST_ASSET_PATH, IMMICH_TEST_ASSET_TEMP_PATH, restoreTempFolder, testApp } from 'src/test-utils/utils'; import request from 'supertest'; import { errorStub } from 'test/fixtures/error.stub'; diff --git a/server/package.json b/server/package.json index 30ba53b61..eb65eadf0 100644 --- a/server/package.json +++ b/server/package.json @@ -148,6 +148,8 @@ "collectCoverageFrom": [ "/src/**/*.(t|j)s", "!/src/infra/**/*", + "!/src/migrations/**/*", + "!/src/subscribers/**/*", "!/src/immich/controllers/**/*" ], "coverageDirectory": "./coverage", diff --git a/server/src/commands/list-users.command.ts b/server/src/commands/list-users.command.ts index eeda72d1c..222833fad 100644 --- a/server/src/commands/list-users.command.ts +++ b/server/src/commands/list-users.command.ts @@ -1,6 +1,6 @@ import { Command, CommandRunner } from 'nest-commander'; import { UserService } from 'src/domain/user/user.service'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { UserEntity } from 'src/entities/user.entity'; @Command({ name: 'list-users', diff --git a/server/src/config.ts b/server/src/config.ts index 01f3f1a1c..b97f0bb7e 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -4,7 +4,7 @@ import { QueueOptions } from 'bullmq'; import { RedisOptions } from 'ioredis'; import Joi from 'joi'; import { QueueName } from 'src/domain/job/job.constants'; -import { LogLevel } from 'src/infra/entities/system-config.entity'; +import { LogLevel } from 'src/entities/system-config.entity'; const WHEN_DB_URL_SET = Joi.when('DB_URL', { is: Joi.exist(), diff --git a/server/src/cores/access.core.ts b/server/src/cores/access.core.ts index 389647524..f9e22bb6b 100644 --- a/server/src/cores/access.core.ts +++ b/server/src/cores/access.core.ts @@ -1,6 +1,6 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { setDifference, setIsEqual, setUnion } from 'src/utils'; diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 39d9e12c9..8bf65b248 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -1,9 +1,9 @@ import { dirname, join, resolve } from 'node:path'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { AssetPathType, PathType, PersonPathType } from 'src/infra/entities/move.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity'; +import { PersonEntity } from 'src/entities/person.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/cores/system-config.core.ts b/server/src/cores/system-config.core.ts index 1bfab773d..295a0e5ed 100644 --- a/server/src/cores/system-config.core.ts +++ b/server/src/cores/system-config.core.ts @@ -20,7 +20,7 @@ import { TranscodeHWAccel, TranscodePolicy, VideoCodec, -} from 'src/infra/entities/system-config.entity'; +} from 'src/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; diff --git a/server/src/cores/user.core.ts b/server/src/cores/user.core.ts index 488c16036..d91f2bae5 100644 --- a/server/src/cores/user.core.ts +++ b/server/src/cores/user.core.ts @@ -1,8 +1,8 @@ import { BadRequestException, ForbiddenException } from '@nestjs/common'; import sanitize from 'sanitize-filename'; import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; -import { LibraryType } from 'src/infra/entities/library.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { LibraryType } from 'src/entities/library.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; diff --git a/server/src/domain/activity/activity.dto.ts b/server/src/domain/activity/activity.dto.ts index 1bfbabd80..a9d865778 100644 --- a/server/src/domain/activity/activity.dto.ts +++ b/server/src/domain/activity/activity.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString, ValidateIf } from 'class-validator'; import { UserDto, mapSimpleUser } from 'src/domain/user/response-dto/user-response.dto'; -import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { ActivityEntity } from 'src/entities/activity.entity'; import { Optional, ValidateUUID } from 'src/validation'; export enum ReactionType { diff --git a/server/src/domain/activity/activity.service.ts b/server/src/domain/activity/activity.service.ts index 9ed8946f5..81d77fa8d 100644 --- a/server/src/domain/activity/activity.service.ts +++ b/server/src/domain/activity/activity.service.ts @@ -12,7 +12,7 @@ import { mapActivity, } from 'src/domain/activity/activity.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { ActivityEntity } from 'src/entities/activity.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IActivityRepository } from 'src/interfaces/activity.repository'; diff --git a/server/src/domain/album/album-response.dto.ts b/server/src/domain/album/album-response.dto.ts index 663a463f2..b016a1200 100644 --- a/server/src/domain/album/album-response.dto.ts +++ b/server/src/domain/album/album-response.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { AlbumEntity, AssetOrder } from 'src/infra/entities/album.entity'; +import { AlbumEntity, AssetOrder } from 'src/entities/album.entity'; import { Optional } from 'src/validation'; export class AlbumResponseDto { diff --git a/server/src/domain/album/album.service.ts b/server/src/domain/album/album.service.ts index 77a6c6c46..4d459ea44 100644 --- a/server/src/domain/album/album.service.ts +++ b/server/src/domain/album/album.service.ts @@ -14,9 +14,9 @@ import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AlbumEntity } from 'src/entities/album.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/album/dto/album-update.dto.ts b/server/src/domain/album/dto/album-update.dto.ts index 1f329cb3c..cf2d5f8c2 100644 --- a/server/src/domain/album/dto/album-update.dto.ts +++ b/server/src/domain/album/dto/album-update.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsString } from 'class-validator'; -import { AssetOrder } from 'src/infra/entities/album.entity'; +import { AssetOrder } from 'src/entities/album.entity'; import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class UpdateAlbumDto { diff --git a/server/src/domain/api-key/api-key.service.ts b/server/src/domain/api-key/api-key.service.ts index c8e7c5ec3..540c1d71f 100644 --- a/server/src/domain/api-key/api-key.service.ts +++ b/server/src/domain/api-key/api-key.service.ts @@ -1,7 +1,7 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto } from 'src/domain/api-key/api-key.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { APIKeyEntity } from 'src/entities/api-key.entity'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/domain/asset/asset.service.spec.ts b/server/src/domain/asset/asset.service.spec.ts index 9b59f4092..7b49cfef9 100644 --- a/server/src/domain/asset/asset.service.spec.ts +++ b/server/src/domain/asset/asset.service.spec.ts @@ -5,7 +5,7 @@ import { AssetJobName } from 'src/domain/asset/dto/asset-ids.dto'; import { AssetStatsResponseDto } from 'src/domain/asset/dto/asset-statistics.dto'; import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { JobName } from 'src/domain/job/job.constants'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; import { AssetStats, IAssetRepository, TimeBucketSize } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; diff --git a/server/src/domain/asset/asset.service.ts b/server/src/domain/asset/asset.service.ts index 2594233c4..38446b576 100644 --- a/server/src/domain/asset/asset.service.ts +++ b/server/src/domain/asset/asset.service.ts @@ -25,8 +25,8 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; import { IAssetDeletionJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { LibraryType } from 'src/infra/entities/library.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { LibraryType } from 'src/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; diff --git a/server/src/domain/asset/dto/asset-statistics.dto.ts b/server/src/domain/asset/dto/asset-statistics.dto.ts index 45bae1f5d..93e007029 100644 --- a/server/src/domain/asset/dto/asset-statistics.dto.ts +++ b/server/src/domain/asset/dto/asset-statistics.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { AssetType } from 'src/infra/entities/asset.entity'; +import { AssetType } from 'src/entities/asset.entity'; import { AssetStats } from 'src/interfaces/asset.repository'; import { ValidateBoolean } from 'src/validation'; diff --git a/server/src/domain/asset/dto/time-bucket.dto.ts b/server/src/domain/asset/dto/time-bucket.dto.ts index 7b2ee24c0..a5ff023d1 100644 --- a/server/src/domain/asset/dto/time-bucket.dto.ts +++ b/server/src/domain/asset/dto/time-bucket.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { AssetOrder } from 'src/infra/entities/album.entity'; +import { AssetOrder } from 'src/entities/album.entity'; import { TimeBucketSize } from 'src/interfaces/asset.repository'; import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; diff --git a/server/src/domain/asset/response-dto/asset-response.dto.ts b/server/src/domain/asset/response-dto/asset-response.dto.ts index a5c88b4cb..dff12d481 100644 --- a/server/src/domain/asset/response-dto/asset-response.dto.ts +++ b/server/src/domain/asset/response-dto/asset-response.dto.ts @@ -5,8 +5,8 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; import { PersonWithFacesResponseDto, mapFacesWithoutPerson, mapPerson } from 'src/domain/person/person.dto'; import { TagResponseDto, mapTag } from 'src/domain/tag/tag-response.dto'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; export class SanitizedAssetResponseDto { id!: string; diff --git a/server/src/domain/asset/response-dto/exif-response.dto.ts b/server/src/domain/asset/response-dto/exif-response.dto.ts index fbef6cbbc..6724de98f 100644 --- a/server/src/domain/asset/response-dto/exif-response.dto.ts +++ b/server/src/domain/asset/response-dto/exif-response.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; export class ExifResponseDto { make?: string | null = null; diff --git a/server/src/domain/asset/response-dto/smart-info-response.dto.ts b/server/src/domain/asset/response-dto/smart-info-response.dto.ts index 840fca8a7..c55c7ffb3 100644 --- a/server/src/domain/asset/response-dto/smart-info-response.dto.ts +++ b/server/src/domain/asset/response-dto/smart-info-response.dto.ts @@ -1,4 +1,4 @@ -import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { SmartInfoEntity } from 'src/entities/smart-info.entity'; export class SmartInfoResponseDto { tags?: string[] | null; diff --git a/server/src/domain/audit/audit.dto.ts b/server/src/domain/audit/audit.dto.ts index 1c34e9491..e83efca76 100644 --- a/server/src/domain/audit/audit.dto.ts +++ b/server/src/domain/audit/audit.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsEnum, IsString, IsUUID, ValidateNested } from 'class-validator'; -import { EntityType } from 'src/infra/entities/audit.entity'; -import { AssetPathType, PathType, PersonPathType, UserPathType } from 'src/infra/entities/move.entity'; +import { EntityType } from 'src/entities/audit.entity'; +import { AssetPathType, PathType, PersonPathType, UserPathType } from 'src/entities/move.entity'; import { Optional, ValidateDate, ValidateUUID } from 'src/validation'; const PathEnum = Object.values({ ...AssetPathType, ...PersonPathType, ...UserPathType }); diff --git a/server/src/domain/audit/audit.service.spec.ts b/server/src/domain/audit/audit.service.spec.ts index aa110dfb2..ecda57b08 100644 --- a/server/src/domain/audit/audit.service.spec.ts +++ b/server/src/domain/audit/audit.service.spec.ts @@ -1,5 +1,5 @@ import { AuditService } from 'src/domain/audit/audit.service'; -import { DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; +import { DatabaseAction, EntityType } from 'src/entities/audit.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IAuditRepository } from 'src/interfaces/audit.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/domain/audit/audit.service.ts b/server/src/domain/audit/audit.service.ts index cf8b7f303..91acb54d9 100644 --- a/server/src/domain/audit/audit.service.ts +++ b/server/src/domain/audit/audit.service.ts @@ -14,8 +14,8 @@ import { import { AuthDto } from 'src/domain/auth/auth.dto'; import { AUDIT_LOG_MAX_DURATION } from 'src/domain/domain.constant'; import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; -import { DatabaseAction } from 'src/infra/entities/audit.entity'; -import { AssetPathType, PersonPathType, UserPathType } from 'src/infra/entities/move.entity'; +import { DatabaseAction } from 'src/entities/audit.entity'; +import { AssetPathType, PersonPathType, UserPathType } from 'src/entities/move.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/auth/auth.dto.ts b/server/src/domain/auth/auth.dto.ts index 1694231ab..f3f2270d0 100644 --- a/server/src/domain/auth/auth.dto.ts +++ b/server/src/domain/auth/auth.dto.ts @@ -1,10 +1,10 @@ import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsEmail, IsNotEmpty, IsString, MinLength } from 'class-validator'; -import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; -import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { APIKeyEntity } from 'src/entities/api-key.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; +import { UserTokenEntity } from 'src/entities/user-token.entity'; +import { UserEntity } from 'src/entities/user.entity'; export class AuthDto { user!: UserEntity; diff --git a/server/src/domain/auth/auth.service.spec.ts b/server/src/domain/auth/auth.service.spec.ts index 2cbc3cb6e..e091cdcd9 100644 --- a/server/src/domain/auth/auth.service.spec.ts +++ b/server/src/domain/auth/auth.service.spec.ts @@ -5,7 +5,7 @@ import { Socket } from 'socket.io'; import { AuthType } from 'src/domain/auth/auth.constant'; import { AuthDto, SignUpDto } from 'src/domain/auth/auth.dto'; import { AuthService } from 'src/domain/auth/auth.service'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; diff --git a/server/src/domain/auth/auth.service.ts b/server/src/domain/auth/auth.service.ts index 0f2709307..2d807a249 100644 --- a/server/src/domain/auth/auth.service.ts +++ b/server/src/domain/auth/auth.service.ts @@ -37,8 +37,8 @@ import { mapUserToken, } from 'src/domain/auth/auth.dto'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { SystemConfig } from 'src/infra/entities/system-config.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { SystemConfig } from 'src/entities/system-config.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; diff --git a/server/src/domain/domain.constant.ts b/server/src/domain/domain.constant.ts index 13c8fa532..29c4837b6 100644 --- a/server/src/domain/domain.constant.ts +++ b/server/src/domain/domain.constant.ts @@ -1,7 +1,7 @@ import { Duration } from 'luxon'; import { readFileSync } from 'node:fs'; import { extname, join } from 'node:path'; -import { AssetType } from 'src/infra/entities/asset.entity'; +import { AssetType } from 'src/entities/asset.entity'; export const AUDIT_LOG_MAX_DURATION = Duration.fromObject({ days: 100 }); export const ONE_HOUR = Duration.fromObject({ hours: 1 }); diff --git a/server/src/domain/download/download.service.ts b/server/src/domain/download/download.service.ts index 5c790548d..8c0168a6c 100644 --- a/server/src/domain/download/download.service.ts +++ b/server/src/domain/download/download.service.ts @@ -5,7 +5,7 @@ import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/download.dto'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IStorageRepository, ImmichReadStream } from 'src/interfaces/storage.repository'; diff --git a/server/src/domain/job/job.service.spec.ts b/server/src/domain/job/job.service.spec.ts index 1b46ec936..ec905b062 100644 --- a/server/src/domain/job/job.service.spec.ts +++ b/server/src/domain/job/job.service.spec.ts @@ -2,7 +2,7 @@ import { BadRequestException } from '@nestjs/common'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; import { JobService } from 'src/domain/job/job.service'; -import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { SystemConfig, SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ICommunicationRepository } from 'src/interfaces/communication.repository'; import { IJobRepository, JobHandler, JobItem, JobStatus } from 'src/interfaces/job.repository'; diff --git a/server/src/domain/job/job.service.ts b/server/src/domain/job/job.service.ts index 567603656..192b093c1 100644 --- a/server/src/domain/job/job.service.ts +++ b/server/src/domain/job/job.service.ts @@ -3,7 +3,7 @@ import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { ConcurrentQueueName, JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/domain/job/job.dto'; -import { AssetType } from 'src/infra/entities/asset.entity'; +import { AssetType } from 'src/entities/asset.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; diff --git a/server/src/domain/library/library.dto.ts b/server/src/domain/library/library.dto.ts index f65779fb8..951012a85 100644 --- a/server/src/domain/library/library.dto.ts +++ b/server/src/domain/library/library.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { ArrayMaxSize, ArrayUnique, IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; export class CreateLibraryDto { diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/domain/library/library.service.spec.ts index 00592dc1e..f34b6d5be 100644 --- a/server/src/domain/library/library.service.spec.ts +++ b/server/src/domain/library/library.service.spec.ts @@ -7,10 +7,10 @@ import { JobName } from 'src/domain/job/job.constants'; import { ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; import { mapLibrary } from 'src/domain/library/library.dto'; import { LibraryService } from 'src/domain/library/library.service'; -import { AssetType } from 'src/infra/entities/asset.entity'; -import { LibraryType } from 'src/infra/entities/library.entity'; -import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AssetType } from 'src/entities/asset.entity'; +import { LibraryType } from 'src/entities/library.entity'; +import { SystemConfig, SystemConfigKey } from 'src/entities/system-config.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { IDatabaseRepository } from 'src/interfaces/database.repository'; diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts index b859d0046..1fc009149 100644 --- a/server/src/domain/library/library.service.ts +++ b/server/src/domain/library/library.service.ts @@ -23,8 +23,8 @@ import { ValidateLibraryResponseDto, mapLibrary, } from 'src/domain/library/library.dto'; -import { AssetType } from 'src/infra/entities/asset.entity'; -import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { AssetType } from 'src/entities/asset.entity'; +import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository, WithProperty } from 'src/interfaces/asset.repository'; import { InternalEvent, InternalEventMap } from 'src/interfaces/communication.repository'; diff --git a/server/src/domain/media/media.service.spec.ts b/server/src/domain/media/media.service.spec.ts index ad3ed3d22..97a6d161b 100644 --- a/server/src/domain/media/media.service.spec.ts +++ b/server/src/domain/media/media.service.spec.ts @@ -1,8 +1,8 @@ import { Stats } from 'node:fs'; import { JobName } from 'src/domain/job/job.constants'; import { MediaService } from 'src/domain/media/media.service'; -import { AssetType } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { AssetType } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; import { AudioCodec, Colorspace, @@ -11,7 +11,7 @@ import { TranscodeHWAccel, TranscodePolicy, VideoCodec, -} from 'src/infra/entities/system-config.entity'; +} from 'src/entities/system-config.entity'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index 6807e962a..c254689b4 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -14,8 +14,8 @@ import { VP9Config, } from 'src/domain/media/media.util'; import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { AssetPathType } from 'src/infra/entities/move.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { AssetPathType } from 'src/entities/move.entity'; import { AudioCodec, Colorspace, @@ -23,7 +23,7 @@ import { TranscodePolicy, TranscodeTarget, VideoCodec, -} from 'src/infra/entities/system-config.entity'; +} from 'src/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/domain/media/media.util.ts b/server/src/domain/media/media.util.ts index bc9fa4887..3e58ca81a 100644 --- a/server/src/domain/media/media.util.ts +++ b/server/src/domain/media/media.util.ts @@ -1,11 +1,5 @@ import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; -import { - CQMode, - ToneMapping, - TranscodeHWAccel, - TranscodeTarget, - VideoCodec, -} from 'src/infra/entities/system-config.entity'; +import { CQMode, ToneMapping, TranscodeHWAccel, TranscodeTarget, VideoCodec } from 'src/entities/system-config.entity'; import { AudioStreamInfo, BitrateDistribution, diff --git a/server/src/domain/metadata/metadata.service.spec.ts b/server/src/domain/metadata/metadata.service.spec.ts index f8483d6ef..2108c5fc4 100644 --- a/server/src/domain/metadata/metadata.service.spec.ts +++ b/server/src/domain/metadata/metadata.service.spec.ts @@ -5,9 +5,9 @@ import { Stats } from 'node:fs'; import { constants } from 'node:fs/promises'; import { JobName } from 'src/domain/job/job.constants'; import { MetadataService, Orientation } from 'src/domain/metadata/metadata.service'; -import { AssetType } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; -import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { AssetType } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; +import { SystemConfigKey } from 'src/entities/system-config.entity'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; diff --git a/server/src/domain/metadata/metadata.service.ts b/server/src/domain/metadata/metadata.service.ts index d7f98e245..0e949626c 100644 --- a/server/src/domain/metadata/metadata.service.ts +++ b/server/src/domain/metadata/metadata.service.ts @@ -10,8 +10,8 @@ import { StorageCore } from 'src/cores/storage.core'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IEntityJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/partner/partner.service.spec.ts b/server/src/domain/partner/partner.service.spec.ts index 487818b3d..7d4821282 100644 --- a/server/src/domain/partner/partner.service.spec.ts +++ b/server/src/domain/partner/partner.service.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException } from '@nestjs/common'; import { PartnerResponseDto } from 'src/domain/partner/partner.dto'; import { PartnerService } from 'src/domain/partner/partner.service'; -import { UserAvatarColor } from 'src/infra/entities/user.entity'; +import { UserAvatarColor } from 'src/entities/user.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IPartnerRepository, PartnerDirection } from 'src/interfaces/partner.repository'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/partner/partner.service.ts b/server/src/domain/partner/partner.service.ts index 2528b44be..34a88a7ea 100644 --- a/server/src/domain/partner/partner.service.ts +++ b/server/src/domain/partner/partner.service.ts @@ -3,7 +3,7 @@ import { AccessCore, Permission } from 'src/cores/access.core'; import { AuthDto } from 'src/domain/auth/auth.dto'; import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { PartnerEntity } from 'src/entities/partner.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IPartnerRepository, PartnerDirection, PartnerIds } from 'src/interfaces/partner.repository'; diff --git a/server/src/domain/person/person.dto.ts b/server/src/domain/person/person.dto.ts index f3699499a..4153ba813 100644 --- a/server/src/domain/person/person.dto.ts +++ b/server/src/domain/person/person.dto.ts @@ -2,8 +2,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsNotEmpty, IsString, MaxDate, ValidateNested } from 'class-validator'; import { AuthDto } from 'src/domain/auth/auth.dto'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { PersonEntity } from 'src/entities/person.entity'; import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; export class PersonCreateDto { diff --git a/server/src/domain/person/person.service.spec.ts b/server/src/domain/person/person.service.spec.ts index 042469d7e..9da66e868 100644 --- a/server/src/domain/person/person.service.spec.ts +++ b/server/src/domain/person/person.service.spec.ts @@ -3,8 +3,8 @@ import { BulkIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-respo import { JobName } from 'src/domain/job/job.constants'; import { PersonResponseDto, mapFaces, mapPerson } from 'src/domain/person/person.dto'; import { PersonService } from 'src/domain/person/person.service'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { Colorspace, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { Colorspace, SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; diff --git a/server/src/domain/person/person.service.ts b/server/src/domain/person/person.service.ts index 9e56e4b18..cd7ba9224 100644 --- a/server/src/domain/person/person.service.ts +++ b/server/src/domain/person/person.service.ts @@ -24,8 +24,8 @@ import { mapFaces, mapPerson, } from 'src/domain/person/person.dto'; -import { PersonPathType } from 'src/infra/entities/move.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; +import { PersonPathType } from 'src/entities/move.entity'; +import { PersonEntity } from 'src/entities/person.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/search/dto/search.dto.ts b/server/src/domain/search/dto/search.dto.ts index 52090b945..4f77517b3 100644 --- a/server/src/domain/search/dto/search.dto.ts +++ b/server/src/domain/search/dto/search.dto.ts @@ -1,9 +1,9 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsInt, IsNotEmpty, IsString, Max, Min } from 'class-validator'; -import { AssetOrder } from 'src/infra/entities/album.entity'; -import { AssetType } from 'src/infra/entities/asset.entity'; -import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; +import { AssetOrder } from 'src/entities/album.entity'; +import { AssetType } from 'src/entities/asset.entity'; +import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; class BaseSearchDto { diff --git a/server/src/domain/search/search.service.spec.ts b/server/src/domain/search/search.service.spec.ts index f9313d277..f72212809 100644 --- a/server/src/domain/search/search.service.spec.ts +++ b/server/src/domain/search/search.service.spec.ts @@ -1,7 +1,7 @@ import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { SearchDto } from 'src/domain/search/dto/search.dto'; import { SearchService } from 'src/domain/search/search.service'; -import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; import { IMetadataRepository } from 'src/interfaces/metadata.repository'; diff --git a/server/src/domain/search/search.service.ts b/server/src/domain/search/search.service.ts index 9778c6d3d..cedee68d0 100644 --- a/server/src/domain/search/search.service.ts +++ b/server/src/domain/search/search.service.ts @@ -14,8 +14,8 @@ import { mapPlaces, } from 'src/domain/search/dto/search.dto'; import { SearchResponseDto } from 'src/domain/search/response-dto/search-response.dto'; -import { AssetOrder } from 'src/infra/entities/album.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetOrder } from 'src/entities/album.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; import { IMetadataRepository } from 'src/interfaces/metadata.repository'; diff --git a/server/src/domain/server-info/server-info.service.spec.ts b/server/src/domain/server-info/server-info.service.spec.ts index 05f05cc8f..1685f8bda 100644 --- a/server/src/domain/server-info/server-info.service.spec.ts +++ b/server/src/domain/server-info/server-info.service.spec.ts @@ -1,6 +1,6 @@ import { serverVersion } from 'src/domain/domain.constant'; import { ServerInfoService } from 'src/domain/server-info/server-info.service'; -import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; +import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; import { ICommunicationRepository } from 'src/interfaces/communication.repository'; import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index 533bb42d9..13921949c 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -12,7 +12,7 @@ import { ServerStatsResponseDto, UsageByUserDto, } from 'src/domain/server-info/server-info.dto'; -import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; +import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; import { ImmichLogger } from 'src/infra/logger'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; diff --git a/server/src/domain/shared-link/shared-link-response.dto.ts b/server/src/domain/shared-link/shared-link-response.dto.ts index 034b45f1c..44024506f 100644 --- a/server/src/domain/shared-link/shared-link-response.dto.ts +++ b/server/src/domain/shared-link/shared-link-response.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty } from '@nestjs/swagger'; import _ from 'lodash'; import { AlbumResponseDto, mapAlbumWithoutAssets } from 'src/domain/album/album-response.dto'; import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; -import { SharedLinkEntity, SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { SharedLinkEntity, SharedLinkType } from 'src/entities/shared-link.entity'; export class SharedLinkResponseDto { id!: string; diff --git a/server/src/domain/shared-link/shared-link.dto.ts b/server/src/domain/shared-link/shared-link.dto.ts index 7ef9a7733..73928aac2 100644 --- a/server/src/domain/shared-link/shared-link.dto.ts +++ b/server/src/domain/shared-link/shared-link.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsString } from 'class-validator'; -import { SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { SharedLinkType } from 'src/entities/shared-link.entity'; import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; export class SharedLinkCreateDto { diff --git a/server/src/domain/shared-link/shared-link.service.spec.ts b/server/src/domain/shared-link/shared-link.service.spec.ts index 3b15138f4..926ec16b1 100644 --- a/server/src/domain/shared-link/shared-link.service.spec.ts +++ b/server/src/domain/shared-link/shared-link.service.spec.ts @@ -2,7 +2,7 @@ import { BadRequestException, ForbiddenException, UnauthorizedException } from ' import _ from 'lodash'; import { AssetIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; -import { SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { SharedLinkType } from 'src/entities/shared-link.entity'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; import { albumStub } from 'test/fixtures/album.stub'; diff --git a/server/src/domain/shared-link/shared-link.service.ts b/server/src/domain/shared-link/shared-link.service.ts index 34619cc5c..e01deee7b 100644 --- a/server/src/domain/shared-link/shared-link.service.ts +++ b/server/src/domain/shared-link/shared-link.service.ts @@ -9,8 +9,8 @@ import { mapSharedLinkWithoutMetadata, } from 'src/domain/shared-link/shared-link-response.dto'; import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { SharedLinkEntity, SharedLinkType } from 'src/infra/entities/shared-link.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { SharedLinkEntity, SharedLinkType } from 'src/entities/shared-link.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; diff --git a/server/src/domain/smart-info/smart-info.service.spec.ts b/server/src/domain/smart-info/smart-info.service.spec.ts index fec43eb08..29ce75fb4 100644 --- a/server/src/domain/smart-info/smart-info.service.spec.ts +++ b/server/src/domain/smart-info/smart-info.service.spec.ts @@ -1,8 +1,8 @@ import { JobName } from 'src/domain/job/job.constants'; import { cleanModelName, getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { IDatabaseRepository } from 'src/interfaces/database.repository'; import { IJobRepository } from 'src/interfaces/job.repository'; diff --git a/server/src/domain/storage-template/storage-template.service.spec.ts b/server/src/domain/storage-template/storage-template.service.spec.ts index c73dfbdcf..ecadb3e86 100644 --- a/server/src/domain/storage-template/storage-template.service.spec.ts +++ b/server/src/domain/storage-template/storage-template.service.spec.ts @@ -2,8 +2,8 @@ import { when } from 'jest-when'; import { Stats } from 'node:fs'; import { SystemConfigCore, defaults } from 'src/cores/system-config.core'; import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; -import { AssetPathType } from 'src/infra/entities/move.entity'; -import { SystemConfig, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { AssetPathType } from 'src/entities/move.entity'; +import { SystemConfig, SystemConfigKey } from 'src/entities/system-config.entity'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/domain/storage-template/storage-template.service.ts b/server/src/domain/storage-template/storage-template.service.ts index 480f97368..b4af03a9f 100644 --- a/server/src/domain/storage-template/storage-template.service.ts +++ b/server/src/domain/storage-template/storage-template.service.ts @@ -17,9 +17,9 @@ import { supportedWeekTokens, supportedYearTokens, } from 'src/domain/system-config/system-config.constants'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { AssetPathType } from 'src/infra/entities/move.entity'; -import { SystemConfig } from 'src/infra/entities/system-config.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { AssetPathType } from 'src/entities/move.entity'; +import { SystemConfig } from 'src/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts b/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts index 16f81b37c..017f69c2d 100644 --- a/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts +++ b/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts @@ -8,7 +8,7 @@ import { TranscodeHWAccel, TranscodePolicy, VideoCodec, -} from 'src/infra/entities/system-config.entity'; +} from 'src/entities/system-config.entity'; import { ValidateBoolean } from 'src/validation'; export class SystemConfigFFmpegDto { diff --git a/server/src/domain/system-config/dto/system-config-logging.dto.ts b/server/src/domain/system-config/dto/system-config-logging.dto.ts index f41b568a2..53ef5d2f0 100644 --- a/server/src/domain/system-config/dto/system-config-logging.dto.ts +++ b/server/src/domain/system-config/dto/system-config-logging.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; -import { LogLevel } from 'src/infra/entities/system-config.entity'; +import { LogLevel } from 'src/entities/system-config.entity'; import { ValidateBoolean } from 'src/validation'; export class SystemConfigLoggingDto { diff --git a/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts b/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts index 2f156894f..d3240efb1 100644 --- a/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts +++ b/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsInt, Max, Min } from 'class-validator'; -import { Colorspace } from 'src/infra/entities/system-config.entity'; +import { Colorspace } from 'src/entities/system-config.entity'; export class SystemConfigThumbnailDto { @IsInt() diff --git a/server/src/domain/system-config/dto/system-config.dto.ts b/server/src/domain/system-config/dto/system-config.dto.ts index 4f97975bc..9aef92303 100644 --- a/server/src/domain/system-config/dto/system-config.dto.ts +++ b/server/src/domain/system-config/dto/system-config.dto.ts @@ -16,7 +16,7 @@ import { SystemConfigThemeDto } from 'src/domain/system-config/dto/system-config import { SystemConfigThumbnailDto } from 'src/domain/system-config/dto/system-config-thumbnail.dto'; import { SystemConfigTrashDto } from 'src/domain/system-config/dto/system-config-trash.dto'; import { SystemConfigUserDto } from 'src/domain/system-config/dto/system-config-user.dto'; -import { SystemConfig } from 'src/infra/entities/system-config.entity'; +import { SystemConfig } from 'src/entities/system-config.entity'; export class SystemConfigDto implements SystemConfig { @Type(() => SystemConfigFFmpegDto) diff --git a/server/src/domain/system-config/system-config.service.spec.ts b/server/src/domain/system-config/system-config.service.spec.ts index 94db09bab..f81d726eb 100644 --- a/server/src/domain/system-config/system-config.service.spec.ts +++ b/server/src/domain/system-config/system-config.service.spec.ts @@ -14,7 +14,7 @@ import { TranscodeHWAccel, TranscodePolicy, VideoCodec, -} from 'src/infra/entities/system-config.entity'; +} from 'src/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; import { ICommunicationRepository, ServerEvent } from 'src/interfaces/communication.repository'; import { ISearchRepository } from 'src/interfaces/search.repository'; diff --git a/server/src/domain/system-config/system-config.service.ts b/server/src/domain/system-config/system-config.service.ts index bd2c30805..d69593d21 100644 --- a/server/src/domain/system-config/system-config.service.ts +++ b/server/src/domain/system-config/system-config.service.ts @@ -15,7 +15,7 @@ import { supportedWeekTokens, supportedYearTokens, } from 'src/domain/system-config/system-config.constants'; -import { LogLevel, SystemConfig } from 'src/infra/entities/system-config.entity'; +import { LogLevel, SystemConfig } from 'src/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; import { ClientEvent, diff --git a/server/src/domain/tag/tag-response.dto.ts b/server/src/domain/tag/tag-response.dto.ts index 04ee9540b..535efcf43 100644 --- a/server/src/domain/tag/tag-response.dto.ts +++ b/server/src/domain/tag/tag-response.dto.ts @@ -1,5 +1,5 @@ import { ApiProperty } from '@nestjs/swagger'; -import { TagEntity, TagType } from 'src/infra/entities/tag.entity'; +import { TagEntity, TagType } from 'src/entities/tag.entity'; export class TagResponseDto { id!: string; diff --git a/server/src/domain/tag/tag.dto.ts b/server/src/domain/tag/tag.dto.ts index 322f40acf..abf9549d8 100644 --- a/server/src/domain/tag/tag.dto.ts +++ b/server/src/domain/tag/tag.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { TagType } from 'src/infra/entities/tag.entity'; +import { TagType } from 'src/entities/tag.entity'; import { Optional } from 'src/validation'; export class CreateTagDto { diff --git a/server/src/domain/tag/tag.service.spec.ts b/server/src/domain/tag/tag.service.spec.ts index 012a745ee..9f630cdc0 100644 --- a/server/src/domain/tag/tag.service.spec.ts +++ b/server/src/domain/tag/tag.service.spec.ts @@ -2,7 +2,7 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; import { AssetIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { TagService } from 'src/domain/tag/tag.service'; -import { TagType } from 'src/infra/entities/tag.entity'; +import { TagType } from 'src/entities/tag.entity'; import { ITagRepository } from 'src/interfaces/tag.repository'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/user/dto/update-user.dto.ts b/server/src/domain/user/dto/update-user.dto.ts index c7c47c4cf..059971e6c 100644 --- a/server/src/domain/user/dto/update-user.dto.ts +++ b/server/src/domain/user/dto/update-user.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Transform } from 'class-transformer'; import { IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator'; -import { UserAvatarColor } from 'src/infra/entities/user.entity'; +import { UserAvatarColor } from 'src/entities/user.entity'; import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation'; export class UpdateUserDto { diff --git a/server/src/domain/user/response-dto/user-response.dto.ts b/server/src/domain/user/response-dto/user-response.dto.ts index b2a5d12cf..12ffca48c 100644 --- a/server/src/domain/user/response-dto/user-response.dto.ts +++ b/server/src/domain/user/response-dto/user-response.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum } from 'class-validator'; -import { UserAvatarColor, UserEntity, UserStatus } from 'src/infra/entities/user.entity'; +import { UserAvatarColor, UserEntity, UserStatus } from 'src/entities/user.entity'; export const getRandomAvatarColor = (user: UserEntity): UserAvatarColor => { const values = Object.values(UserAvatarColor); diff --git a/server/src/domain/user/user.service.spec.ts b/server/src/domain/user/user.service.spec.ts index c187e71cc..5b9a1de95 100644 --- a/server/src/domain/user/user.service.spec.ts +++ b/server/src/domain/user/user.service.spec.ts @@ -9,7 +9,7 @@ import { JobName } from 'src/domain/job/job.constants'; import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { UserService } from 'src/domain/user/user.service'; -import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; +import { UserEntity, UserStatus } from 'src/entities/user.entity'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { IJobRepository } from 'src/interfaces/job.repository'; diff --git a/server/src/domain/user/user.service.ts b/server/src/domain/user/user.service.ts index 3b2bbf370..349a775ec 100644 --- a/server/src/domain/user/user.service.ts +++ b/server/src/domain/user/user.service.ts @@ -15,7 +15,7 @@ import { mapCreateProfileImageResponse, } from 'src/domain/user/response-dto/create-profile-image-response.dto'; import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { UserEntity, UserStatus } from 'src/infra/entities/user.entity'; +import { UserEntity, UserStatus } from 'src/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/infra/entities/activity.entity.ts b/server/src/entities/activity.entity.ts similarity index 86% rename from server/src/infra/entities/activity.entity.ts rename to server/src/entities/activity.entity.ts index 478595556..8de76ac89 100644 --- a/server/src/infra/entities/activity.entity.ts +++ b/server/src/entities/activity.entity.ts @@ -1,6 +1,6 @@ -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AlbumEntity } from 'src/entities/album.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Check, Column, diff --git a/server/src/infra/entities/album.entity.ts b/server/src/entities/album.entity.ts similarity index 88% rename from server/src/infra/entities/album.entity.ts rename to server/src/entities/album.entity.ts index ab15d401d..99fae4f23 100644 --- a/server/src/infra/entities/album.entity.ts +++ b/server/src/entities/album.entity.ts @@ -1,6 +1,6 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Column, CreateDateColumn, diff --git a/server/src/infra/entities/api-key.entity.ts b/server/src/entities/api-key.entity.ts similarity index 90% rename from server/src/infra/entities/api-key.entity.ts rename to server/src/entities/api-key.entity.ts index 0d1893398..18aaa8304 100644 --- a/server/src/infra/entities/api-key.entity.ts +++ b/server/src/entities/api-key.entity.ts @@ -1,4 +1,4 @@ -import { UserEntity } from 'src/infra/entities/user.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; @Entity('api_keys') diff --git a/server/src/infra/entities/asset-face.entity.ts b/server/src/entities/asset-face.entity.ts similarity index 91% rename from server/src/infra/entities/asset-face.entity.ts rename to server/src/entities/asset-face.entity.ts index afd2a263a..38fcd4606 100644 --- a/server/src/infra/entities/asset-face.entity.ts +++ b/server/src/entities/asset-face.entity.ts @@ -1,5 +1,5 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { PersonEntity } from 'src/entities/person.entity'; import { Column, Entity, Index, ManyToOne, PrimaryGeneratedColumn } from 'typeorm'; @Entity('asset_faces', { synchronize: false }) diff --git a/server/src/infra/entities/asset-job-status.entity.ts b/server/src/entities/asset-job-status.entity.ts similarity index 88% rename from server/src/infra/entities/asset-job-status.entity.ts rename to server/src/entities/asset-job-status.entity.ts index 22d98e367..b50075203 100644 --- a/server/src/infra/entities/asset-job-status.entity.ts +++ b/server/src/entities/asset-job-status.entity.ts @@ -1,4 +1,4 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; @Entity('asset_job_status') diff --git a/server/src/infra/entities/asset-stack.entity.ts b/server/src/entities/asset-stack.entity.ts similarity index 88% rename from server/src/infra/entities/asset-stack.entity.ts rename to server/src/entities/asset-stack.entity.ts index 372fac1e4..28607e7ab 100644 --- a/server/src/infra/entities/asset-stack.entity.ts +++ b/server/src/entities/asset-stack.entity.ts @@ -1,4 +1,4 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { Column, Entity, JoinColumn, OneToMany, OneToOne, PrimaryGeneratedColumn } from 'typeorm'; @Entity('asset_stack') diff --git a/server/src/infra/entities/asset.entity.ts b/server/src/entities/asset.entity.ts similarity index 85% rename from server/src/infra/entities/asset.entity.ts rename to server/src/entities/asset.entity.ts index e82bbfb00..916636115 100644 --- a/server/src/infra/entities/asset.entity.ts +++ b/server/src/entities/asset.entity.ts @@ -1,14 +1,14 @@ -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; -import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; -import { LibraryEntity } from 'src/infra/entities/library.entity'; -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; -import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; -import { SmartSearchEntity } from 'src/infra/entities/smart-search.entity'; -import { TagEntity } from 'src/infra/entities/tag.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AlbumEntity } from 'src/entities/album.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; +import { AssetStackEntity } from 'src/entities/asset-stack.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; +import { LibraryEntity } from 'src/entities/library.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; +import { SmartInfoEntity } from 'src/entities/smart-info.entity'; +import { SmartSearchEntity } from 'src/entities/smart-search.entity'; +import { TagEntity } from 'src/entities/tag.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Column, CreateDateColumn, diff --git a/server/src/infra/entities/audit.entity.ts b/server/src/entities/audit.entity.ts similarity index 100% rename from server/src/infra/entities/audit.entity.ts rename to server/src/entities/audit.entity.ts diff --git a/server/src/infra/entities/exif.entity.ts b/server/src/entities/exif.entity.ts similarity index 98% rename from server/src/infra/entities/exif.entity.ts rename to server/src/entities/exif.entity.ts index 8ed645d11..6f7aafadf 100644 --- a/server/src/infra/entities/exif.entity.ts +++ b/server/src/entities/exif.entity.ts @@ -1,4 +1,4 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; import { Column } from 'typeorm/decorator/columns/Column.js'; import { Entity } from 'typeorm/decorator/entity/Entity.js'; diff --git a/server/src/infra/entities/geodata-places.entity.ts b/server/src/entities/geodata-places.entity.ts similarity index 100% rename from server/src/infra/entities/geodata-places.entity.ts rename to server/src/entities/geodata-places.entity.ts diff --git a/server/src/entities/index.ts b/server/src/entities/index.ts new file mode 100644 index 000000000..33b5f0013 --- /dev/null +++ b/server/src/entities/index.ts @@ -0,0 +1,47 @@ +import { ActivityEntity } from 'src/entities/activity.entity'; +import { AlbumEntity } from 'src/entities/album.entity'; +import { APIKeyEntity } from 'src/entities/api-key.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; +import { AssetStackEntity } from 'src/entities/asset-stack.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { AuditEntity } from 'src/entities/audit.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; +import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; +import { LibraryEntity } from 'src/entities/library.entity'; +import { MoveEntity } from 'src/entities/move.entity'; +import { PartnerEntity } from 'src/entities/partner.entity'; +import { PersonEntity } from 'src/entities/person.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; +import { SmartInfoEntity } from 'src/entities/smart-info.entity'; +import { SmartSearchEntity } from 'src/entities/smart-search.entity'; +import { SystemConfigEntity } from 'src/entities/system-config.entity'; +import { SystemMetadataEntity } from 'src/entities/system-metadata.entity'; +import { TagEntity } from 'src/entities/tag.entity'; +import { UserTokenEntity } from 'src/entities/user-token.entity'; +import { UserEntity } from 'src/entities/user.entity'; + +export const databaseEntities = [ + ActivityEntity, + AlbumEntity, + APIKeyEntity, + AssetEntity, + AssetStackEntity, + AssetFaceEntity, + AssetJobStatusEntity, + AuditEntity, + ExifEntity, + GeodataPlacesEntity, + MoveEntity, + PartnerEntity, + PersonEntity, + SharedLinkEntity, + SmartInfoEntity, + SmartSearchEntity, + SystemConfigEntity, + SystemMetadataEntity, + TagEntity, + UserEntity, + UserTokenEntity, + LibraryEntity, +]; diff --git a/server/src/infra/entities/library.entity.ts b/server/src/entities/library.entity.ts similarity index 90% rename from server/src/infra/entities/library.entity.ts rename to server/src/entities/library.entity.ts index f68a38095..8be560a88 100644 --- a/server/src/infra/entities/library.entity.ts +++ b/server/src/entities/library.entity.ts @@ -1,5 +1,5 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Column, CreateDateColumn, diff --git a/server/src/infra/entities/move.entity.ts b/server/src/entities/move.entity.ts similarity index 100% rename from server/src/infra/entities/move.entity.ts rename to server/src/entities/move.entity.ts diff --git a/server/src/infra/entities/partner.entity.ts b/server/src/entities/partner.entity.ts similarity index 92% rename from server/src/infra/entities/partner.entity.ts rename to server/src/entities/partner.entity.ts index abf0400da..189f6f51a 100644 --- a/server/src/infra/entities/partner.entity.ts +++ b/server/src/entities/partner.entity.ts @@ -1,4 +1,4 @@ -import { UserEntity } from 'src/infra/entities/user.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Column, CreateDateColumn, Entity, JoinColumn, ManyToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm'; @Entity('partners') diff --git a/server/src/infra/entities/person.entity.ts b/server/src/entities/person.entity.ts similarity index 88% rename from server/src/infra/entities/person.entity.ts rename to server/src/entities/person.entity.ts index 046ac9d40..bc60efcd6 100644 --- a/server/src/infra/entities/person.entity.ts +++ b/server/src/entities/person.entity.ts @@ -1,5 +1,5 @@ -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Check, Column, diff --git a/server/src/infra/entities/shared-link.entity.ts b/server/src/entities/shared-link.entity.ts similarity index 89% rename from server/src/infra/entities/shared-link.entity.ts rename to server/src/entities/shared-link.entity.ts index 7370146df..f328192f7 100644 --- a/server/src/infra/entities/shared-link.entity.ts +++ b/server/src/entities/shared-link.entity.ts @@ -1,6 +1,6 @@ -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AlbumEntity } from 'src/entities/album.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Column, CreateDateColumn, diff --git a/server/src/infra/entities/smart-info.entity.ts b/server/src/entities/smart-info.entity.ts similarity index 89% rename from server/src/infra/entities/smart-info.entity.ts rename to server/src/entities/smart-info.entity.ts index 5bd65e7fb..86190c174 100644 --- a/server/src/infra/entities/smart-info.entity.ts +++ b/server/src/entities/smart-info.entity.ts @@ -1,4 +1,4 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { Column, Entity, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; @Entity('smart_info', { synchronize: false }) diff --git a/server/src/infra/entities/smart-search.entity.ts b/server/src/entities/smart-search.entity.ts similarity index 89% rename from server/src/infra/entities/smart-search.entity.ts rename to server/src/entities/smart-search.entity.ts index bbd966fd4..4595ad240 100644 --- a/server/src/infra/entities/smart-search.entity.ts +++ b/server/src/entities/smart-search.entity.ts @@ -1,4 +1,4 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { Column, Entity, Index, JoinColumn, OneToOne, PrimaryColumn } from 'typeorm'; @Entity('smart_search', { synchronize: false }) diff --git a/server/src/infra/entities/system-config.entity.ts b/server/src/entities/system-config.entity.ts similarity index 100% rename from server/src/infra/entities/system-config.entity.ts rename to server/src/entities/system-config.entity.ts diff --git a/server/src/infra/entities/system-metadata.entity.ts b/server/src/entities/system-metadata.entity.ts similarity index 100% rename from server/src/infra/entities/system-metadata.entity.ts rename to server/src/entities/system-metadata.entity.ts diff --git a/server/src/infra/entities/tag.entity.ts b/server/src/entities/tag.entity.ts similarity index 88% rename from server/src/infra/entities/tag.entity.ts rename to server/src/entities/tag.entity.ts index b159dcb2e..93edcb055 100644 --- a/server/src/infra/entities/tag.entity.ts +++ b/server/src/entities/tag.entity.ts @@ -1,5 +1,5 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Column, Entity, ManyToMany, ManyToOne, PrimaryGeneratedColumn, Unique } from 'typeorm'; @Entity('tags') diff --git a/server/src/infra/entities/user-token.entity.ts b/server/src/entities/user-token.entity.ts similarity index 91% rename from server/src/infra/entities/user-token.entity.ts rename to server/src/entities/user-token.entity.ts index fd04c20dd..3c2cf2cf6 100644 --- a/server/src/infra/entities/user-token.entity.ts +++ b/server/src/entities/user-token.entity.ts @@ -1,4 +1,4 @@ -import { UserEntity } from 'src/infra/entities/user.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Column, CreateDateColumn, Entity, ManyToOne, PrimaryGeneratedColumn, UpdateDateColumn } from 'typeorm'; @Entity('user_token') diff --git a/server/src/infra/entities/user.entity.ts b/server/src/entities/user.entity.ts similarity index 93% rename from server/src/infra/entities/user.entity.ts rename to server/src/entities/user.entity.ts index 888655d3b..4d6361aba 100644 --- a/server/src/infra/entities/user.entity.ts +++ b/server/src/entities/user.entity.ts @@ -1,5 +1,5 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { TagEntity } from 'src/infra/entities/tag.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { TagEntity } from 'src/entities/tag.entity'; import { Column, CreateDateColumn, diff --git a/server/src/immich-admin/main.ts b/server/src/immich-admin/main.ts index 0b569dd9a..4a561ec88 100755 --- a/server/src/immich-admin/main.ts +++ b/server/src/immich-admin/main.ts @@ -1,6 +1,6 @@ import { CommandFactory } from 'nest-commander'; +import { LogLevel } from 'src/entities/system-config.entity'; import { AppModule } from 'src/immich-admin/app.module'; -import { LogLevel } from 'src/infra/entities/system-config.entity'; export async function bootstrap() { process.env.LOG_LEVEL = LogLevel.WARN; diff --git a/server/src/immich/api-v1/asset/asset-repository.ts b/server/src/immich/api-v1/asset/asset-repository.ts index 12a627875..e7b870239 100644 --- a/server/src/immich/api-v1/asset/asset-repository.ts +++ b/server/src/immich/api-v1/asset/asset-repository.ts @@ -1,12 +1,12 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; import { AssetSearchDto } from 'src/immich/api-v1/asset/dto/asset-search.dto'; import { CheckExistingAssetsDto } from 'src/immich/api-v1/asset/dto/check-existing-assets.dto'; import { SearchPropertiesDto } from 'src/immich/api-v1/asset/dto/search-properties.dto'; import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; import { OptionalBetween } from 'src/infra/infra.utils'; import { In } from 'typeorm/find-options/operator/In.js'; import { Repository } from 'typeorm/repository/Repository.js'; diff --git a/server/src/immich/api-v1/asset/asset.service.spec.ts b/server/src/immich/api-v1/asset/asset.service.spec.ts index 37f1a540f..d10590475 100644 --- a/server/src/immich/api-v1/asset/asset.service.spec.ts +++ b/server/src/immich/api-v1/asset/asset.service.spec.ts @@ -1,11 +1,11 @@ import { when } from 'jest-when'; import { JobName } from 'src/domain/job/job.constants'; +import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; import { AssetService } from 'src/immich/api-v1/asset/asset.service'; import { CreateAssetDto } from 'src/immich/api-v1/asset/dto/create-asset.dto'; import { AssetRejectReason, AssetUploadAction } from 'src/immich/api-v1/asset/response-dto/asset-check-response.dto'; -import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IJobRepository } from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 879128077..0a5722690 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -11,6 +11,8 @@ import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset- import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; import { JobName } from 'src/domain/job/job.constants'; +import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { LibraryType } from 'src/entities/library.entity'; import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; import { AssetBulkUploadCheckDto } from 'src/immich/api-v1/asset/dto/asset-check.dto'; import { AssetSearchDto } from 'src/immich/api-v1/asset/dto/asset-search.dto'; @@ -27,8 +29,6 @@ import { AssetFileUploadResponseDto } from 'src/immich/api-v1/asset/response-dto import { CheckExistingAssetsResponseDto } from 'src/immich/api-v1/asset/response-dto/check-existing-assets-response.dto'; import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; -import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { LibraryType } from 'src/infra/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; diff --git a/server/src/immich/app.module.ts b/server/src/immich/app.module.ts index 66edf2341..a5b88473e 100644 --- a/server/src/immich/app.module.ts +++ b/server/src/immich/app.module.ts @@ -24,12 +24,12 @@ import { TagController } from 'src/controllers/tag.controller'; import { TrashController } from 'src/controllers/trash.controller'; import { UserController } from 'src/controllers/user.controller'; import { DomainModule } from 'src/domain/domain.module'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; import { AssetRepositoryV1, IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; import { AssetController as AssetControllerV1 } from 'src/immich/api-v1/asset/asset.controller'; import { AssetService as AssetServiceV1 } from 'src/immich/api-v1/asset/asset.service'; import { AppService } from 'src/immich/app.service'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; import { InfraModule } from 'src/infra/infra.module'; import { AuthGuard } from 'src/middleware/auth.guard'; import { ErrorInterceptor } from 'src/middleware/error.interceptor'; diff --git a/server/src/infra/database.config.ts b/server/src/infra/database.config.ts index fd6286f1b..572288c59 100644 --- a/server/src/infra/database.config.ts +++ b/server/src/infra/database.config.ts @@ -16,11 +16,11 @@ const urlOrParts = url /* eslint unicorn/prefer-module: "off" -- We can fix this when migrating to ESM*/ export const databaseConfig: PostgresConnectionOptions = { type: 'postgres', - entities: [__dirname + '/entities/*.entity.{js,ts}'], - synchronize: false, - migrations: [__dirname + '/migrations/*.{js,ts}'], - subscribers: [__dirname + '/subscribers/*.{js,ts}'], + entities: [__dirname + '/../entities/*.entity.{js,ts}'], + migrations: [__dirname + '/../migrations/*.{js,ts}'], + subscribers: [__dirname + '/../subscribers/*.{js,ts}'], migrationsRun: false, + synchronize: false, connectTimeoutMS: 10_000, // 10 seconds parseInt8: true, ...urlOrParts, diff --git a/server/src/infra/entities/index.ts b/server/src/infra/entities/index.ts deleted file mode 100644 index 47fc3c7f1..000000000 --- a/server/src/infra/entities/index.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { ActivityEntity } from 'src/infra/entities/activity.entity'; -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; -import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { AuditEntity } from 'src/infra/entities/audit.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; -import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; -import { LibraryEntity } from 'src/infra/entities/library.entity'; -import { MoveEntity } from 'src/infra/entities/move.entity'; -import { PartnerEntity } from 'src/infra/entities/partner.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; -import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; -import { SmartSearchEntity } from 'src/infra/entities/smart-search.entity'; -import { SystemConfigEntity } from 'src/infra/entities/system-config.entity'; -import { SystemMetadataEntity } from 'src/infra/entities/system-metadata.entity'; -import { TagEntity } from 'src/infra/entities/tag.entity'; -import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; - -export const databaseEntities = [ - ActivityEntity, - AlbumEntity, - APIKeyEntity, - AssetEntity, - AssetStackEntity, - AssetFaceEntity, - AssetJobStatusEntity, - AuditEntity, - ExifEntity, - GeodataPlacesEntity, - MoveEntity, - PartnerEntity, - PersonEntity, - SharedLinkEntity, - SmartInfoEntity, - SmartSearchEntity, - SystemConfigEntity, - SystemMetadataEntity, - TagEntity, - UserEntity, - UserTokenEntity, - LibraryEntity, -]; diff --git a/server/src/infra/infra.module.ts b/server/src/infra/infra.module.ts index 9864a0191..b0387ba96 100644 --- a/server/src/infra/infra.module.ts +++ b/server/src/infra/infra.module.ts @@ -6,36 +6,9 @@ import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpenTelemetryModule } from 'nestjs-otel'; import { bullConfig, bullQueues, immichAppConfig } from 'src/config'; +import { databaseEntities } from 'src/entities'; import { databaseConfig } from 'src/infra/database.config'; -import { databaseEntities } from 'src/infra/entities'; import { otelConfig } from 'src/infra/instrumentation'; -import { AccessRepository } from 'src/infra/repositories/access.repository'; -import { ActivityRepository } from 'src/infra/repositories/activity.repository'; -import { AlbumRepository } from 'src/infra/repositories/album.repository'; -import { ApiKeyRepository } from 'src/infra/repositories/api-key.repository'; -import { AssetStackRepository } from 'src/infra/repositories/asset-stack.repository'; -import { AssetRepository } from 'src/infra/repositories/asset.repository'; -import { AuditRepository } from 'src/infra/repositories/audit.repository'; -import { CommunicationRepository } from 'src/infra/repositories/communication.repository'; -import { CryptoRepository } from 'src/infra/repositories/crypto.repository'; -import { DatabaseRepository } from 'src/infra/repositories/database.repository'; -import { FilesystemProvider } from 'src/infra/repositories/filesystem.provider'; -import { JobRepository } from 'src/infra/repositories/job.repository'; -import { LibraryRepository } from 'src/infra/repositories/library.repository'; -import { MachineLearningRepository } from 'src/infra/repositories/machine-learning.repository'; -import { MediaRepository } from 'src/infra/repositories/media.repository'; -import { MetadataRepository } from 'src/infra/repositories/metadata.repository'; -import { MoveRepository } from 'src/infra/repositories/move.repository'; -import { PartnerRepository } from 'src/infra/repositories/partner.repository'; -import { PersonRepository } from 'src/infra/repositories/person.repository'; -import { SearchRepository } from 'src/infra/repositories/search.repository'; -import { ServerInfoRepository } from 'src/infra/repositories/server-info.repository'; -import { SharedLinkRepository } from 'src/infra/repositories/shared-link.repository'; -import { SystemConfigRepository } from 'src/infra/repositories/system-config.repository'; -import { SystemMetadataRepository } from 'src/infra/repositories/system-metadata.repository'; -import { TagRepository } from 'src/infra/repositories/tag.repository'; -import { UserTokenRepository } from 'src/infra/repositories/user-token.repository'; -import { UserRepository } from 'src/infra/repositories/user.repository'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IActivityRepository } from 'src/interfaces/activity.repository'; import { IAlbumRepository } from 'src/interfaces/album.repository'; @@ -63,6 +36,33 @@ import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.reposi import { ITagRepository } from 'src/interfaces/tag.repository'; import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { AccessRepository } from 'src/repositories/access.repository'; +import { ActivityRepository } from 'src/repositories/activity.repository'; +import { AlbumRepository } from 'src/repositories/album.repository'; +import { ApiKeyRepository } from 'src/repositories/api-key.repository'; +import { AssetStackRepository } from 'src/repositories/asset-stack.repository'; +import { AssetRepository } from 'src/repositories/asset.repository'; +import { AuditRepository } from 'src/repositories/audit.repository'; +import { CommunicationRepository } from 'src/repositories/communication.repository'; +import { CryptoRepository } from 'src/repositories/crypto.repository'; +import { DatabaseRepository } from 'src/repositories/database.repository'; +import { FilesystemProvider } from 'src/repositories/filesystem.provider'; +import { JobRepository } from 'src/repositories/job.repository'; +import { LibraryRepository } from 'src/repositories/library.repository'; +import { MachineLearningRepository } from 'src/repositories/machine-learning.repository'; +import { MediaRepository } from 'src/repositories/media.repository'; +import { MetadataRepository } from 'src/repositories/metadata.repository'; +import { MoveRepository } from 'src/repositories/move.repository'; +import { PartnerRepository } from 'src/repositories/partner.repository'; +import { PersonRepository } from 'src/repositories/person.repository'; +import { SearchRepository } from 'src/repositories/search.repository'; +import { ServerInfoRepository } from 'src/repositories/server-info.repository'; +import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; +import { SystemConfigRepository } from 'src/repositories/system-config.repository'; +import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; +import { TagRepository } from 'src/repositories/tag.repository'; +import { UserTokenRepository } from 'src/repositories/user-token.repository'; +import { UserRepository } from 'src/repositories/user.repository'; const providers: Provider[] = [ { provide: IActivityRepository, useClass: ActivityRepository }, diff --git a/server/src/infra/infra.utils.ts b/server/src/infra/infra.utils.ts index 36f1ef4bf..2b75af379 100644 --- a/server/src/infra/infra.utils.ts +++ b/server/src/infra/infra.utils.ts @@ -1,5 +1,5 @@ import _ from 'lodash'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { AssetSearchBuilderOptions } from 'src/interfaces/search.repository'; import { Paginated, PaginatedBuilderOptions, PaginationMode, PaginationOptions, PaginationResult } from 'src/utils'; import { diff --git a/server/src/infra/logger.ts b/server/src/infra/logger.ts index dcc87a875..fef13a8fb 100644 --- a/server/src/infra/logger.ts +++ b/server/src/infra/logger.ts @@ -1,6 +1,6 @@ import { ConsoleLogger } from '@nestjs/common'; import { isLogLevelEnabled } from '@nestjs/common/services/utils/is-log-level-enabled.util'; -import { LogLevel } from 'src/infra/entities/system-config.entity'; +import { LogLevel } from 'src/entities/system-config.entity'; const LOG_LEVELS = [LogLevel.VERBOSE, LogLevel.DEBUG, LogLevel.LOG, LogLevel.WARN, LogLevel.ERROR, LogLevel.FATAL]; diff --git a/server/src/infra/sql-generator/index.ts b/server/src/infra/sql-generator/index.ts index a117568d8..10730fc36 100644 --- a/server/src/infra/sql-generator/index.ts +++ b/server/src/infra/sql-generator/index.ts @@ -6,26 +6,26 @@ import { TypeOrmModule } from '@nestjs/typeorm'; import { mkdir, rm, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators'; +import { databaseEntities } from 'src/entities'; import { databaseConfig } from 'src/infra/database.config'; -import { databaseEntities } from 'src/infra/entities'; -import { AccessRepository } from 'src/infra/repositories/access.repository'; -import { AlbumRepository } from 'src/infra/repositories/album.repository'; -import { ApiKeyRepository } from 'src/infra/repositories/api-key.repository'; -import { AssetRepository } from 'src/infra/repositories/asset.repository'; -import { AuditRepository } from 'src/infra/repositories/audit.repository'; -import { LibraryRepository } from 'src/infra/repositories/library.repository'; -import { MoveRepository } from 'src/infra/repositories/move.repository'; -import { PartnerRepository } from 'src/infra/repositories/partner.repository'; -import { PersonRepository } from 'src/infra/repositories/person.repository'; -import { SearchRepository } from 'src/infra/repositories/search.repository'; -import { SharedLinkRepository } from 'src/infra/repositories/shared-link.repository'; -import { SystemConfigRepository } from 'src/infra/repositories/system-config.repository'; -import { SystemMetadataRepository } from 'src/infra/repositories/system-metadata.repository'; -import { TagRepository } from 'src/infra/repositories/tag.repository'; -import { UserTokenRepository } from 'src/infra/repositories/user-token.repository'; -import { UserRepository } from 'src/infra/repositories/user.repository'; import { SqlLogger } from 'src/infra/sql-generator/sql.logger'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { AccessRepository } from 'src/repositories/access.repository'; +import { AlbumRepository } from 'src/repositories/album.repository'; +import { ApiKeyRepository } from 'src/repositories/api-key.repository'; +import { AssetRepository } from 'src/repositories/asset.repository'; +import { AuditRepository } from 'src/repositories/audit.repository'; +import { LibraryRepository } from 'src/repositories/library.repository'; +import { MoveRepository } from 'src/repositories/move.repository'; +import { PartnerRepository } from 'src/repositories/partner.repository'; +import { PersonRepository } from 'src/repositories/person.repository'; +import { SearchRepository } from 'src/repositories/search.repository'; +import { SharedLinkRepository } from 'src/repositories/shared-link.repository'; +import { SystemConfigRepository } from 'src/repositories/system-config.repository'; +import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository'; +import { TagRepository } from 'src/repositories/tag.repository'; +import { UserTokenRepository } from 'src/repositories/user-token.repository'; +import { UserRepository } from 'src/repositories/user.repository'; const reflector = new Reflector(); const repositories = [ diff --git a/server/src/interfaces/activity.repository.ts b/server/src/interfaces/activity.repository.ts index 39eb5da6b..5e7b4d2c7 100644 --- a/server/src/interfaces/activity.repository.ts +++ b/server/src/interfaces/activity.repository.ts @@ -1,5 +1,5 @@ -import { ActivityEntity } from 'src/infra/entities/activity.entity'; -import { ActivitySearch } from 'src/infra/repositories/activity.repository'; +import { ActivityEntity } from 'src/entities/activity.entity'; +import { ActivitySearch } from 'src/repositories/activity.repository'; export const IActivityRepository = 'IActivityRepository'; diff --git a/server/src/interfaces/album.repository.ts b/server/src/interfaces/album.repository.ts index 213309412..230e94e2a 100644 --- a/server/src/interfaces/album.repository.ts +++ b/server/src/interfaces/album.repository.ts @@ -1,4 +1,4 @@ -import { AlbumEntity } from 'src/infra/entities/album.entity'; +import { AlbumEntity } from 'src/entities/album.entity'; export const IAlbumRepository = 'IAlbumRepository'; diff --git a/server/src/interfaces/api-key.repository.ts b/server/src/interfaces/api-key.repository.ts index ff6d97dd5..731b7ff6f 100644 --- a/server/src/interfaces/api-key.repository.ts +++ b/server/src/interfaces/api-key.repository.ts @@ -1,4 +1,4 @@ -import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { APIKeyEntity } from 'src/entities/api-key.entity'; export const IKeyRepository = 'IKeyRepository'; diff --git a/server/src/interfaces/asset-stack.repository.ts b/server/src/interfaces/asset-stack.repository.ts index 32c45b0d1..1e037d38e 100644 --- a/server/src/interfaces/asset-stack.repository.ts +++ b/server/src/interfaces/asset-stack.repository.ts @@ -1,4 +1,4 @@ -import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; +import { AssetStackEntity } from 'src/entities/asset-stack.entity'; export const IAssetStackRepository = 'IAssetStackRepository'; diff --git a/server/src/interfaces/asset.repository.ts b/server/src/interfaces/asset.repository.ts index a362d2349..9bca4a6df 100644 --- a/server/src/interfaces/asset.repository.ts +++ b/server/src/interfaces/asset.repository.ts @@ -1,7 +1,7 @@ -import { AssetOrder } from 'src/infra/entities/album.entity'; -import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { AssetOrder } from 'src/entities/album.entity'; +import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; import { ReverseGeocodeResult } from 'src/interfaces/metadata.repository'; import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.repository'; import { Paginated, PaginationOptions } from 'src/utils'; diff --git a/server/src/interfaces/audit.repository.ts b/server/src/interfaces/audit.repository.ts index 36112bfb8..767a4bc2f 100644 --- a/server/src/interfaces/audit.repository.ts +++ b/server/src/interfaces/audit.repository.ts @@ -1,4 +1,4 @@ -import { AuditEntity, DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; +import { AuditEntity, DatabaseAction, EntityType } from 'src/entities/audit.entity'; export const IAuditRepository = 'IAuditRepository'; diff --git a/server/src/interfaces/communication.repository.ts b/server/src/interfaces/communication.repository.ts index 38315a9bb..870c0d937 100644 --- a/server/src/interfaces/communication.repository.ts +++ b/server/src/interfaces/communication.repository.ts @@ -1,6 +1,6 @@ import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; import { ReleaseNotification, ServerVersionResponseDto } from 'src/domain/server-info/server-info.dto'; -import { SystemConfig } from 'src/infra/entities/system-config.entity'; +import { SystemConfig } from 'src/entities/system-config.entity'; export const ICommunicationRepository = 'ICommunicationRepository'; diff --git a/server/src/interfaces/library.repository.ts b/server/src/interfaces/library.repository.ts index 39b94f87c..5638d6024 100644 --- a/server/src/interfaces/library.repository.ts +++ b/server/src/interfaces/library.repository.ts @@ -1,5 +1,5 @@ import { LibraryStatsResponseDto } from 'src/domain/library/library.dto'; -import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; export const ILibraryRepository = 'ILibraryRepository'; diff --git a/server/src/interfaces/media.repository.ts b/server/src/interfaces/media.repository.ts index 09bcd7eef..0e34227d3 100644 --- a/server/src/interfaces/media.repository.ts +++ b/server/src/interfaces/media.repository.ts @@ -1,5 +1,5 @@ import { Writable } from 'node:stream'; -import { TranscodeTarget, VideoCodec } from 'src/infra/entities/system-config.entity'; +import { TranscodeTarget, VideoCodec } from 'src/entities/system-config.entity'; export const IMediaRepository = 'IMediaRepository'; diff --git a/server/src/interfaces/move.repository.ts b/server/src/interfaces/move.repository.ts index eb191021f..c9d39e78c 100644 --- a/server/src/interfaces/move.repository.ts +++ b/server/src/interfaces/move.repository.ts @@ -1,4 +1,4 @@ -import { MoveEntity, PathType } from 'src/infra/entities/move.entity'; +import { MoveEntity, PathType } from 'src/entities/move.entity'; export const IMoveRepository = 'IMoveRepository'; diff --git a/server/src/interfaces/partner.repository.ts b/server/src/interfaces/partner.repository.ts index 5606fc495..842745a51 100644 --- a/server/src/interfaces/partner.repository.ts +++ b/server/src/interfaces/partner.repository.ts @@ -1,4 +1,4 @@ -import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { PartnerEntity } from 'src/entities/partner.entity'; export interface PartnerIds { sharedById: string; diff --git a/server/src/interfaces/person.repository.ts b/server/src/interfaces/person.repository.ts index f00fce44e..cba11fbb9 100644 --- a/server/src/interfaces/person.repository.ts +++ b/server/src/interfaces/person.repository.ts @@ -1,6 +1,6 @@ -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { PersonEntity } from 'src/entities/person.entity'; import { Paginated, PaginationOptions } from 'src/utils'; import { FindManyOptions, FindOptionsRelations, FindOptionsSelect } from 'typeorm'; diff --git a/server/src/interfaces/search.repository.ts b/server/src/interfaces/search.repository.ts index a54147f1f..29eaa32b7 100644 --- a/server/src/interfaces/search.repository.ts +++ b/server/src/interfaces/search.repository.ts @@ -1,7 +1,7 @@ -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; -import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; +import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { Paginated } from 'src/utils'; export const ISearchRepository = 'ISearchRepository'; diff --git a/server/src/interfaces/shared-link.repository.ts b/server/src/interfaces/shared-link.repository.ts index 0d5e8eca7..fe08a6294 100644 --- a/server/src/interfaces/shared-link.repository.ts +++ b/server/src/interfaces/shared-link.repository.ts @@ -1,4 +1,4 @@ -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; export const ISharedLinkRepository = 'ISharedLinkRepository'; diff --git a/server/src/interfaces/system-config.repository.ts b/server/src/interfaces/system-config.repository.ts index 86b311485..f591a6671 100644 --- a/server/src/interfaces/system-config.repository.ts +++ b/server/src/interfaces/system-config.repository.ts @@ -1,4 +1,4 @@ -import { SystemConfigEntity } from 'src/infra/entities/system-config.entity'; +import { SystemConfigEntity } from 'src/entities/system-config.entity'; export const ISystemConfigRepository = 'ISystemConfigRepository'; diff --git a/server/src/interfaces/system-metadata.repository.ts b/server/src/interfaces/system-metadata.repository.ts index d28713226..cbbce44e2 100644 --- a/server/src/interfaces/system-metadata.repository.ts +++ b/server/src/interfaces/system-metadata.repository.ts @@ -1,4 +1,4 @@ -import { SystemMetadata } from 'src/infra/entities/system-metadata.entity'; +import { SystemMetadata } from 'src/entities/system-metadata.entity'; export const ISystemMetadataRepository = 'ISystemMetadataRepository'; diff --git a/server/src/interfaces/tag.repository.ts b/server/src/interfaces/tag.repository.ts index 47c3f40fa..8071461df 100644 --- a/server/src/interfaces/tag.repository.ts +++ b/server/src/interfaces/tag.repository.ts @@ -1,5 +1,5 @@ -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { TagEntity } from 'src/infra/entities/tag.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { TagEntity } from 'src/entities/tag.entity'; export const ITagRepository = 'ITagRepository'; diff --git a/server/src/interfaces/user-token.repository.ts b/server/src/interfaces/user-token.repository.ts index 2d342a2fc..0fcec39fd 100644 --- a/server/src/interfaces/user-token.repository.ts +++ b/server/src/interfaces/user-token.repository.ts @@ -1,4 +1,4 @@ -import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { UserTokenEntity } from 'src/entities/user-token.entity'; export const IUserTokenRepository = 'IUserTokenRepository'; diff --git a/server/src/interfaces/user.repository.ts b/server/src/interfaces/user.repository.ts index be5ef165d..ebc70688e 100644 --- a/server/src/interfaces/user.repository.ts +++ b/server/src/interfaces/user.repository.ts @@ -1,4 +1,4 @@ -import { UserEntity } from 'src/infra/entities/user.entity'; +import { UserEntity } from 'src/entities/user.entity'; export interface UserListFilter { withDeleted?: boolean; diff --git a/server/src/infra/migrations/1645130759468-CreateUserTable.ts b/server/src/migrations/1645130759468-CreateUserTable.ts similarity index 100% rename from server/src/infra/migrations/1645130759468-CreateUserTable.ts rename to server/src/migrations/1645130759468-CreateUserTable.ts diff --git a/server/src/infra/migrations/1645130777674-CreateDeviceInfoTable.ts b/server/src/migrations/1645130777674-CreateDeviceInfoTable.ts similarity index 100% rename from server/src/infra/migrations/1645130777674-CreateDeviceInfoTable.ts rename to server/src/migrations/1645130777674-CreateDeviceInfoTable.ts diff --git a/server/src/infra/migrations/1645130805273-CreateAssetsTable.ts b/server/src/migrations/1645130805273-CreateAssetsTable.ts similarity index 100% rename from server/src/infra/migrations/1645130805273-CreateAssetsTable.ts rename to server/src/migrations/1645130805273-CreateAssetsTable.ts diff --git a/server/src/infra/migrations/1645130817965-CreateExifTable.ts b/server/src/migrations/1645130817965-CreateExifTable.ts similarity index 100% rename from server/src/infra/migrations/1645130817965-CreateExifTable.ts rename to server/src/migrations/1645130817965-CreateExifTable.ts diff --git a/server/src/infra/migrations/1645130870184-CreateSmartInfoTable.ts b/server/src/migrations/1645130870184-CreateSmartInfoTable.ts similarity index 100% rename from server/src/infra/migrations/1645130870184-CreateSmartInfoTable.ts rename to server/src/migrations/1645130870184-CreateSmartInfoTable.ts diff --git a/server/src/infra/migrations/1646249209023-AddExifTextSearchColumn.ts b/server/src/migrations/1646249209023-AddExifTextSearchColumn.ts similarity index 100% rename from server/src/infra/migrations/1646249209023-AddExifTextSearchColumn.ts rename to server/src/migrations/1646249209023-AddExifTextSearchColumn.ts diff --git a/server/src/infra/migrations/1646249734844-CreateExifTextSearchIndex.ts b/server/src/migrations/1646249734844-CreateExifTextSearchIndex.ts similarity index 100% rename from server/src/infra/migrations/1646249734844-CreateExifTextSearchIndex.ts rename to server/src/migrations/1646249734844-CreateExifTextSearchIndex.ts diff --git a/server/src/infra/migrations/1646709533213-AddRegionCityToExIf.ts b/server/src/migrations/1646709533213-AddRegionCityToExIf.ts similarity index 100% rename from server/src/infra/migrations/1646709533213-AddRegionCityToExIf.ts rename to server/src/migrations/1646709533213-AddRegionCityToExIf.ts diff --git a/server/src/infra/migrations/1646710459852-AddLocationToExifTextSearch.ts b/server/src/migrations/1646710459852-AddLocationToExifTextSearch.ts similarity index 100% rename from server/src/infra/migrations/1646710459852-AddLocationToExifTextSearch.ts rename to server/src/migrations/1646710459852-AddLocationToExifTextSearch.ts diff --git a/server/src/infra/migrations/1648317474768-AddObjectColumnToSmartInfo.ts b/server/src/migrations/1648317474768-AddObjectColumnToSmartInfo.ts similarity index 100% rename from server/src/infra/migrations/1648317474768-AddObjectColumnToSmartInfo.ts rename to server/src/migrations/1648317474768-AddObjectColumnToSmartInfo.ts diff --git a/server/src/infra/migrations/1649643216111-CreateSharedAlbumAndRelatedTables.ts b/server/src/migrations/1649643216111-CreateSharedAlbumAndRelatedTables.ts similarity index 100% rename from server/src/infra/migrations/1649643216111-CreateSharedAlbumAndRelatedTables.ts rename to server/src/migrations/1649643216111-CreateSharedAlbumAndRelatedTables.ts diff --git a/server/src/infra/migrations/1652633525943-UpdateUserTableWithAdminAndName.ts b/server/src/migrations/1652633525943-UpdateUserTableWithAdminAndName.ts similarity index 100% rename from server/src/infra/migrations/1652633525943-UpdateUserTableWithAdminAndName.ts rename to server/src/migrations/1652633525943-UpdateUserTableWithAdminAndName.ts diff --git a/server/src/infra/migrations/1653214255670-UpdateAssetTableWithWebpPath.ts b/server/src/migrations/1653214255670-UpdateAssetTableWithWebpPath.ts similarity index 100% rename from server/src/infra/migrations/1653214255670-UpdateAssetTableWithWebpPath.ts rename to server/src/migrations/1653214255670-UpdateAssetTableWithWebpPath.ts diff --git a/server/src/infra/migrations/1654299904583-UpdateAssetTableWithEncodeVideoPath.ts b/server/src/migrations/1654299904583-UpdateAssetTableWithEncodeVideoPath.ts similarity index 100% rename from server/src/infra/migrations/1654299904583-UpdateAssetTableWithEncodeVideoPath.ts rename to server/src/migrations/1654299904583-UpdateAssetTableWithEncodeVideoPath.ts diff --git a/server/src/infra/migrations/1655401127251-RenameSharedAlbums.ts b/server/src/migrations/1655401127251-RenameSharedAlbums.ts similarity index 100% rename from server/src/infra/migrations/1655401127251-RenameSharedAlbums.ts rename to server/src/migrations/1655401127251-RenameSharedAlbums.ts diff --git a/server/src/infra/migrations/1656338626260-RenameIsFirstLoggedInColumn.ts b/server/src/migrations/1656338626260-RenameIsFirstLoggedInColumn.ts similarity index 100% rename from server/src/infra/migrations/1656338626260-RenameIsFirstLoggedInColumn.ts rename to server/src/migrations/1656338626260-RenameIsFirstLoggedInColumn.ts diff --git a/server/src/infra/migrations/1656888591977-RenameAssetAlbumIdSequence.ts b/server/src/migrations/1656888591977-RenameAssetAlbumIdSequence.ts similarity index 100% rename from server/src/infra/migrations/1656888591977-RenameAssetAlbumIdSequence.ts rename to server/src/migrations/1656888591977-RenameAssetAlbumIdSequence.ts diff --git a/server/src/infra/migrations/1656888918620-DropExifTextSearchableColumn.ts b/server/src/migrations/1656888918620-DropExifTextSearchableColumn.ts similarity index 100% rename from server/src/infra/migrations/1656888918620-DropExifTextSearchableColumn.ts rename to server/src/migrations/1656888918620-DropExifTextSearchableColumn.ts diff --git a/server/src/infra/migrations/1656889061566-MatchMigrationsWithTypeORMEntities.ts b/server/src/migrations/1656889061566-MatchMigrationsWithTypeORMEntities.ts similarity index 100% rename from server/src/infra/migrations/1656889061566-MatchMigrationsWithTypeORMEntities.ts rename to server/src/migrations/1656889061566-MatchMigrationsWithTypeORMEntities.ts diff --git a/server/src/infra/migrations/1658860470248-AddExifImageNameAsSearchableText.ts b/server/src/migrations/1658860470248-AddExifImageNameAsSearchableText.ts similarity index 100% rename from server/src/infra/migrations/1658860470248-AddExifImageNameAsSearchableText.ts rename to server/src/migrations/1658860470248-AddExifImageNameAsSearchableText.ts diff --git a/server/src/infra/migrations/1661011331242-AddCaption.ts b/server/src/migrations/1661011331242-AddCaption.ts similarity index 100% rename from server/src/infra/migrations/1661011331242-AddCaption.ts rename to server/src/migrations/1661011331242-AddCaption.ts diff --git a/server/src/infra/migrations/1661528919411-ChangeExifFileSizeInByteToBigInt.ts b/server/src/migrations/1661528919411-ChangeExifFileSizeInByteToBigInt.ts similarity index 100% rename from server/src/infra/migrations/1661528919411-ChangeExifFileSizeInByteToBigInt.ts rename to server/src/migrations/1661528919411-ChangeExifFileSizeInByteToBigInt.ts diff --git a/server/src/infra/migrations/1661881837496-AddAssetChecksum.ts b/server/src/migrations/1661881837496-AddAssetChecksum.ts similarity index 100% rename from server/src/infra/migrations/1661881837496-AddAssetChecksum.ts rename to server/src/migrations/1661881837496-AddAssetChecksum.ts diff --git a/server/src/infra/migrations/1661971370662-UpdateAssetTableWithNewUniqueConstraint.ts b/server/src/migrations/1661971370662-UpdateAssetTableWithNewUniqueConstraint.ts similarity index 100% rename from server/src/infra/migrations/1661971370662-UpdateAssetTableWithNewUniqueConstraint.ts rename to server/src/migrations/1661971370662-UpdateAssetTableWithNewUniqueConstraint.ts diff --git a/server/src/infra/migrations/1662427365521-FixTimestampDataTypeInAssetTable.ts b/server/src/migrations/1662427365521-FixTimestampDataTypeInAssetTable.ts similarity index 100% rename from server/src/infra/migrations/1662427365521-FixTimestampDataTypeInAssetTable.ts rename to server/src/migrations/1662427365521-FixTimestampDataTypeInAssetTable.ts diff --git a/server/src/infra/migrations/1665540663419-CreateSystemConfigTable.ts b/server/src/migrations/1665540663419-CreateSystemConfigTable.ts similarity index 100% rename from server/src/infra/migrations/1665540663419-CreateSystemConfigTable.ts rename to server/src/migrations/1665540663419-CreateSystemConfigTable.ts diff --git a/server/src/infra/migrations/1667762360744-AddingDeletedAtColumnInUserEntity.ts b/server/src/migrations/1667762360744-AddingDeletedAtColumnInUserEntity.ts similarity index 100% rename from server/src/infra/migrations/1667762360744-AddingDeletedAtColumnInUserEntity.ts rename to server/src/migrations/1667762360744-AddingDeletedAtColumnInUserEntity.ts diff --git a/server/src/infra/migrations/1668383120461-AddLivePhotosRelatedColumnToAssetTable.ts b/server/src/migrations/1668383120461-AddLivePhotosRelatedColumnToAssetTable.ts similarity index 100% rename from server/src/infra/migrations/1668383120461-AddLivePhotosRelatedColumnToAssetTable.ts rename to server/src/migrations/1668383120461-AddLivePhotosRelatedColumnToAssetTable.ts diff --git a/server/src/infra/migrations/1668835311083-UpdateUserTableForOIDC.ts b/server/src/migrations/1668835311083-UpdateUserTableForOIDC.ts similarity index 100% rename from server/src/infra/migrations/1668835311083-UpdateUserTableForOIDC.ts rename to server/src/migrations/1668835311083-UpdateUserTableForOIDC.ts diff --git a/server/src/infra/migrations/1670104716264-OAuthId.ts b/server/src/migrations/1670104716264-OAuthId.ts similarity index 100% rename from server/src/infra/migrations/1670104716264-OAuthId.ts rename to server/src/migrations/1670104716264-OAuthId.ts diff --git a/server/src/infra/migrations/1670257571385-CreateTagsTable.ts b/server/src/migrations/1670257571385-CreateTagsTable.ts similarity index 100% rename from server/src/infra/migrations/1670257571385-CreateTagsTable.ts rename to server/src/migrations/1670257571385-CreateTagsTable.ts diff --git a/server/src/infra/migrations/1670607437008-TruncateOldConfigItems.ts b/server/src/migrations/1670607437008-TruncateOldConfigItems.ts similarity index 100% rename from server/src/infra/migrations/1670607437008-TruncateOldConfigItems.ts rename to server/src/migrations/1670607437008-TruncateOldConfigItems.ts diff --git a/server/src/infra/migrations/1670633210032-AddUserEmailUniqueConstraint.ts b/server/src/migrations/1670633210032-AddUserEmailUniqueConstraint.ts similarity index 100% rename from server/src/infra/migrations/1670633210032-AddUserEmailUniqueConstraint.ts rename to server/src/migrations/1670633210032-AddUserEmailUniqueConstraint.ts diff --git a/server/src/infra/migrations/1672109862870-DropSaltColumn.ts b/server/src/migrations/1672109862870-DropSaltColumn.ts similarity index 100% rename from server/src/infra/migrations/1672109862870-DropSaltColumn.ts rename to server/src/migrations/1672109862870-DropSaltColumn.ts diff --git a/server/src/infra/migrations/1672502270115-AddAPIKeys.ts b/server/src/migrations/1672502270115-AddAPIKeys.ts similarity index 100% rename from server/src/infra/migrations/1672502270115-AddAPIKeys.ts rename to server/src/migrations/1672502270115-AddAPIKeys.ts diff --git a/server/src/infra/migrations/1673150490490-AddSharedLinkTable.ts b/server/src/migrations/1673150490490-AddSharedLinkTable.ts similarity index 100% rename from server/src/infra/migrations/1673150490490-AddSharedLinkTable.ts rename to server/src/migrations/1673150490490-AddSharedLinkTable.ts diff --git a/server/src/infra/migrations/1673907194740-AddMorePermissionToSharedLink.ts b/server/src/migrations/1673907194740-AddMorePermissionToSharedLink.ts similarity index 100% rename from server/src/infra/migrations/1673907194740-AddMorePermissionToSharedLink.ts rename to server/src/migrations/1673907194740-AddMorePermissionToSharedLink.ts diff --git a/server/src/infra/migrations/1674263302005-RemoveVideoCodecConfigOption.ts b/server/src/migrations/1674263302005-RemoveVideoCodecConfigOption.ts similarity index 100% rename from server/src/infra/migrations/1674263302005-RemoveVideoCodecConfigOption.ts rename to server/src/migrations/1674263302005-RemoveVideoCodecConfigOption.ts diff --git a/server/src/infra/migrations/1674342044239-CreateUserTokenEntity.ts b/server/src/migrations/1674342044239-CreateUserTokenEntity.ts similarity index 100% rename from server/src/infra/migrations/1674342044239-CreateUserTokenEntity.ts rename to server/src/migrations/1674342044239-CreateUserTokenEntity.ts diff --git a/server/src/infra/migrations/1674757936889-AlterExifExposureTimeToString.ts b/server/src/migrations/1674757936889-AlterExifExposureTimeToString.ts similarity index 100% rename from server/src/infra/migrations/1674757936889-AlterExifExposureTimeToString.ts rename to server/src/migrations/1674757936889-AlterExifExposureTimeToString.ts diff --git a/server/src/infra/migrations/1674774248319-TruncateAPIKeys.ts b/server/src/migrations/1674774248319-TruncateAPIKeys.ts similarity index 100% rename from server/src/infra/migrations/1674774248319-TruncateAPIKeys.ts rename to server/src/migrations/1674774248319-TruncateAPIKeys.ts diff --git a/server/src/infra/migrations/1674939383309-AddSharedLinkUserForeignKeyConstraint.ts b/server/src/migrations/1674939383309-AddSharedLinkUserForeignKeyConstraint.ts similarity index 100% rename from server/src/infra/migrations/1674939383309-AddSharedLinkUserForeignKeyConstraint.ts rename to server/src/migrations/1674939383309-AddSharedLinkUserForeignKeyConstraint.ts diff --git a/server/src/infra/migrations/1675667878312-AddUpdatedAtColumnToAlbumsUsersAssets.ts b/server/src/migrations/1675667878312-AddUpdatedAtColumnToAlbumsUsersAssets.ts similarity index 100% rename from server/src/infra/migrations/1675667878312-AddUpdatedAtColumnToAlbumsUsersAssets.ts rename to server/src/migrations/1675667878312-AddUpdatedAtColumnToAlbumsUsersAssets.ts diff --git a/server/src/infra/migrations/1675701909594-AddAlbumUserForeignKeyConstraint.ts b/server/src/migrations/1675701909594-AddAlbumUserForeignKeyConstraint.ts similarity index 100% rename from server/src/infra/migrations/1675701909594-AddAlbumUserForeignKeyConstraint.ts rename to server/src/migrations/1675701909594-AddAlbumUserForeignKeyConstraint.ts diff --git a/server/src/infra/migrations/1675808874445-APIKeyUUIDPrimaryKey.ts b/server/src/migrations/1675808874445-APIKeyUUIDPrimaryKey.ts similarity index 100% rename from server/src/infra/migrations/1675808874445-APIKeyUUIDPrimaryKey.ts rename to server/src/migrations/1675808874445-APIKeyUUIDPrimaryKey.ts diff --git a/server/src/infra/migrations/1675812532822-FixAlbumEntityTypeORM.ts b/server/src/migrations/1675812532822-FixAlbumEntityTypeORM.ts similarity index 100% rename from server/src/infra/migrations/1675812532822-FixAlbumEntityTypeORM.ts rename to server/src/migrations/1675812532822-FixAlbumEntityTypeORM.ts diff --git a/server/src/infra/migrations/1676437878377-AppleContentIdentifier.ts b/server/src/migrations/1676437878377-AppleContentIdentifier.ts similarity index 100% rename from server/src/infra/migrations/1676437878377-AppleContentIdentifier.ts rename to server/src/migrations/1676437878377-AppleContentIdentifier.ts diff --git a/server/src/infra/migrations/1676680127415-FixAssetRelations.ts b/server/src/migrations/1676680127415-FixAssetRelations.ts similarity index 100% rename from server/src/infra/migrations/1676680127415-FixAssetRelations.ts rename to server/src/migrations/1676680127415-FixAssetRelations.ts diff --git a/server/src/infra/migrations/1676721296440-AssetCreatedAtField.ts b/server/src/migrations/1676721296440-AssetCreatedAtField.ts similarity index 100% rename from server/src/infra/migrations/1676721296440-AssetCreatedAtField.ts rename to server/src/migrations/1676721296440-AssetCreatedAtField.ts diff --git a/server/src/infra/migrations/1676848629119-ExifEntityDefinitionFixes.ts b/server/src/migrations/1676848629119-ExifEntityDefinitionFixes.ts similarity index 100% rename from server/src/infra/migrations/1676848629119-ExifEntityDefinitionFixes.ts rename to server/src/migrations/1676848629119-ExifEntityDefinitionFixes.ts diff --git a/server/src/infra/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts b/server/src/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts similarity index 100% rename from server/src/infra/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts rename to server/src/migrations/1676848694786-SharedLinkEntityDefinitionFixes.ts diff --git a/server/src/infra/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts b/server/src/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts similarity index 100% rename from server/src/infra/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts rename to server/src/migrations/1676852143506-SmartInfoEntityDefinitionFixes.ts diff --git a/server/src/infra/migrations/1677497925328-AddExifTimeZone.ts b/server/src/migrations/1677497925328-AddExifTimeZone.ts similarity index 100% rename from server/src/infra/migrations/1677497925328-AddExifTimeZone.ts rename to server/src/migrations/1677497925328-AddExifTimeZone.ts diff --git a/server/src/infra/migrations/1677535643119-AddIndexForAlbumInSharedLinkTable.ts b/server/src/migrations/1677535643119-AddIndexForAlbumInSharedLinkTable.ts similarity index 100% rename from server/src/infra/migrations/1677535643119-AddIndexForAlbumInSharedLinkTable.ts rename to server/src/migrations/1677535643119-AddIndexForAlbumInSharedLinkTable.ts diff --git a/server/src/infra/migrations/1677613712565-AlbumThumbnailRelation.ts b/server/src/migrations/1677613712565-AlbumThumbnailRelation.ts similarity index 100% rename from server/src/infra/migrations/1677613712565-AlbumThumbnailRelation.ts rename to server/src/migrations/1677613712565-AlbumThumbnailRelation.ts diff --git a/server/src/infra/migrations/1677971458822-AddCLIPEncodeDataColumn.ts b/server/src/migrations/1677971458822-AddCLIPEncodeDataColumn.ts similarity index 100% rename from server/src/infra/migrations/1677971458822-AddCLIPEncodeDataColumn.ts rename to server/src/migrations/1677971458822-AddCLIPEncodeDataColumn.ts diff --git a/server/src/infra/migrations/1679751316282-UpdateTranscodeOption.ts b/server/src/migrations/1679751316282-UpdateTranscodeOption.ts similarity index 100% rename from server/src/infra/migrations/1679751316282-UpdateTranscodeOption.ts rename to server/src/migrations/1679751316282-UpdateTranscodeOption.ts diff --git a/server/src/infra/migrations/1679901204458-ClipEmbeddingFloat4.ts b/server/src/migrations/1679901204458-ClipEmbeddingFloat4.ts similarity index 100% rename from server/src/infra/migrations/1679901204458-ClipEmbeddingFloat4.ts rename to server/src/migrations/1679901204458-ClipEmbeddingFloat4.ts diff --git a/server/src/infra/migrations/1680632845740-AddIsArchivedColumn.ts b/server/src/migrations/1680632845740-AddIsArchivedColumn.ts similarity index 100% rename from server/src/infra/migrations/1680632845740-AddIsArchivedColumn.ts rename to server/src/migrations/1680632845740-AddIsArchivedColumn.ts diff --git a/server/src/infra/migrations/1680694465853-RemoveRedundantConstraints.ts b/server/src/migrations/1680694465853-RemoveRedundantConstraints.ts similarity index 100% rename from server/src/infra/migrations/1680694465853-RemoveRedundantConstraints.ts rename to server/src/migrations/1680694465853-RemoveRedundantConstraints.ts diff --git a/server/src/infra/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts b/server/src/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts similarity index 100% rename from server/src/infra/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts rename to server/src/migrations/1681144628393-AddOriginalFileNameToAssetTable.ts diff --git a/server/src/infra/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts b/server/src/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts similarity index 100% rename from server/src/infra/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts rename to server/src/migrations/1681159594469-RemoveImageNameFromEXIFTable.ts diff --git a/server/src/infra/migrations/1682371561743-FixNullableRelations.ts b/server/src/migrations/1682371561743-FixNullableRelations.ts similarity index 100% rename from server/src/infra/migrations/1682371561743-FixNullableRelations.ts rename to server/src/migrations/1682371561743-FixNullableRelations.ts diff --git a/server/src/infra/migrations/1682371791038-AddDeviceInfoToUserToken.ts b/server/src/migrations/1682371791038-AddDeviceInfoToUserToken.ts similarity index 100% rename from server/src/infra/migrations/1682371791038-AddDeviceInfoToUserToken.ts rename to server/src/migrations/1682371791038-AddDeviceInfoToUserToken.ts diff --git a/server/src/infra/migrations/1682710252424-DropDeviceInfoTable.ts b/server/src/migrations/1682710252424-DropDeviceInfoTable.ts similarity index 100% rename from server/src/infra/migrations/1682710252424-DropDeviceInfoTable.ts rename to server/src/migrations/1682710252424-DropDeviceInfoTable.ts diff --git a/server/src/infra/migrations/1683808254676-AddPartnersTable.ts b/server/src/migrations/1683808254676-AddPartnersTable.ts similarity index 100% rename from server/src/infra/migrations/1683808254676-AddPartnersTable.ts rename to server/src/migrations/1683808254676-AddPartnersTable.ts diff --git a/server/src/infra/migrations/1684255168091-AddFacialTables.ts b/server/src/migrations/1684255168091-AddFacialTables.ts similarity index 100% rename from server/src/infra/migrations/1684255168091-AddFacialTables.ts rename to server/src/migrations/1684255168091-AddFacialTables.ts diff --git a/server/src/infra/migrations/1684273840676-AddSidecarFile.ts b/server/src/migrations/1684273840676-AddSidecarFile.ts similarity index 100% rename from server/src/infra/migrations/1684273840676-AddSidecarFile.ts rename to server/src/migrations/1684273840676-AddSidecarFile.ts diff --git a/server/src/infra/migrations/1684328185099-RequireChecksumNotNull.ts b/server/src/migrations/1684328185099-RequireChecksumNotNull.ts similarity index 100% rename from server/src/infra/migrations/1684328185099-RequireChecksumNotNull.ts rename to server/src/migrations/1684328185099-RequireChecksumNotNull.ts diff --git a/server/src/infra/migrations/1684410565398-AddStorageLabel.ts b/server/src/migrations/1684410565398-AddStorageLabel.ts similarity index 100% rename from server/src/infra/migrations/1684410565398-AddStorageLabel.ts rename to server/src/migrations/1684410565398-AddStorageLabel.ts diff --git a/server/src/infra/migrations/1684867360825-AddUserTokenAndAPIKeyCascades.ts b/server/src/migrations/1684867360825-AddUserTokenAndAPIKeyCascades.ts similarity index 100% rename from server/src/infra/migrations/1684867360825-AddUserTokenAndAPIKeyCascades.ts rename to server/src/migrations/1684867360825-AddUserTokenAndAPIKeyCascades.ts diff --git a/server/src/infra/migrations/1685044328272-AddSharedLinkCascade.ts b/server/src/migrations/1685044328272-AddSharedLinkCascade.ts similarity index 100% rename from server/src/infra/migrations/1685044328272-AddSharedLinkCascade.ts rename to server/src/migrations/1685044328272-AddSharedLinkCascade.ts diff --git a/server/src/infra/migrations/1685370430343-UserDatesTimestamptz.ts b/server/src/migrations/1685370430343-UserDatesTimestamptz.ts similarity index 100% rename from server/src/infra/migrations/1685370430343-UserDatesTimestamptz.ts rename to server/src/migrations/1685370430343-UserDatesTimestamptz.ts diff --git a/server/src/infra/migrations/1685731372040-RemoveInvalidCoordinates.ts b/server/src/migrations/1685731372040-RemoveInvalidCoordinates.ts similarity index 100% rename from server/src/infra/migrations/1685731372040-RemoveInvalidCoordinates.ts rename to server/src/migrations/1685731372040-RemoveInvalidCoordinates.ts diff --git a/server/src/infra/migrations/1686584273471-ImportAsset.ts b/server/src/migrations/1686584273471-ImportAsset.ts similarity index 100% rename from server/src/infra/migrations/1686584273471-ImportAsset.ts rename to server/src/migrations/1686584273471-ImportAsset.ts diff --git a/server/src/infra/migrations/1686762895180-AddThumbhashColumn.ts b/server/src/migrations/1686762895180-AddThumbhashColumn.ts similarity index 100% rename from server/src/infra/migrations/1686762895180-AddThumbhashColumn.ts rename to server/src/migrations/1686762895180-AddThumbhashColumn.ts diff --git a/server/src/infra/migrations/1688241394489-AddDetectFaceResultInfo.ts b/server/src/migrations/1688241394489-AddDetectFaceResultInfo.ts similarity index 100% rename from server/src/infra/migrations/1688241394489-AddDetectFaceResultInfo.ts rename to server/src/migrations/1688241394489-AddDetectFaceResultInfo.ts diff --git a/server/src/infra/migrations/1688392120838-AddLibraryTable.ts b/server/src/migrations/1688392120838-AddLibraryTable.ts similarity index 100% rename from server/src/infra/migrations/1688392120838-AddLibraryTable.ts rename to server/src/migrations/1688392120838-AddLibraryTable.ts diff --git a/server/src/infra/migrations/1689001889950-DropMimeTypeColumn.ts b/server/src/migrations/1689001889950-DropMimeTypeColumn.ts similarity index 100% rename from server/src/infra/migrations/1689001889950-DropMimeTypeColumn.ts rename to server/src/migrations/1689001889950-DropMimeTypeColumn.ts diff --git a/server/src/infra/migrations/1689281196844-AddHiddenFaces.ts b/server/src/migrations/1689281196844-AddHiddenFaces.ts similarity index 100% rename from server/src/infra/migrations/1689281196844-AddHiddenFaces.ts rename to server/src/migrations/1689281196844-AddHiddenFaces.ts diff --git a/server/src/infra/migrations/1690469489288-Panoramas.ts b/server/src/migrations/1690469489288-Panoramas.ts similarity index 100% rename from server/src/infra/migrations/1690469489288-Panoramas.ts rename to server/src/migrations/1690469489288-Panoramas.ts diff --git a/server/src/infra/migrations/1691209138541-AddAlbumDescription.ts b/server/src/migrations/1691209138541-AddAlbumDescription.ts similarity index 100% rename from server/src/infra/migrations/1691209138541-AddAlbumDescription.ts rename to server/src/migrations/1691209138541-AddAlbumDescription.ts diff --git a/server/src/infra/migrations/1691600216749-UserMemoryPreference.ts b/server/src/migrations/1691600216749-UserMemoryPreference.ts similarity index 100% rename from server/src/infra/migrations/1691600216749-UserMemoryPreference.ts rename to server/src/migrations/1691600216749-UserMemoryPreference.ts diff --git a/server/src/infra/migrations/1692057328660-fixGPSNullIsland.ts b/server/src/migrations/1692057328660-fixGPSNullIsland.ts similarity index 100% rename from server/src/infra/migrations/1692057328660-fixGPSNullIsland.ts rename to server/src/migrations/1692057328660-fixGPSNullIsland.ts diff --git a/server/src/infra/migrations/1692112147855-AddPersonBirthDate.ts b/server/src/migrations/1692112147855-AddPersonBirthDate.ts similarity index 100% rename from server/src/infra/migrations/1692112147855-AddPersonBirthDate.ts rename to server/src/migrations/1692112147855-AddPersonBirthDate.ts diff --git a/server/src/infra/migrations/1692804658140-AddAuditTable.ts b/server/src/migrations/1692804658140-AddAuditTable.ts similarity index 100% rename from server/src/infra/migrations/1692804658140-AddAuditTable.ts rename to server/src/migrations/1692804658140-AddAuditTable.ts diff --git a/server/src/infra/migrations/1693236627291-RenameMLEnableFlags.ts b/server/src/migrations/1693236627291-RenameMLEnableFlags.ts similarity index 100% rename from server/src/infra/migrations/1693236627291-RenameMLEnableFlags.ts rename to server/src/migrations/1693236627291-RenameMLEnableFlags.ts diff --git a/server/src/infra/migrations/1693833336881-AddPersonFaceAssetId.ts b/server/src/migrations/1693833336881-AddPersonFaceAssetId.ts similarity index 100% rename from server/src/infra/migrations/1693833336881-AddPersonFaceAssetId.ts rename to server/src/migrations/1693833336881-AddPersonFaceAssetId.ts diff --git a/server/src/infra/migrations/1694204416744-AddAssetDeletedAtColumn.ts b/server/src/migrations/1694204416744-AddAssetDeletedAtColumn.ts similarity index 100% rename from server/src/infra/migrations/1694204416744-AddAssetDeletedAtColumn.ts rename to server/src/migrations/1694204416744-AddAssetDeletedAtColumn.ts diff --git a/server/src/infra/migrations/1694525143117-AddLocalDateTime.ts b/server/src/migrations/1694525143117-AddLocalDateTime.ts similarity index 100% rename from server/src/infra/migrations/1694525143117-AddLocalDateTime.ts rename to server/src/migrations/1694525143117-AddLocalDateTime.ts diff --git a/server/src/infra/migrations/1694638413248-AddDeletedAtToAlbums.ts b/server/src/migrations/1694638413248-AddDeletedAtToAlbums.ts similarity index 100% rename from server/src/infra/migrations/1694638413248-AddDeletedAtToAlbums.ts rename to server/src/migrations/1694638413248-AddDeletedAtToAlbums.ts diff --git a/server/src/infra/migrations/1694750975773-AddExifColorSpace.ts b/server/src/migrations/1694750975773-AddExifColorSpace.ts similarity index 100% rename from server/src/infra/migrations/1694750975773-AddExifColorSpace.ts rename to server/src/migrations/1694750975773-AddExifColorSpace.ts diff --git a/server/src/infra/migrations/1694758412194-UpdateOpusCodecToLibopus.ts b/server/src/migrations/1694758412194-UpdateOpusCodecToLibopus.ts similarity index 100% rename from server/src/infra/migrations/1694758412194-UpdateOpusCodecToLibopus.ts rename to server/src/migrations/1694758412194-UpdateOpusCodecToLibopus.ts diff --git a/server/src/infra/migrations/1695354433573-AddStackParentIdToAssets.ts b/server/src/migrations/1695354433573-AddStackParentIdToAssets.ts similarity index 100% rename from server/src/infra/migrations/1695354433573-AddStackParentIdToAssets.ts rename to server/src/migrations/1695354433573-AddStackParentIdToAssets.ts diff --git a/server/src/infra/migrations/1695660378655-RemoveInvalidCoordinates.ts b/server/src/migrations/1695660378655-RemoveInvalidCoordinates.ts similarity index 100% rename from server/src/infra/migrations/1695660378655-RemoveInvalidCoordinates.ts rename to server/src/migrations/1695660378655-RemoveInvalidCoordinates.ts diff --git a/server/src/infra/migrations/1696888644031-AddOriginalPathIndex.ts b/server/src/migrations/1696888644031-AddOriginalPathIndex.ts similarity index 100% rename from server/src/infra/migrations/1696888644031-AddOriginalPathIndex.ts rename to server/src/migrations/1696888644031-AddOriginalPathIndex.ts diff --git a/server/src/infra/migrations/1696968880063-AddMoveTable.ts b/server/src/migrations/1696968880063-AddMoveTable.ts similarity index 100% rename from server/src/infra/migrations/1696968880063-AddMoveTable.ts rename to server/src/migrations/1696968880063-AddMoveTable.ts diff --git a/server/src/infra/migrations/1697272818851-UnassignFace.ts b/server/src/migrations/1697272818851-UnassignFace.ts similarity index 100% rename from server/src/infra/migrations/1697272818851-UnassignFace.ts rename to server/src/migrations/1697272818851-UnassignFace.ts diff --git a/server/src/infra/migrations/1698290827089-AddPasswordToSharedLinks.ts b/server/src/migrations/1698290827089-AddPasswordToSharedLinks.ts similarity index 100% rename from server/src/infra/migrations/1698290827089-AddPasswordToSharedLinks.ts rename to server/src/migrations/1698290827089-AddPasswordToSharedLinks.ts diff --git a/server/src/infra/migrations/1698693294632-AddActivity.ts b/server/src/migrations/1698693294632-AddActivity.ts similarity index 100% rename from server/src/infra/migrations/1698693294632-AddActivity.ts rename to server/src/migrations/1698693294632-AddActivity.ts diff --git a/server/src/infra/migrations/1699268680508-DisableActivity.ts b/server/src/migrations/1699268680508-DisableActivity.ts similarity index 100% rename from server/src/infra/migrations/1699268680508-DisableActivity.ts rename to server/src/migrations/1699268680508-DisableActivity.ts diff --git a/server/src/infra/migrations/1699322864544-UserNameConsolidation.ts b/server/src/migrations/1699322864544-UserNameConsolidation.ts similarity index 100% rename from server/src/infra/migrations/1699322864544-UserNameConsolidation.ts rename to server/src/migrations/1699322864544-UserNameConsolidation.ts diff --git a/server/src/infra/migrations/1699345863886-AddJobStatus.ts b/server/src/migrations/1699345863886-AddJobStatus.ts similarity index 100% rename from server/src/infra/migrations/1699345863886-AddJobStatus.ts rename to server/src/migrations/1699345863886-AddJobStatus.ts diff --git a/server/src/infra/migrations/1699562570201-AdddInTimelineToPartnersTable.ts b/server/src/migrations/1699562570201-AdddInTimelineToPartnersTable.ts similarity index 100% rename from server/src/infra/migrations/1699562570201-AdddInTimelineToPartnersTable.ts rename to server/src/migrations/1699562570201-AdddInTimelineToPartnersTable.ts diff --git a/server/src/infra/migrations/1699727044012-EditFaceAssetForeignKey.ts b/server/src/migrations/1699727044012-EditFaceAssetForeignKey.ts similarity index 100% rename from server/src/infra/migrations/1699727044012-EditFaceAssetForeignKey.ts rename to server/src/migrations/1699727044012-EditFaceAssetForeignKey.ts diff --git a/server/src/infra/migrations/1699889987493-AddAvatarColor.ts b/server/src/migrations/1699889987493-AddAvatarColor.ts similarity index 100% rename from server/src/infra/migrations/1699889987493-AddAvatarColor.ts rename to server/src/migrations/1699889987493-AddAvatarColor.ts diff --git a/server/src/infra/migrations/1700345818045-SystemMetadata.ts b/server/src/migrations/1700345818045-SystemMetadata.ts similarity index 100% rename from server/src/infra/migrations/1700345818045-SystemMetadata.ts rename to server/src/migrations/1700345818045-SystemMetadata.ts diff --git a/server/src/infra/migrations/1700362016675-Geodata.ts b/server/src/migrations/1700362016675-Geodata.ts similarity index 100% rename from server/src/infra/migrations/1700362016675-Geodata.ts rename to server/src/migrations/1700362016675-Geodata.ts diff --git a/server/src/infra/migrations/1700713871511-UsePgVectors.ts b/server/src/migrations/1700713871511-UsePgVectors.ts similarity index 100% rename from server/src/infra/migrations/1700713871511-UsePgVectors.ts rename to server/src/migrations/1700713871511-UsePgVectors.ts diff --git a/server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts b/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts similarity index 100% rename from server/src/infra/migrations/1700713994428-AddCLIPEmbeddingIndex.ts rename to server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts diff --git a/server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts b/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts similarity index 100% rename from server/src/infra/migrations/1700714033632-AddFaceEmbeddingIndex.ts rename to server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts diff --git a/server/src/infra/migrations/1700714072055-AddSmartInfoTagsIndex.ts b/server/src/migrations/1700714072055-AddSmartInfoTagsIndex.ts similarity index 100% rename from server/src/infra/migrations/1700714072055-AddSmartInfoTagsIndex.ts rename to server/src/migrations/1700714072055-AddSmartInfoTagsIndex.ts diff --git a/server/src/infra/migrations/1700714140297-CreateSmartInfoTextSearchIndex.ts b/server/src/migrations/1700714140297-CreateSmartInfoTextSearchIndex.ts similarity index 100% rename from server/src/infra/migrations/1700714140297-CreateSmartInfoTextSearchIndex.ts rename to server/src/migrations/1700714140297-CreateSmartInfoTextSearchIndex.ts diff --git a/server/src/infra/migrations/1700752078178-AddAssetFaceIndicies.ts b/server/src/migrations/1700752078178-AddAssetFaceIndicies.ts similarity index 100% rename from server/src/infra/migrations/1700752078178-AddAssetFaceIndicies.ts rename to server/src/migrations/1700752078178-AddAssetFaceIndicies.ts diff --git a/server/src/infra/migrations/1701665867595-AddExifCityIndex.ts b/server/src/migrations/1701665867595-AddExifCityIndex.ts similarity index 100% rename from server/src/infra/migrations/1701665867595-AddExifCityIndex.ts rename to server/src/migrations/1701665867595-AddExifCityIndex.ts diff --git a/server/src/infra/migrations/1702084989965-AddWebSocketAttachmentTable.ts b/server/src/migrations/1702084989965-AddWebSocketAttachmentTable.ts similarity index 100% rename from server/src/infra/migrations/1702084989965-AddWebSocketAttachmentTable.ts rename to server/src/migrations/1702084989965-AddWebSocketAttachmentTable.ts diff --git a/server/src/infra/migrations/1702257380990-DropNullIslandLatLong.ts b/server/src/migrations/1702257380990-DropNullIslandLatLong.ts similarity index 100% rename from server/src/infra/migrations/1702257380990-DropNullIslandLatLong.ts rename to server/src/migrations/1702257380990-DropNullIslandLatLong.ts diff --git a/server/src/infra/migrations/1702938928766-NullifyFutureBirthDatesAndAddCheckConstraint.ts b/server/src/migrations/1702938928766-NullifyFutureBirthDatesAndAddCheckConstraint.ts similarity index 100% rename from server/src/infra/migrations/1702938928766-NullifyFutureBirthDatesAndAddCheckConstraint.ts rename to server/src/migrations/1702938928766-NullifyFutureBirthDatesAndAddCheckConstraint.ts diff --git a/server/src/infra/migrations/1702942303661-FixRemovedAssetsSharedLink.ts b/server/src/migrations/1702942303661-FixRemovedAssetsSharedLink.ts similarity index 100% rename from server/src/infra/migrations/1702942303661-FixRemovedAssetsSharedLink.ts rename to server/src/migrations/1702942303661-FixRemovedAssetsSharedLink.ts diff --git a/server/src/infra/migrations/1703035138085-AddAutoStackId.ts b/server/src/migrations/1703035138085-AddAutoStackId.ts similarity index 100% rename from server/src/infra/migrations/1703035138085-AddAutoStackId.ts rename to server/src/migrations/1703035138085-AddAutoStackId.ts diff --git a/server/src/infra/migrations/1703288449127-DefaultStorageTemplateOnForExistingInstallations.ts b/server/src/migrations/1703288449127-DefaultStorageTemplateOnForExistingInstallations.ts similarity index 100% rename from server/src/infra/migrations/1703288449127-DefaultStorageTemplateOnForExistingInstallations.ts rename to server/src/migrations/1703288449127-DefaultStorageTemplateOnForExistingInstallations.ts diff --git a/server/src/infra/migrations/1704382918223-AddQuotaColumnsToUser.ts b/server/src/migrations/1704382918223-AddQuotaColumnsToUser.ts similarity index 100% rename from server/src/infra/migrations/1704382918223-AddQuotaColumnsToUser.ts rename to server/src/migrations/1704382918223-AddQuotaColumnsToUser.ts diff --git a/server/src/infra/migrations/1704571051932-DefaultOnboardingForExistingInstallations.ts b/server/src/migrations/1704571051932-DefaultOnboardingForExistingInstallations.ts similarity index 100% rename from server/src/infra/migrations/1704571051932-DefaultOnboardingForExistingInstallations.ts rename to server/src/migrations/1704571051932-DefaultOnboardingForExistingInstallations.ts diff --git a/server/src/infra/migrations/1704943345360-SetAssetFaceNullOnPersonDelete.ts b/server/src/migrations/1704943345360-SetAssetFaceNullOnPersonDelete.ts similarity index 100% rename from server/src/infra/migrations/1704943345360-SetAssetFaceNullOnPersonDelete.ts rename to server/src/migrations/1704943345360-SetAssetFaceNullOnPersonDelete.ts diff --git a/server/src/infra/migrations/1705094221536-AddMetadataExtractedAt.ts b/server/src/migrations/1705094221536-AddMetadataExtractedAt.ts similarity index 100% rename from server/src/infra/migrations/1705094221536-AddMetadataExtractedAt.ts rename to server/src/migrations/1705094221536-AddMetadataExtractedAt.ts diff --git a/server/src/infra/migrations/1705306747072-AddOriginalFileNameIndex.ts b/server/src/migrations/1705306747072-AddOriginalFileNameIndex.ts similarity index 100% rename from server/src/infra/migrations/1705306747072-AddOriginalFileNameIndex.ts rename to server/src/migrations/1705306747072-AddOriginalFileNameIndex.ts diff --git a/server/src/infra/migrations/1705363967169-CreateAssetStackTable.ts b/server/src/migrations/1705363967169-CreateAssetStackTable.ts similarity index 100% rename from server/src/infra/migrations/1705363967169-CreateAssetStackTable.ts rename to server/src/migrations/1705363967169-CreateAssetStackTable.ts diff --git a/server/src/infra/migrations/1707000751533-AddVectorsToSearchPath.ts b/server/src/migrations/1707000751533-AddVectorsToSearchPath.ts similarity index 100% rename from server/src/infra/migrations/1707000751533-AddVectorsToSearchPath.ts rename to server/src/migrations/1707000751533-AddVectorsToSearchPath.ts diff --git a/server/src/infra/migrations/1708059341865-GeodataLocationSearch.ts b/server/src/migrations/1708059341865-GeodataLocationSearch.ts similarity index 100% rename from server/src/infra/migrations/1708059341865-GeodataLocationSearch.ts rename to server/src/migrations/1708059341865-GeodataLocationSearch.ts diff --git a/server/src/infra/migrations/1708116312820-GeonamesEnhancement.ts b/server/src/migrations/1708116312820-GeonamesEnhancement.ts similarity index 100% rename from server/src/infra/migrations/1708116312820-GeonamesEnhancement.ts rename to server/src/migrations/1708116312820-GeonamesEnhancement.ts diff --git a/server/src/infra/migrations/1708227417898-AddFileCreatedAtIndex.ts b/server/src/migrations/1708227417898-AddFileCreatedAtIndex.ts similarity index 100% rename from server/src/infra/migrations/1708227417898-AddFileCreatedAtIndex.ts rename to server/src/migrations/1708227417898-AddFileCreatedAtIndex.ts diff --git a/server/src/infra/migrations/1708425975121-RemoveExternalPath.ts b/server/src/migrations/1708425975121-RemoveExternalPath.ts similarity index 100% rename from server/src/infra/migrations/1708425975121-RemoveExternalPath.ts rename to server/src/migrations/1708425975121-RemoveExternalPath.ts diff --git a/server/src/infra/migrations/1709150004123-RemoveLibraryWatchPollingOption.ts b/server/src/migrations/1709150004123-RemoveLibraryWatchPollingOption.ts similarity index 100% rename from server/src/infra/migrations/1709150004123-RemoveLibraryWatchPollingOption.ts rename to server/src/migrations/1709150004123-RemoveLibraryWatchPollingOption.ts diff --git a/server/src/infra/migrations/1709608140355-AddAssetOriginalPathTrigramIndex.ts b/server/src/migrations/1709608140355-AddAssetOriginalPathTrigramIndex.ts similarity index 100% rename from server/src/infra/migrations/1709608140355-AddAssetOriginalPathTrigramIndex.ts rename to server/src/migrations/1709608140355-AddAssetOriginalPathTrigramIndex.ts diff --git a/server/src/infra/migrations/1709763765506-AddExtensionToOriginalFileName.ts b/server/src/migrations/1709763765506-AddExtensionToOriginalFileName.ts similarity index 100% rename from server/src/infra/migrations/1709763765506-AddExtensionToOriginalFileName.ts rename to server/src/migrations/1709763765506-AddExtensionToOriginalFileName.ts diff --git a/server/src/infra/migrations/1709825430031-CascadeSharedLinksDelete.ts b/server/src/migrations/1709825430031-CascadeSharedLinksDelete.ts similarity index 100% rename from server/src/infra/migrations/1709825430031-CascadeSharedLinksDelete.ts rename to server/src/migrations/1709825430031-CascadeSharedLinksDelete.ts diff --git a/server/src/infra/migrations/1709870213078-AddUserStatus.ts b/server/src/migrations/1709870213078-AddUserStatus.ts similarity index 100% rename from server/src/infra/migrations/1709870213078-AddUserStatus.ts rename to server/src/migrations/1709870213078-AddUserStatus.ts diff --git a/server/src/infra/migrations/1710182081326-AscendingOrderAlbum.ts b/server/src/migrations/1710182081326-AscendingOrderAlbum.ts similarity index 100% rename from server/src/infra/migrations/1710182081326-AscendingOrderAlbum.ts rename to server/src/migrations/1710182081326-AscendingOrderAlbum.ts diff --git a/server/src/infra/migrations/1710293990203-AddAssetRelationIndices.ts b/server/src/migrations/1710293990203-AddAssetRelationIndices.ts similarity index 100% rename from server/src/infra/migrations/1710293990203-AddAssetRelationIndices.ts rename to server/src/migrations/1710293990203-AddAssetRelationIndices.ts diff --git a/server/src/infra/repositories/access.repository.ts b/server/src/repositories/access.repository.ts similarity index 95% rename from server/src/infra/repositories/access.repository.ts rename to server/src/repositories/access.repository.ts index c6b7bc0fd..418cf542f 100644 --- a/server/src/infra/repositories/access.repository.ts +++ b/server/src/repositories/access.repository.ts @@ -1,14 +1,14 @@ import { InjectRepository } from '@nestjs/typeorm'; import { ChunkedSet, DummyValue, GenerateSql } from 'src/decorators'; -import { ActivityEntity } from 'src/infra/entities/activity.entity'; -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { LibraryEntity } from 'src/infra/entities/library.entity'; -import { PartnerEntity } from 'src/infra/entities/partner.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; -import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { ActivityEntity } from 'src/entities/activity.entity'; +import { AlbumEntity } from 'src/entities/album.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { LibraryEntity } from 'src/entities/library.entity'; +import { PartnerEntity } from 'src/entities/partner.entity'; +import { PersonEntity } from 'src/entities/person.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; +import { UserTokenEntity } from 'src/entities/user-token.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { Brackets, In, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/activity.repository.ts b/server/src/repositories/activity.repository.ts similarity index 96% rename from server/src/infra/repositories/activity.repository.ts rename to server/src/repositories/activity.repository.ts index 4c1cec6d6..bec4a4f17 100644 --- a/server/src/infra/repositories/activity.repository.ts +++ b/server/src/repositories/activity.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { ActivityEntity } from 'src/entities/activity.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { IActivityRepository } from 'src/interfaces/activity.repository'; import { IsNull, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/album.repository.ts b/server/src/repositories/album.repository.ts similarity index 98% rename from server/src/infra/repositories/album.repository.ts rename to server/src/repositories/album.repository.ts index ca4d4a913..4646ef3d9 100644 --- a/server/src/infra/repositories/album.repository.ts +++ b/server/src/repositories/album.repository.ts @@ -2,9 +2,9 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import _ from 'lodash'; import { Chunked, ChunkedArray, DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from 'src/decorators'; +import { AlbumEntity } from 'src/entities/album.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; import { dataSource } from 'src/infra/database.config'; -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { AlbumAsset, diff --git a/server/src/infra/repositories/api-key.repository.ts b/server/src/repositories/api-key.repository.ts similarity index 96% rename from server/src/infra/repositories/api-key.repository.ts rename to server/src/repositories/api-key.repository.ts index 0add8512a..14a7db9c9 100644 --- a/server/src/infra/repositories/api-key.repository.ts +++ b/server/src/repositories/api-key.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { APIKeyEntity } from 'src/entities/api-key.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/asset-stack.repository.ts b/server/src/repositories/asset-stack.repository.ts similarity index 94% rename from server/src/infra/repositories/asset-stack.repository.ts rename to server/src/repositories/asset-stack.repository.ts index 0f984f4ea..9859c5fad 100644 --- a/server/src/infra/repositories/asset-stack.repository.ts +++ b/server/src/repositories/asset-stack.repository.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; +import { AssetStackEntity } from 'src/entities/asset-stack.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts similarity index 98% rename from server/src/infra/repositories/asset.repository.ts rename to server/src/repositories/asset.repository.ts index 3026c5386..71bef17ef 100644 --- a/server/src/infra/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -3,11 +3,11 @@ import { InjectRepository } from '@nestjs/typeorm'; import { DateTime } from 'luxon'; import path from 'node:path'; import { Chunked, ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; -import { AssetOrder } from 'src/infra/entities/album.entity'; -import { AssetJobStatusEntity } from 'src/infra/entities/asset-job-status.entity'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; -import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; +import { AssetOrder } from 'src/entities/album.entity'; +import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; +import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { OptionalBetween, paginate, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; import { diff --git a/server/src/infra/repositories/audit.repository.ts b/server/src/repositories/audit.repository.ts similarity index 94% rename from server/src/infra/repositories/audit.repository.ts rename to server/src/repositories/audit.repository.ts index bfd55336d..1d892dab2 100644 --- a/server/src/infra/repositories/audit.repository.ts +++ b/server/src/repositories/audit.repository.ts @@ -1,5 +1,5 @@ import { InjectRepository } from '@nestjs/typeorm'; -import { AuditEntity } from 'src/infra/entities/audit.entity'; +import { AuditEntity } from 'src/entities/audit.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { AuditSearch, IAuditRepository } from 'src/interfaces/audit.repository'; import { LessThan, MoreThan, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/communication.repository.ts b/server/src/repositories/communication.repository.ts similarity index 100% rename from server/src/infra/repositories/communication.repository.ts rename to server/src/repositories/communication.repository.ts diff --git a/server/src/infra/repositories/crypto.repository.ts b/server/src/repositories/crypto.repository.ts similarity index 100% rename from server/src/infra/repositories/crypto.repository.ts rename to server/src/repositories/crypto.repository.ts diff --git a/server/src/infra/repositories/database.repository.ts b/server/src/repositories/database.repository.ts similarity index 100% rename from server/src/infra/repositories/database.repository.ts rename to server/src/repositories/database.repository.ts diff --git a/server/src/infra/repositories/filesystem.provider.spec.ts b/server/src/repositories/filesystem.provider.spec.ts similarity index 98% rename from server/src/infra/repositories/filesystem.provider.spec.ts rename to server/src/repositories/filesystem.provider.spec.ts index 9b12187ed..56f54b036 100644 --- a/server/src/infra/repositories/filesystem.provider.spec.ts +++ b/server/src/repositories/filesystem.provider.spec.ts @@ -1,6 +1,6 @@ import mockfs from 'mock-fs'; import { CrawlOptionsDto } from 'src/domain/library/library.dto'; -import { FilesystemProvider } from 'src/infra/repositories/filesystem.provider'; +import { FilesystemProvider } from 'src/repositories/filesystem.provider'; interface Test { test: string; diff --git a/server/src/infra/repositories/filesystem.provider.ts b/server/src/repositories/filesystem.provider.ts similarity index 100% rename from server/src/infra/repositories/filesystem.provider.ts rename to server/src/repositories/filesystem.provider.ts diff --git a/server/src/infra/repositories/job.repository.ts b/server/src/repositories/job.repository.ts similarity index 100% rename from server/src/infra/repositories/job.repository.ts rename to server/src/repositories/job.repository.ts diff --git a/server/src/infra/repositories/library.repository.ts b/server/src/repositories/library.repository.ts similarity index 98% rename from server/src/infra/repositories/library.repository.ts rename to server/src/repositories/library.repository.ts index ae6a1e343..7171aad0d 100644 --- a/server/src/infra/repositories/library.repository.ts +++ b/server/src/repositories/library.repository.ts @@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { LibraryStatsResponseDto } from 'src/domain/library/library.dto'; -import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IsNull, Not } from 'typeorm'; diff --git a/server/src/infra/repositories/machine-learning.repository.ts b/server/src/repositories/machine-learning.repository.ts similarity index 100% rename from server/src/infra/repositories/machine-learning.repository.ts rename to server/src/repositories/machine-learning.repository.ts diff --git a/server/src/infra/repositories/media.repository.ts b/server/src/repositories/media.repository.ts similarity index 98% rename from server/src/infra/repositories/media.repository.ts rename to server/src/repositories/media.repository.ts index 8c143d049..d0f4332b4 100644 --- a/server/src/infra/repositories/media.repository.ts +++ b/server/src/repositories/media.repository.ts @@ -3,7 +3,7 @@ import fs from 'node:fs/promises'; import { Writable } from 'node:stream'; import { promisify } from 'node:util'; import sharp from 'sharp'; -import { Colorspace } from 'src/infra/entities/system-config.entity'; +import { Colorspace } from 'src/entities/system-config.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; import { diff --git a/server/src/infra/repositories/metadata.repository.ts b/server/src/repositories/metadata.repository.ts similarity index 97% rename from server/src/infra/repositories/metadata.repository.ts rename to server/src/repositories/metadata.repository.ts index a5e82535c..5da664f14 100644 --- a/server/src/infra/repositories/metadata.repository.ts +++ b/server/src/repositories/metadata.repository.ts @@ -14,9 +14,9 @@ import { geodataCities500Path, geodataDatePath, } from 'src/domain/domain.constant'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; -import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; -import { SystemMetadataKey } from 'src/infra/entities/system-metadata.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; +import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; +import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; import { GeoPoint, IMetadataRepository, ImmichTags, ReverseGeocodeResult } from 'src/interfaces/metadata.repository'; diff --git a/server/src/infra/repositories/move.repository.ts b/server/src/repositories/move.repository.ts similarity index 93% rename from server/src/infra/repositories/move.repository.ts rename to server/src/repositories/move.repository.ts index 7f7595125..e567bcca3 100644 --- a/server/src/infra/repositories/move.repository.ts +++ b/server/src/repositories/move.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { MoveEntity, PathType } from 'src/infra/entities/move.entity'; +import { MoveEntity, PathType } from 'src/entities/move.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { IMoveRepository, MoveCreate } from 'src/interfaces/move.repository'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/partner.repository.ts b/server/src/repositories/partner.repository.ts similarity index 95% rename from server/src/infra/repositories/partner.repository.ts rename to server/src/repositories/partner.repository.ts index f8b9866ca..4c4bbc0ed 100644 --- a/server/src/infra/repositories/partner.repository.ts +++ b/server/src/repositories/partner.repository.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { PartnerEntity } from 'src/entities/partner.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { IPartnerRepository, PartnerIds } from 'src/interfaces/partner.repository'; import { DeepPartial, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/person.repository.ts b/server/src/repositories/person.repository.ts similarity index 97% rename from server/src/infra/repositories/person.repository.ts rename to server/src/repositories/person.repository.ts index 5096032da..6a0008c3d 100644 --- a/server/src/infra/repositories/person.repository.ts +++ b/server/src/repositories/person.repository.ts @@ -1,9 +1,9 @@ import { InjectRepository } from '@nestjs/typeorm'; import _ from 'lodash'; import { ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { PersonEntity } from 'src/infra/entities/person.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { PersonEntity } from 'src/entities/person.entity'; import { asVector, paginate } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; import { diff --git a/server/src/infra/repositories/search.repository.ts b/server/src/repositories/search.repository.ts similarity index 97% rename from server/src/infra/repositories/search.repository.ts rename to server/src/repositories/search.repository.ts index 83bbef667..aefb3c933 100644 --- a/server/src/infra/repositories/search.repository.ts +++ b/server/src/repositories/search.repository.ts @@ -2,12 +2,12 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; +import { SmartInfoEntity } from 'src/entities/smart-info.entity'; +import { SmartSearchEntity } from 'src/entities/smart-search.entity'; import { vectorExt } from 'src/infra/database.config'; -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { GeodataPlacesEntity } from 'src/infra/entities/geodata-places.entity'; -import { SmartInfoEntity } from 'src/infra/entities/smart-info.entity'; -import { SmartSearchEntity } from 'src/infra/entities/smart-search.entity'; import { asVector, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/infra/repositories/server-info.repository.ts b/server/src/repositories/server-info.repository.ts similarity index 100% rename from server/src/infra/repositories/server-info.repository.ts rename to server/src/repositories/server-info.repository.ts diff --git a/server/src/infra/repositories/shared-link.repository.ts b/server/src/repositories/shared-link.repository.ts similarity index 96% rename from server/src/infra/repositories/shared-link.repository.ts rename to server/src/repositories/shared-link.repository.ts index 93aacf1f2..968b6dd73 100644 --- a/server/src/infra/repositories/shared-link.repository.ts +++ b/server/src/repositories/shared-link.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/system-config.repository.ts b/server/src/repositories/system-config.repository.ts similarity index 94% rename from server/src/infra/repositories/system-config.repository.ts rename to server/src/repositories/system-config.repository.ts index ba3ee0aa0..af6296ce0 100644 --- a/server/src/infra/repositories/system-config.repository.ts +++ b/server/src/repositories/system-config.repository.ts @@ -1,7 +1,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { readFile } from 'node:fs/promises'; import { Chunked, DummyValue, GenerateSql } from 'src/decorators'; -import { SystemConfigEntity } from 'src/infra/entities/system-config.entity'; +import { SystemConfigEntity } from 'src/entities/system-config.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { In, Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/system-metadata.repository.ts b/server/src/repositories/system-metadata.repository.ts similarity index 90% rename from server/src/infra/repositories/system-metadata.repository.ts rename to server/src/repositories/system-metadata.repository.ts index 12c72c090..978dba9bd 100644 --- a/server/src/infra/repositories/system-metadata.repository.ts +++ b/server/src/repositories/system-metadata.repository.ts @@ -1,5 +1,5 @@ import { InjectRepository } from '@nestjs/typeorm'; -import { SystemMetadata, SystemMetadataEntity } from 'src/infra/entities/system-metadata.entity'; +import { SystemMetadata, SystemMetadataEntity } from 'src/entities/system-metadata.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/tag.repository.ts b/server/src/repositories/tag.repository.ts similarity index 96% rename from server/src/infra/repositories/tag.repository.ts rename to server/src/repositories/tag.repository.ts index c44b0763a..a2ae74878 100644 --- a/server/src/infra/repositories/tag.repository.ts +++ b/server/src/repositories/tag.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { TagEntity } from 'src/infra/entities/tag.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { TagEntity } from 'src/entities/tag.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ITagRepository } from 'src/interfaces/tag.repository'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/user-token.repository.ts b/server/src/repositories/user-token.repository.ts similarity index 95% rename from server/src/infra/repositories/user-token.repository.ts rename to server/src/repositories/user-token.repository.ts index 19dcafc1e..31d6d2190 100644 --- a/server/src/infra/repositories/user-token.repository.ts +++ b/server/src/repositories/user-token.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { UserTokenEntity } from 'src/entities/user-token.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; import { Repository } from 'typeorm'; diff --git a/server/src/infra/repositories/user.repository.ts b/server/src/repositories/user.repository.ts similarity index 97% rename from server/src/infra/repositories/user.repository.ts rename to server/src/repositories/user.repository.ts index 743293766..bd94e71a5 100644 --- a/server/src/infra/repositories/user.repository.ts +++ b/server/src/repositories/user.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { IUserRepository, diff --git a/server/src/infra/subscribers/audit.subscriber.ts b/server/src/subscribers/audit.subscriber.ts similarity index 84% rename from server/src/infra/subscribers/audit.subscriber.ts rename to server/src/subscribers/audit.subscriber.ts index ddfc5d0d7..3d65507ae 100644 --- a/server/src/infra/subscribers/audit.subscriber.ts +++ b/server/src/subscribers/audit.subscriber.ts @@ -1,6 +1,6 @@ -import { AlbumEntity } from 'src/infra/entities/album.entity'; -import { AssetEntity } from 'src/infra/entities/asset.entity'; -import { AuditEntity, DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; +import { AlbumEntity } from 'src/entities/album.entity'; +import { AssetEntity } from 'src/entities/asset.entity'; +import { AuditEntity, DatabaseAction, EntityType } from 'src/entities/audit.entity'; import { EntitySubscriberInterface, EventSubscriber, RemoveEvent } from 'typeorm'; @EventSubscriber() diff --git a/server/src/test-utils/utils.ts b/server/src/test-utils/utils.ts index b9e74f767..9b8ab059b 100644 --- a/server/src/test-utils/utils.ts +++ b/server/src/test-utils/utils.ts @@ -11,11 +11,11 @@ import { AppModule } from 'src/immich/app.module'; import { AppService } from 'src/immich/app.service'; import { dataSource } from 'src/infra/database.config'; import { InfraModule, InfraTestModule } from 'src/infra/infra.module'; -import { MediaRepository } from 'src/infra/repositories/media.repository'; import { IJobRepository, JobItem, JobItemHandler } from 'src/interfaces/job.repository'; import { IMediaRepository } from 'src/interfaces/media.repository'; import { StorageEventType } from 'src/interfaces/storage.repository'; import { AppService as MicroAppService } from 'src/microservices/app.service'; +import { MediaRepository } from 'src/repositories/media.repository'; import { EntityTarget, ObjectLiteral } from 'typeorm'; export const IMMICH_TEST_ASSET_PATH = process.env.IMMICH_TEST_ASSET_PATH as string; diff --git a/server/test/fixtures/activity.stub.ts b/server/test/fixtures/activity.stub.ts index ae33699a0..4805f6604 100644 --- a/server/test/fixtures/activity.stub.ts +++ b/server/test/fixtures/activity.stub.ts @@ -1,4 +1,4 @@ -import { ActivityEntity } from 'src/infra/entities/activity.entity'; +import { ActivityEntity } from 'src/entities/activity.entity'; import { albumStub } from 'test/fixtures/album.stub'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/test/fixtures/album.stub.ts b/server/test/fixtures/album.stub.ts index 18be7d4ff..ff9348167 100644 --- a/server/test/fixtures/album.stub.ts +++ b/server/test/fixtures/album.stub.ts @@ -1,4 +1,4 @@ -import { AlbumEntity, AssetOrder } from 'src/infra/entities/album.entity'; +import { AlbumEntity, AssetOrder } from 'src/entities/album.entity'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/test/fixtures/api-key.stub.ts b/server/test/fixtures/api-key.stub.ts index bc6f85c65..954c8f35a 100644 --- a/server/test/fixtures/api-key.stub.ts +++ b/server/test/fixtures/api-key.stub.ts @@ -1,4 +1,4 @@ -import { APIKeyEntity } from 'src/infra/entities/api-key.entity'; +import { APIKeyEntity } from 'src/entities/api-key.entity'; import { authStub } from 'test/fixtures/auth.stub'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/test/fixtures/asset.stub.ts b/server/test/fixtures/asset.stub.ts index d2daeaaff..e9b4650c2 100644 --- a/server/test/fixtures/asset.stub.ts +++ b/server/test/fixtures/asset.stub.ts @@ -1,6 +1,6 @@ -import { AssetStackEntity } from 'src/infra/entities/asset-stack.entity'; -import { AssetEntity, AssetType } from 'src/infra/entities/asset.entity'; -import { ExifEntity } from 'src/infra/entities/exif.entity'; +import { AssetStackEntity } from 'src/entities/asset-stack.entity'; +import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { ExifEntity } from 'src/entities/exif.entity'; import { authStub } from 'test/fixtures/auth.stub'; import { fileStub } from 'test/fixtures/file.stub'; import { libraryStub } from 'test/fixtures/library.stub'; diff --git a/server/test/fixtures/audit.stub.ts b/server/test/fixtures/audit.stub.ts index 2c7ef6782..bca1d3349 100644 --- a/server/test/fixtures/audit.stub.ts +++ b/server/test/fixtures/audit.stub.ts @@ -1,4 +1,4 @@ -import { AuditEntity, DatabaseAction, EntityType } from 'src/infra/entities/audit.entity'; +import { AuditEntity, DatabaseAction, EntityType } from 'src/entities/audit.entity'; import { authStub } from 'test/fixtures/auth.stub'; export const auditStub = { diff --git a/server/test/fixtures/auth.stub.ts b/server/test/fixtures/auth.stub.ts index f05285fd6..e0add44d2 100644 --- a/server/test/fixtures/auth.stub.ts +++ b/server/test/fixtures/auth.stub.ts @@ -1,7 +1,7 @@ import { AuthDto } from 'src/domain/auth/auth.dto'; -import { SharedLinkEntity } from 'src/infra/entities/shared-link.entity'; -import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { SharedLinkEntity } from 'src/entities/shared-link.entity'; +import { UserTokenEntity } from 'src/entities/user-token.entity'; +import { UserEntity } from 'src/entities/user.entity'; export const adminSignupStub = { name: 'Immich Admin', diff --git a/server/test/fixtures/face.stub.ts b/server/test/fixtures/face.stub.ts index 58a017927..2d2acec40 100644 --- a/server/test/fixtures/face.stub.ts +++ b/server/test/fixtures/face.stub.ts @@ -1,4 +1,4 @@ -import { AssetFaceEntity } from 'src/infra/entities/asset-face.entity'; +import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { assetStub } from 'test/fixtures/asset.stub'; import { personStub } from 'test/fixtures/person.stub'; diff --git a/server/test/fixtures/library.stub.ts b/server/test/fixtures/library.stub.ts index 0c5296595..b3fa4b7f0 100644 --- a/server/test/fixtures/library.stub.ts +++ b/server/test/fixtures/library.stub.ts @@ -1,7 +1,7 @@ import { join } from 'node:path'; import { THUMBNAIL_DIR } from 'src/cores/storage.core'; import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; -import { LibraryEntity, LibraryType } from 'src/infra/entities/library.entity'; +import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; import { userStub } from 'test/fixtures/user.stub'; export const libraryStub = { diff --git a/server/test/fixtures/partner.stub.ts b/server/test/fixtures/partner.stub.ts index 1277e2e21..4e5643bc1 100644 --- a/server/test/fixtures/partner.stub.ts +++ b/server/test/fixtures/partner.stub.ts @@ -1,4 +1,4 @@ -import { PartnerEntity } from 'src/infra/entities/partner.entity'; +import { PartnerEntity } from 'src/entities/partner.entity'; import { userStub } from 'test/fixtures/user.stub'; export const partnerStub = { diff --git a/server/test/fixtures/person.stub.ts b/server/test/fixtures/person.stub.ts index a573d72e3..5e5a2214e 100644 --- a/server/test/fixtures/person.stub.ts +++ b/server/test/fixtures/person.stub.ts @@ -1,4 +1,4 @@ -import { PersonEntity } from 'src/infra/entities/person.entity'; +import { PersonEntity } from 'src/entities/person.entity'; import { userStub } from 'test/fixtures/user.stub'; export const personStub = { diff --git a/server/test/fixtures/shared-link.stub.ts b/server/test/fixtures/shared-link.stub.ts index d3b3d5151..6855c8c7a 100644 --- a/server/test/fixtures/shared-link.stub.ts +++ b/server/test/fixtures/shared-link.stub.ts @@ -3,10 +3,10 @@ import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.d import { ExifResponseDto } from 'src/domain/asset/response-dto/exif-response.dto'; import { SharedLinkResponseDto } from 'src/domain/shared-link/shared-link-response.dto'; import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; -import { AssetOrder } from 'src/infra/entities/album.entity'; -import { AssetType } from 'src/infra/entities/asset.entity'; -import { SharedLinkEntity, SharedLinkType } from 'src/infra/entities/shared-link.entity'; -import { UserEntity } from 'src/infra/entities/user.entity'; +import { AssetOrder } from 'src/entities/album.entity'; +import { AssetType } from 'src/entities/asset.entity'; +import { SharedLinkEntity, SharedLinkType } from 'src/entities/shared-link.entity'; +import { UserEntity } from 'src/entities/user.entity'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { libraryStub } from 'test/fixtures/library.stub'; diff --git a/server/test/fixtures/system-config.stub.ts b/server/test/fixtures/system-config.stub.ts index 2de539848..b557644ef 100644 --- a/server/test/fixtures/system-config.stub.ts +++ b/server/test/fixtures/system-config.stub.ts @@ -1,4 +1,4 @@ -import { SystemConfigEntity, SystemConfigKey } from 'src/infra/entities/system-config.entity'; +import { SystemConfigEntity, SystemConfigKey } from 'src/entities/system-config.entity'; export const systemConfigStub: Record = { defaults: [], diff --git a/server/test/fixtures/tag.stub.ts b/server/test/fixtures/tag.stub.ts index a48005528..27123ddb6 100644 --- a/server/test/fixtures/tag.stub.ts +++ b/server/test/fixtures/tag.stub.ts @@ -1,5 +1,5 @@ import { TagResponseDto } from 'src/domain/tag/tag-response.dto'; -import { TagEntity, TagType } from 'src/infra/entities/tag.entity'; +import { TagEntity, TagType } from 'src/entities/tag.entity'; import { userStub } from 'test/fixtures/user.stub'; export const tagStub = { diff --git a/server/test/fixtures/user-token.stub.ts b/server/test/fixtures/user-token.stub.ts index de42d1d32..2f6fcc0cd 100644 --- a/server/test/fixtures/user-token.stub.ts +++ b/server/test/fixtures/user-token.stub.ts @@ -1,4 +1,4 @@ -import { UserTokenEntity } from 'src/infra/entities/user-token.entity'; +import { UserTokenEntity } from 'src/entities/user-token.entity'; import { userStub } from 'test/fixtures/user.stub'; export const userTokenStub = { diff --git a/server/test/fixtures/user.stub.ts b/server/test/fixtures/user.stub.ts index 7809583c7..5cf5acfc3 100644 --- a/server/test/fixtures/user.stub.ts +++ b/server/test/fixtures/user.stub.ts @@ -1,4 +1,4 @@ -import { UserAvatarColor, UserEntity } from 'src/infra/entities/user.entity'; +import { UserAvatarColor, UserEntity } from 'src/entities/user.entity'; import { authStub } from 'test/fixtures/auth.stub'; export const userDto = { From 907eb869bc8804de505da827869164f7f7982639 Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 20 Mar 2024 16:22:47 -0500 Subject: [PATCH 039/152] chore: move apps and test utils (#8129) --- .../e2e/jobs/specs/library-watcher.e2e-spec.ts | 2 +- server/e2e/jobs/specs/library.e2e-spec.ts | 2 +- server/src/{immich/main.ts => apps/api.main.ts} | 10 +++++----- .../{immich/app.module.ts => apps/api.module.ts} | 8 ++++---- .../app.service.ts => apps/api.service.ts} | 4 ++-- server/src/apps/immich-admin.main.ts | 8 ++++++++ .../immich-admin.module.ts} | 2 +- .../main.ts => apps/microservices.main.ts} | 4 ++-- .../microservices.module.ts | 6 +++--- .../microservices.service.ts} | 2 +- server/src/immich-admin/main.ts | 8 -------- server/src/main.ts | 12 ++++++------ server/{src/test-utils => test}/utils.ts | 16 ++++++++-------- 13 files changed, 42 insertions(+), 42 deletions(-) rename server/src/{immich/main.ts => apps/api.main.ts} (89%) rename server/src/{immich/app.module.ts => apps/api.module.ts} (95%) rename server/src/{immich/app.service.ts => apps/api.service.ts} (97%) create mode 100755 server/src/apps/immich-admin.main.ts rename server/src/{immich-admin/app.module.ts => apps/immich-admin.module.ts} (95%) rename server/src/{microservices/main.ts => apps/microservices.main.ts} (86%) rename server/src/{microservices => apps}/microservices.module.ts (67%) rename server/src/{microservices/app.service.ts => apps/microservices.service.ts} (99%) delete mode 100755 server/src/immich-admin/main.ts rename server/{src/test-utils => test}/utils.ts (93%) diff --git a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts index e8be570ca..3d43227b7 100644 --- a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts +++ b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts @@ -13,7 +13,7 @@ import { restoreTempFolder, testApp, waitForEvent, -} from 'src/test-utils/utils'; +} from 'test/utils'; describe(`Library watcher (e2e)`, () => { let server: any; diff --git a/server/e2e/jobs/specs/library.e2e-spec.ts b/server/e2e/jobs/specs/library.e2e-spec.ts index c2839a7d1..657c53fc2 100644 --- a/server/e2e/jobs/specs/library.e2e-spec.ts +++ b/server/e2e/jobs/specs/library.e2e-spec.ts @@ -3,10 +3,10 @@ import fs from 'node:fs'; import { LibraryController } from 'src/controllers/library.controller'; import { LoginResponseDto } from 'src/domain/auth/auth.dto'; import { LibraryType } from 'src/entities/library.entity'; -import { IMMICH_TEST_ASSET_PATH, IMMICH_TEST_ASSET_TEMP_PATH, restoreTempFolder, testApp } from 'src/test-utils/utils'; import request from 'supertest'; import { errorStub } from 'test/fixtures/error.stub'; import { uuidStub } from 'test/fixtures/uuid.stub'; +import { IMMICH_TEST_ASSET_PATH, IMMICH_TEST_ASSET_TEMP_PATH, restoreTempFolder, testApp } from 'test/utils'; import { utimes } from 'utimes'; describe(`${LibraryController.name} (e2e)`, () => { diff --git a/server/src/immich/main.ts b/server/src/apps/api.main.ts similarity index 89% rename from server/src/immich/main.ts rename to server/src/apps/api.main.ts index 310ac9302..9ffdd1d48 100644 --- a/server/src/immich/main.ts +++ b/server/src/apps/api.main.ts @@ -4,10 +4,10 @@ import { json } from 'body-parser'; import cookieParser from 'cookie-parser'; import { existsSync } from 'node:fs'; import sirv from 'sirv'; +import { ApiModule } from 'src/apps/api.module'; +import { ApiService } from 'src/apps/api.service'; import { excludePaths } from 'src/config'; import { WEB_ROOT, envName, isDev, serverVersion } from 'src/domain/domain.constant'; -import { AppModule } from 'src/immich/app.module'; -import { AppService } from 'src/immich/app.service'; import { useSwagger } from 'src/immich/app.utils'; import { otelSDK } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; @@ -16,9 +16,9 @@ import { WebSocketAdapter } from 'src/infra/websocket.adapter'; const logger = new ImmichLogger('ImmichServer'); const port = Number(process.env.SERVER_PORT) || 3001; -export async function bootstrap() { +export async function bootstrapApi() { otelSDK.start(); - const app = await NestFactory.create(AppModule, { bufferLogs: true }); + const app = await NestFactory.create(ApiModule, { bufferLogs: true }); app.useLogger(app.get(ImmichLogger)); app.set('trust proxy', ['loopback', 'linklocal', 'uniquelocal']); @@ -48,7 +48,7 @@ export async function bootstrap() { }), ); } - app.use(app.get(AppService).ssr(excludePaths)); + app.use(app.get(ApiService).ssr(excludePaths)); const server = await app.listen(port); server.requestTimeout = 30 * 60 * 1000; diff --git a/server/src/immich/app.module.ts b/server/src/apps/api.module.ts similarity index 95% rename from server/src/immich/app.module.ts rename to server/src/apps/api.module.ts index a5b88473e..04c95f199 100644 --- a/server/src/immich/app.module.ts +++ b/server/src/apps/api.module.ts @@ -2,6 +2,7 @@ import { Module, OnModuleInit, ValidationPipe } from '@nestjs/common'; import { APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core'; import { ScheduleModule } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { ApiService } from 'src/apps/api.service'; import { ActivityController } from 'src/controllers/activity.controller'; import { AlbumController } from 'src/controllers/album.controller'; import { APIKeyController } from 'src/controllers/api-key.controller'; @@ -29,7 +30,6 @@ import { ExifEntity } from 'src/entities/exif.entity'; import { AssetRepositoryV1, IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; import { AssetController as AssetControllerV1 } from 'src/immich/api-v1/asset/asset.controller'; import { AssetService as AssetServiceV1 } from 'src/immich/api-v1/asset/asset.service'; -import { AppService } from 'src/immich/app.service'; import { InfraModule } from 'src/infra/infra.module'; import { AuthGuard } from 'src/middleware/auth.guard'; import { ErrorInterceptor } from 'src/middleware/error.interceptor'; @@ -73,13 +73,13 @@ import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor'; { provide: APP_INTERCEPTOR, useClass: ErrorInterceptor }, { provide: APP_GUARD, useClass: AuthGuard }, { provide: IAssetRepositoryV1, useClass: AssetRepositoryV1 }, - AppService, + ApiService, AssetServiceV1, FileUploadInterceptor, ], }) -export class AppModule implements OnModuleInit { - constructor(private appService: AppService) {} +export class ApiModule implements OnModuleInit { + constructor(private appService: ApiService) {} async onModuleInit() { await this.appService.init(); diff --git a/server/src/immich/app.service.ts b/server/src/apps/api.service.ts similarity index 97% rename from server/src/immich/app.service.ts rename to server/src/apps/api.service.ts index f7f1664be..31134cefa 100644 --- a/server/src/immich/app.service.ts +++ b/server/src/apps/api.service.ts @@ -35,8 +35,8 @@ const render = (index: string, meta: OpenGraphTags) => { }; @Injectable() -export class AppService { - private logger = new ImmichLogger(AppService.name); +export class ApiService { + private logger = new ImmichLogger(ApiService.name); constructor( private authService: AuthService, diff --git a/server/src/apps/immich-admin.main.ts b/server/src/apps/immich-admin.main.ts new file mode 100755 index 000000000..5f528a21b --- /dev/null +++ b/server/src/apps/immich-admin.main.ts @@ -0,0 +1,8 @@ +import { CommandFactory } from 'nest-commander'; +import { ImmichAdminModule } from 'src/apps/immich-admin.module'; +import { LogLevel } from 'src/entities/system-config.entity'; + +export async function bootstrapImmichAdmin() { + process.env.LOG_LEVEL = LogLevel.WARN; + await CommandFactory.run(ImmichAdminModule); +} diff --git a/server/src/immich-admin/app.module.ts b/server/src/apps/immich-admin.module.ts similarity index 95% rename from server/src/immich-admin/app.module.ts rename to server/src/apps/immich-admin.module.ts index b491fbb55..d0e5cab4c 100644 --- a/server/src/immich-admin/app.module.ts +++ b/server/src/apps/immich-admin.module.ts @@ -18,4 +18,4 @@ import { InfraModule } from 'src/infra/infra.module'; ListUsersCommand, ], }) -export class AppModule {} +export class ImmichAdminModule {} diff --git a/server/src/microservices/main.ts b/server/src/apps/microservices.main.ts similarity index 86% rename from server/src/microservices/main.ts rename to server/src/apps/microservices.main.ts index 01949dd02..552fb714c 100644 --- a/server/src/microservices/main.ts +++ b/server/src/apps/microservices.main.ts @@ -1,14 +1,14 @@ import { NestFactory } from '@nestjs/core'; +import { MicroservicesModule } from 'src/apps/microservices.module'; import { envName, serverVersion } from 'src/domain/domain.constant'; import { otelSDK } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; import { WebSocketAdapter } from 'src/infra/websocket.adapter'; -import { MicroservicesModule } from 'src/microservices/microservices.module'; const logger = new ImmichLogger('ImmichMicroservice'); const port = Number(process.env.MICROSERVICES_PORT) || 3002; -export async function bootstrap() { +export async function bootstrapMicroservices() { otelSDK.start(); const app = await NestFactory.create(MicroservicesModule, { bufferLogs: true }); app.useLogger(app.get(ImmichLogger)); diff --git a/server/src/microservices/microservices.module.ts b/server/src/apps/microservices.module.ts similarity index 67% rename from server/src/microservices/microservices.module.ts rename to server/src/apps/microservices.module.ts index 6fc9f0890..3ddfb28f3 100644 --- a/server/src/microservices/microservices.module.ts +++ b/server/src/apps/microservices.module.ts @@ -1,14 +1,14 @@ import { Module, OnModuleInit } from '@nestjs/common'; +import { MicroservicesService } from 'src/apps/microservices.service'; import { DomainModule } from 'src/domain/domain.module'; import { InfraModule } from 'src/infra/infra.module'; -import { AppService } from 'src/microservices/app.service'; @Module({ imports: [InfraModule, DomainModule], - providers: [AppService], + providers: [MicroservicesService], }) export class MicroservicesModule implements OnModuleInit { - constructor(private appService: AppService) {} + constructor(private appService: MicroservicesService) {} async onModuleInit() { await this.appService.init(); diff --git a/server/src/microservices/app.service.ts b/server/src/apps/microservices.service.ts similarity index 99% rename from server/src/microservices/app.service.ts rename to server/src/apps/microservices.service.ts index 043ee9f03..bfdc37576 100644 --- a/server/src/microservices/app.service.ts +++ b/server/src/apps/microservices.service.ts @@ -17,7 +17,7 @@ import { UserService } from 'src/domain/user/user.service'; import { otelSDK } from 'src/infra/instrumentation'; @Injectable() -export class AppService { +export class MicroservicesService { constructor( private auditService: AuditService, private assetService: AssetService, diff --git a/server/src/immich-admin/main.ts b/server/src/immich-admin/main.ts deleted file mode 100755 index 4a561ec88..000000000 --- a/server/src/immich-admin/main.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { CommandFactory } from 'nest-commander'; -import { LogLevel } from 'src/entities/system-config.entity'; -import { AppModule } from 'src/immich-admin/app.module'; - -export async function bootstrap() { - process.env.LOG_LEVEL = LogLevel.WARN; - await CommandFactory.run(AppModule); -} diff --git a/server/src/main.ts b/server/src/main.ts index d59875133..ee60c793c 100644 --- a/server/src/main.ts +++ b/server/src/main.ts @@ -1,6 +1,6 @@ -import { bootstrap as admin } from 'src/immich-admin/main'; -import { bootstrap as server } from 'src/immich/main'; -import { bootstrap as microservices } from 'src/microservices/main'; +import { bootstrapApi } from 'src/apps/api.main'; +import { bootstrapImmichAdmin } from 'src/apps/immich-admin.main'; +import { bootstrapMicroservices } from 'src/apps/microservices.main'; const immichApp = process.argv[2] || process.env.IMMICH_APP; @@ -12,15 +12,15 @@ function bootstrap() { switch (immichApp) { case 'immich': { process.title = 'immich_server'; - return server(); + return bootstrapApi(); } case 'microservices': { process.title = 'immich_microservices'; - return microservices(); + return bootstrapMicroservices(); } case 'immich-admin': { process.title = 'immich_admin_cli'; - return admin(); + return bootstrapImmichAdmin(); } default: { throw new Error(`Invalid app name: ${immichApp}. Expected one of immich|microservices|cli`); diff --git a/server/src/test-utils/utils.ts b/server/test/utils.ts similarity index 93% rename from server/src/test-utils/utils.ts rename to server/test/utils.ts index 9b8ab059b..777a6a00c 100644 --- a/server/src/test-utils/utils.ts +++ b/server/test/utils.ts @@ -6,15 +6,15 @@ import { tmpdir } from 'node:os'; import { join } from 'node:path'; import { EventEmitter } from 'node:stream'; import { Server } from 'node:tls'; +import { ApiModule } from 'src/apps/api.module'; +import { ApiService } from 'src/apps/api.service'; +import { MicroservicesService } from 'src/apps/microservices.service'; import { QueueName } from 'src/domain/job/job.constants'; -import { AppModule } from 'src/immich/app.module'; -import { AppService } from 'src/immich/app.service'; import { dataSource } from 'src/infra/database.config'; import { InfraModule, InfraTestModule } from 'src/infra/infra.module'; import { IJobRepository, JobItem, JobItemHandler } from 'src/interfaces/job.repository'; import { IMediaRepository } from 'src/interfaces/media.repository'; import { StorageEventType } from 'src/interfaces/storage.repository'; -import { AppService as MicroAppService } from 'src/microservices/app.service'; import { MediaRepository } from 'src/repositories/media.repository'; import { EntityTarget, ObjectLiteral } from 'typeorm'; @@ -106,8 +106,8 @@ let app: INestApplication; export const testApp = { create: async (): Promise => { const moduleFixture = await Test.createTestingModule({ - imports: [AppModule], - providers: [AppService, MicroAppService], + imports: [ApiModule], + providers: [ApiService, MicroservicesService], }) .overrideModule(InfraModule) .useModule(InfraTestModule) @@ -120,8 +120,8 @@ export const testApp = { app = await moduleFixture.createNestApplication().init(); await app.listen(0); await db.reset(); - await app.get(AppService).init(); - await app.get(MicroAppService).init(); + await app.get(ApiService).init(); + await app.get(MicroservicesService).init(); const port = app.getHttpServer().address().port; const protocol = app instanceof Server ? 'https' : 'http'; @@ -135,7 +135,7 @@ export const testApp = { get: (member: any) => app.get(member), teardown: async () => { if (app) { - await app.get(MicroAppService).teardown(); + await app.get(MicroservicesService).teardown(); await app.close(); } await db.disconnect(); From 0c13c63bb62ab6e16730a1bab337a57dc12acd5a Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 20 Mar 2024 16:46:59 -0500 Subject: [PATCH 040/152] refactor: infra/domain module (#8130) --- server/src/apps/api.module.ts | 6 +- .../infra.module.ts => apps/app.module.ts} | 68 ++++++++++++++++--- server/src/apps/immich-admin.module.ts | 5 +- server/src/apps/microservices.module.ts | 5 +- server/src/domain/domain.module.ts | 62 ----------------- server/test/utils.ts | 6 +- 6 files changed, 69 insertions(+), 83 deletions(-) rename server/src/{infra/infra.module.ts => apps/app.module.ts} (73%) delete mode 100644 server/src/domain/domain.module.ts diff --git a/server/src/apps/api.module.ts b/server/src/apps/api.module.ts index 04c95f199..717b348de 100644 --- a/server/src/apps/api.module.ts +++ b/server/src/apps/api.module.ts @@ -3,6 +3,7 @@ import { APP_GUARD, APP_INTERCEPTOR, APP_PIPE } from '@nestjs/core'; import { ScheduleModule } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { ApiService } from 'src/apps/api.service'; +import { AppModule } from 'src/apps/app.module'; import { ActivityController } from 'src/controllers/activity.controller'; import { AlbumController } from 'src/controllers/album.controller'; import { APIKeyController } from 'src/controllers/api-key.controller'; @@ -24,13 +25,11 @@ import { SystemConfigController } from 'src/controllers/system-config.controller import { TagController } from 'src/controllers/tag.controller'; import { TrashController } from 'src/controllers/trash.controller'; import { UserController } from 'src/controllers/user.controller'; -import { DomainModule } from 'src/domain/domain.module'; import { AssetEntity } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { AssetRepositoryV1, IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; import { AssetController as AssetControllerV1 } from 'src/immich/api-v1/asset/asset.controller'; import { AssetService as AssetServiceV1 } from 'src/immich/api-v1/asset/asset.service'; -import { InfraModule } from 'src/infra/infra.module'; import { AuthGuard } from 'src/middleware/auth.guard'; import { ErrorInterceptor } from 'src/middleware/error.interceptor'; import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor'; @@ -38,8 +37,7 @@ import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor'; @Module({ imports: [ // - InfraModule, - DomainModule, + AppModule, ScheduleModule.forRoot(), TypeOrmModule.forFeature([AssetEntity, ExifEntity]), ], diff --git a/server/src/infra/infra.module.ts b/server/src/apps/app.module.ts similarity index 73% rename from server/src/infra/infra.module.ts rename to server/src/apps/app.module.ts index b0387ba96..f134d3363 100644 --- a/server/src/infra/infra.module.ts +++ b/server/src/apps/app.module.ts @@ -6,9 +6,34 @@ import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpenTelemetryModule } from 'nestjs-otel'; import { bullConfig, bullQueues, immichAppConfig } from 'src/config'; +import { ActivityService } from 'src/domain/activity/activity.service'; +import { AlbumService } from 'src/domain/album/album.service'; +import { APIKeyService } from 'src/domain/api-key/api-key.service'; +import { AssetService } from 'src/domain/asset/asset.service'; +import { AuditService } from 'src/domain/audit/audit.service'; +import { AuthService } from 'src/domain/auth/auth.service'; +import { DatabaseService } from 'src/domain/database/database.service'; +import { DownloadService } from 'src/domain/download/download.service'; +import { JobService } from 'src/domain/job/job.service'; +import { LibraryService } from 'src/domain/library/library.service'; +import { MediaService } from 'src/domain/media/media.service'; +import { MetadataService } from 'src/domain/metadata/metadata.service'; +import { PartnerService } from 'src/domain/partner/partner.service'; +import { PersonService } from 'src/domain/person/person.service'; +import { SearchService } from 'src/domain/search/search.service'; +import { ServerInfoService } from 'src/domain/server-info/server-info.service'; +import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; +import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; +import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; +import { StorageService } from 'src/domain/storage/storage.service'; +import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { TagService } from 'src/domain/tag/tag.service'; +import { TrashService } from 'src/domain/trash/trash.service'; +import { UserService } from 'src/domain/user/user.service'; import { databaseEntities } from 'src/entities'; import { databaseConfig } from 'src/infra/database.config'; import { otelConfig } from 'src/infra/instrumentation'; +import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IActivityRepository } from 'src/interfaces/activity.repository'; import { IAlbumRepository } from 'src/interfaces/album.repository'; @@ -64,7 +89,35 @@ import { TagRepository } from 'src/repositories/tag.repository'; import { UserTokenRepository } from 'src/repositories/user-token.repository'; import { UserRepository } from 'src/repositories/user.repository'; -const providers: Provider[] = [ +const services: Provider[] = [ + APIKeyService, + ActivityService, + AlbumService, + AssetService, + AuditService, + AuthService, + DatabaseService, + DownloadService, + ImmichLogger, + JobService, + LibraryService, + MediaService, + MetadataService, + PartnerService, + PersonService, + SearchService, + ServerInfoService, + SharedLinkService, + SmartInfoService, + StorageService, + StorageTemplateService, + SystemConfigService, + TagService, + TrashService, + UserService, +]; + +const repositories: Provider[] = [ { provide: IActivityRepository, useClass: ActivityRepository }, { provide: IAccessRepository, useClass: AccessRepository }, { provide: IAlbumRepository, useClass: AlbumRepository }, @@ -92,7 +145,6 @@ const providers: Provider[] = [ { provide: IMediaRepository, useClass: MediaRepository }, { provide: IUserRepository, useClass: UserRepository }, { provide: IUserTokenRepository, useClass: UserTokenRepository }, - SchedulerRegistry, ]; @Global() @@ -107,10 +159,10 @@ const providers: Provider[] = [ BullModule.registerQueue(...bullQueues), OpenTelemetryModule.forRoot(otelConfig), ], - providers: [...providers], - exports: [...providers, BullModule], + providers: [...services, ...repositories, SchedulerRegistry], + exports: [...services, ...repositories, BullModule, SchedulerRegistry], }) -export class InfraModule {} +export class AppModule {} @Global() @Module({ @@ -121,7 +173,7 @@ export class InfraModule {} TypeOrmModule.forFeature(databaseEntities), ScheduleModule, ], - providers: [...providers], - exports: [...providers], + providers: [...services, ...repositories, SchedulerRegistry], + exports: [...services, ...repositories, SchedulerRegistry], }) -export class InfraTestModule {} +export class AppTestModule {} diff --git a/server/src/apps/immich-admin.module.ts b/server/src/apps/immich-admin.module.ts index d0e5cab4c..eff2e9cc0 100644 --- a/server/src/apps/immich-admin.module.ts +++ b/server/src/apps/immich-admin.module.ts @@ -1,13 +1,12 @@ import { Module } from '@nestjs/common'; +import { AppModule } from 'src/apps/app.module'; import { ListUsersCommand } from 'src/commands/list-users.command'; import { DisableOAuthLogin, EnableOAuthLogin } from 'src/commands/oauth-login'; import { DisablePasswordLoginCommand, EnablePasswordLoginCommand } from 'src/commands/password-login'; import { PromptPasswordQuestions, ResetAdminPasswordCommand } from 'src/commands/reset-admin-password.command'; -import { DomainModule } from 'src/domain/domain.module'; -import { InfraModule } from 'src/infra/infra.module'; @Module({ - imports: [InfraModule, DomainModule], + imports: [AppModule], providers: [ ResetAdminPasswordCommand, PromptPasswordQuestions, diff --git a/server/src/apps/microservices.module.ts b/server/src/apps/microservices.module.ts index 3ddfb28f3..d9a28a91c 100644 --- a/server/src/apps/microservices.module.ts +++ b/server/src/apps/microservices.module.ts @@ -1,10 +1,9 @@ import { Module, OnModuleInit } from '@nestjs/common'; +import { AppModule } from 'src/apps/app.module'; import { MicroservicesService } from 'src/apps/microservices.service'; -import { DomainModule } from 'src/domain/domain.module'; -import { InfraModule } from 'src/infra/infra.module'; @Module({ - imports: [InfraModule, DomainModule], + imports: [AppModule], providers: [MicroservicesService], }) export class MicroservicesModule implements OnModuleInit { diff --git a/server/src/domain/domain.module.ts b/server/src/domain/domain.module.ts deleted file mode 100644 index 04d7c51f4..000000000 --- a/server/src/domain/domain.module.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Global, Module, Provider } from '@nestjs/common'; -import { ActivityService } from 'src/domain/activity/activity.service'; -import { AlbumService } from 'src/domain/album/album.service'; -import { APIKeyService } from 'src/domain/api-key/api-key.service'; -import { AssetService } from 'src/domain/asset/asset.service'; -import { AuditService } from 'src/domain/audit/audit.service'; -import { AuthService } from 'src/domain/auth/auth.service'; -import { DatabaseService } from 'src/domain/database/database.service'; -import { DownloadService } from 'src/domain/download/download.service'; -import { JobService } from 'src/domain/job/job.service'; -import { LibraryService } from 'src/domain/library/library.service'; -import { MediaService } from 'src/domain/media/media.service'; -import { MetadataService } from 'src/domain/metadata/metadata.service'; -import { PartnerService } from 'src/domain/partner/partner.service'; -import { PersonService } from 'src/domain/person/person.service'; -import { SearchService } from 'src/domain/search/search.service'; -import { ServerInfoService } from 'src/domain/server-info/server-info.service'; -import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; -import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; -import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; -import { StorageService } from 'src/domain/storage/storage.service'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; -import { TagService } from 'src/domain/tag/tag.service'; -import { TrashService } from 'src/domain/trash/trash.service'; -import { UserService } from 'src/domain/user/user.service'; -import { ImmichLogger } from 'src/infra/logger'; - -const providers: Provider[] = [ - APIKeyService, - ActivityService, - AlbumService, - AssetService, - AuditService, - AuthService, - DatabaseService, - DownloadService, - ImmichLogger, - JobService, - LibraryService, - MediaService, - MetadataService, - PartnerService, - PersonService, - SearchService, - ServerInfoService, - SharedLinkService, - SmartInfoService, - StorageService, - StorageTemplateService, - SystemConfigService, - TagService, - TrashService, - UserService, -]; - -@Global() -@Module({ - imports: [], - providers: [...providers], - exports: [...providers], -}) -export class DomainModule {} diff --git a/server/test/utils.ts b/server/test/utils.ts index 777a6a00c..f44f6fe17 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -8,10 +8,10 @@ import { EventEmitter } from 'node:stream'; import { Server } from 'node:tls'; import { ApiModule } from 'src/apps/api.module'; import { ApiService } from 'src/apps/api.service'; +import { AppModule, AppTestModule } from 'src/apps/app.module'; import { MicroservicesService } from 'src/apps/microservices.service'; import { QueueName } from 'src/domain/job/job.constants'; import { dataSource } from 'src/infra/database.config'; -import { InfraModule, InfraTestModule } from 'src/infra/infra.module'; import { IJobRepository, JobItem, JobItemHandler } from 'src/interfaces/job.repository'; import { IMediaRepository } from 'src/interfaces/media.repository'; import { StorageEventType } from 'src/interfaces/storage.repository'; @@ -109,8 +109,8 @@ export const testApp = { imports: [ApiModule], providers: [ApiService, MicroservicesService], }) - .overrideModule(InfraModule) - .useModule(InfraTestModule) + .overrideModule(AppModule) + .useModule(AppTestModule) .overrideProvider(IJobRepository) .useClass(JobMock) .overrideProvider(IMediaRepository) From 6d9e7694b1361527660fa4f30d506964ed9daeb9 Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Wed, 20 Mar 2024 23:53:07 +0100 Subject: [PATCH 041/152] chore(server): move dtos (#8131) move dtos --- server/e2e/client/asset-api.ts | 2 +- server/e2e/client/auth-api.ts | 4 +- server/e2e/client/library-api.ts | 2 +- .../jobs/specs/library-watcher.e2e-spec.ts | 4 +- server/e2e/jobs/specs/library.e2e-spec.ts | 2 +- .../commands/reset-admin-password.command.ts | 2 +- server/src/controllers/activity.controller.ts | 6 +- server/src/controllers/album.controller.ts | 19 +- server/src/controllers/api-key.controller.ts | 9 +- server/src/controllers/asset.controller.ts | 23 ++- server/src/controllers/audit.controller.ts | 6 +- server/src/controllers/auth.controller.ts | 6 +- server/src/controllers/download.controller.ts | 6 +- server/src/controllers/face.controller.ts | 4 +- server/src/controllers/job.controller.ts | 2 +- server/src/controllers/library.controller.ts | 4 +- server/src/controllers/oauth.controller.ts | 6 +- server/src/controllers/partner.controller.ts | 4 +- server/src/controllers/person.controller.ts | 10 +- server/src/controllers/search.controller.ts | 16 +- .../src/controllers/server-info.controller.ts | 4 +- .../src/controllers/shared-link.controller.ts | 14 +- .../controllers/system-config.controller.ts | 4 +- server/src/controllers/tag.controller.ts | 11 +- server/src/controllers/trash.controller.ts | 4 +- server/src/controllers/user.controller.ts | 10 +- server/src/cores/access.core.ts | 2 +- server/src/cores/system-config.core.ts | 2 +- server/src/cores/user.core.ts | 2 +- .../src/domain/activity/activity.service.ts | 4 +- server/src/domain/activity/activity.spec.ts | 2 +- server/src/domain/album/album.service.spec.ts | 2 +- server/src/domain/album/album.service.ts | 16 +- .../domain/album/dto/album-add-users.dto.ts | 8 - .../src/domain/album/dto/album-create.dto.ts | 19 -- .../src/domain/album/dto/album-update.dto.ts | 25 --- server/src/domain/album/dto/album.dto.ts | 6 - server/src/domain/album/dto/get-albums.dto.ts | 19 -- server/src/domain/api-key/api-key.service.ts | 4 +- server/src/domain/asset/asset.service.spec.ts | 7 +- server/src/domain/asset/asset.service.ts | 39 ++-- server/src/domain/asset/dto/asset-ids.dto.ts | 20 --- .../domain/asset/dto/asset-statistics.dto.ts | 34 ---- server/src/domain/asset/dto/asset.dto.ts | 75 -------- server/src/domain/asset/dto/map-marker.dto.ts | 18 -- .../src/domain/asset/dto/memory-lane.dto.ts | 19 -- .../response-dto/map-marker-response.dto.ts | 21 --- .../response-dto/smart-info-response.dto.ts | 13 -- .../response-dto/time-bucket-response.dto.ts | 9 - server/src/domain/audit/audit.service.ts | 8 +- server/src/domain/auth/auth.service.spec.ts | 2 +- server/src/domain/auth/auth.service.ts | 4 +- .../domain/download/download.service.spec.ts | 2 +- .../src/domain/download/download.service.ts | 6 +- server/src/domain/job/job.service.ts | 4 +- .../domain/library/library.service.spec.ts | 2 +- server/src/domain/library/library.service.ts | 2 +- server/src/domain/media/media.service.ts | 2 +- server/src/domain/media/media.util.ts | 2 +- .../domain/partner/partner.service.spec.ts | 2 +- server/src/domain/partner/partner.service.ts | 6 +- .../src/domain/person/person.service.spec.ts | 4 +- server/src/domain/person/person.service.ts | 8 +- .../search/dto/search-suggestion.dto.ts | 34 ---- .../search-explore.response.dto.ts | 11 -- .../response-dto/search-response.dto.ts | 38 ---- .../src/domain/search/search.service.spec.ts | 4 +- server/src/domain/search/search.service.ts | 13 +- .../domain/server-info/server-info.service.ts | 2 +- .../src/domain/shared-link/shared-link.dto.ts | 75 -------- .../shared-link/shared-link.service.spec.ts | 2 +- .../domain/shared-link/shared-link.service.ts | 12 +- ...stem-config-template-storage-option.dto.ts | 10 -- .../system-config/system-config.service.ts | 4 +- server/src/domain/tag/tag.dto.ts | 21 --- server/src/domain/tag/tag.service.spec.ts | 2 +- server/src/domain/tag/tag.service.ts | 11 +- server/src/domain/trash/trash.service.ts | 4 +- .../user/dto/create-profile-image.dto.ts | 7 - server/src/domain/user/dto/create-user.dto.ts | 61 ------- server/src/domain/user/dto/delete-user.dto.ts | 6 - .../domain/user/dto/update-user.dto.spec.ts | 17 -- server/src/domain/user/dto/update-user.dto.ts | 52 ------ .../create-profile-image-response.dto.ts | 11 -- .../user/response-dto/user-response.dto.ts | 65 ------- server/src/domain/user/user.service.spec.ts | 3 +- server/src/domain/user/user.service.ts | 12 +- .../{domain/activity => dtos}/activity.dto.ts | 2 +- .../album => dtos}/album-response.dto.spec.ts | 2 +- .../album.dto.ts} | 97 ++++++++-- .../{domain/api-key => dtos}/api-key.dto.ts | 0 .../asset-ids.response.dto.ts} | 0 .../asset-response.dto.ts | 24 ++- server/src/dtos/asset.dto.ts | 132 ++++++++++++++ .../src/{domain/audit => dtos}/audit.dto.ts | 0 server/src/{domain/auth => dtos}/auth.dto.ts | 0 .../{domain/download => dtos}/download.dto.ts | 0 .../exif-response.dto.ts => dtos/exif.dto.ts} | 0 server/src/{domain/job => dtos}/job.dto.ts | 0 .../{domain/library => dtos}/library.dto.ts | 0 .../dto => dtos}/model-config.dto.ts | 0 .../{domain/partner => dtos}/partner.dto.ts | 2 +- .../src/{domain/person => dtos}/person.dto.ts | 2 +- .../{domain/search/dto => dtos}/search.dto.ts | 129 +++++++++++++ .../server-info => dtos}/server-info.dto.ts | 2 +- .../shared-link.dto.ts} | 76 +++++++- .../asset-stack.dto.ts => dtos/stack.dto.ts} | 0 .../dto => dtos}/system-config-ffmpeg.dto.ts | 0 .../dto => dtos}/system-config-job.dto.ts | 0 .../dto => dtos}/system-config-library.dto.ts | 0 .../dto => dtos}/system-config-logging.dto.ts | 0 .../system-config-machine-learning.dto.ts | 2 +- .../dto => dtos}/system-config-map.dto.ts | 0 .../system-config-new-version-check.dto.ts | 0 .../dto => dtos}/system-config-oauth.dto.ts | 0 .../system-config-password-login.dto.ts | 0 .../system-config-reverse-geocoding.dto.ts | 0 .../dto => dtos}/system-config-server.dto.ts | 0 .../system-config-storage-template.dto.ts | 11 ++ .../dto => dtos}/system-config-theme.dto.ts | 0 .../system-config-thumbnail.dto.ts | 0 .../dto => dtos}/system-config-trash.dto.ts | 0 .../dto => dtos}/system-config-user.dto.ts | 0 .../dto => dtos}/system-config.dto.ts | 32 ++-- .../tag-response.dto.ts => dtos/tag.dto.ts} | 19 ++ .../asset/dto => dtos}/time-bucket.dto.ts | 8 + server/src/dtos/user-profile.dto.ts | 28 +++ .../user.dto.spec.ts} | 16 +- server/src/dtos/user.dto.ts | 169 ++++++++++++++++++ .../immich/api-v1/asset/asset.controller.ts | 4 +- .../src/immich/api-v1/asset/asset.service.ts | 4 +- .../api-v1/asset/dto/create-asset.dto.ts | 2 +- .../interfaces/communication.repository.ts | 4 +- server/src/interfaces/library.repository.ts | 2 +- .../interfaces/machine-learning.repository.ts | 2 +- server/src/interfaces/storage.repository.ts | 2 +- server/src/middleware/auth.guard.ts | 2 +- .../src/middleware/file-upload.interceptor.ts | 3 +- .../repositories/filesystem.provider.spec.ts | 2 +- .../src/repositories/filesystem.provider.ts | 2 +- server/src/repositories/library.repository.ts | 2 +- .../machine-learning.repository.ts | 2 +- server/test/fixtures/auth.stub.ts | 2 +- server/test/fixtures/shared-link.stub.ts | 10 +- server/test/fixtures/tag.stub.ts | 2 +- 145 files changed, 917 insertions(+), 964 deletions(-) delete mode 100644 server/src/domain/album/dto/album-add-users.dto.ts delete mode 100644 server/src/domain/album/dto/album-create.dto.ts delete mode 100644 server/src/domain/album/dto/album-update.dto.ts delete mode 100644 server/src/domain/album/dto/album.dto.ts delete mode 100644 server/src/domain/album/dto/get-albums.dto.ts delete mode 100644 server/src/domain/asset/dto/asset-ids.dto.ts delete mode 100644 server/src/domain/asset/dto/asset-statistics.dto.ts delete mode 100644 server/src/domain/asset/dto/asset.dto.ts delete mode 100644 server/src/domain/asset/dto/map-marker.dto.ts delete mode 100644 server/src/domain/asset/dto/memory-lane.dto.ts delete mode 100644 server/src/domain/asset/response-dto/map-marker-response.dto.ts delete mode 100644 server/src/domain/asset/response-dto/smart-info-response.dto.ts delete mode 100644 server/src/domain/asset/response-dto/time-bucket-response.dto.ts delete mode 100644 server/src/domain/search/dto/search-suggestion.dto.ts delete mode 100644 server/src/domain/search/response-dto/search-explore.response.dto.ts delete mode 100644 server/src/domain/search/response-dto/search-response.dto.ts delete mode 100644 server/src/domain/shared-link/shared-link.dto.ts delete mode 100644 server/src/domain/system-config/response-dto/system-config-template-storage-option.dto.ts delete mode 100644 server/src/domain/tag/tag.dto.ts delete mode 100644 server/src/domain/user/dto/create-profile-image.dto.ts delete mode 100644 server/src/domain/user/dto/create-user.dto.ts delete mode 100644 server/src/domain/user/dto/delete-user.dto.ts delete mode 100644 server/src/domain/user/dto/update-user.dto.spec.ts delete mode 100644 server/src/domain/user/dto/update-user.dto.ts delete mode 100644 server/src/domain/user/response-dto/create-profile-image-response.dto.ts delete mode 100644 server/src/domain/user/response-dto/user-response.dto.ts rename server/src/{domain/activity => dtos}/activity.dto.ts (95%) rename server/src/{domain/album => dtos}/album-response.dto.spec.ts (89%) rename server/src/{domain/album/album-response.dto.ts => dtos/album.dto.ts} (59%) rename server/src/{domain/api-key => dtos}/api-key.dto.ts (100%) rename server/src/{domain/asset/response-dto/asset-ids-response.dto.ts => dtos/asset-ids.response.dto.ts} (100%) rename server/src/{domain/asset/response-dto => dtos}/asset-response.dto.ts (88%) create mode 100644 server/src/dtos/asset.dto.ts rename server/src/{domain/audit => dtos}/audit.dto.ts (100%) rename server/src/{domain/auth => dtos}/auth.dto.ts (100%) rename server/src/{domain/download => dtos}/download.dto.ts (100%) rename server/src/{domain/asset/response-dto/exif-response.dto.ts => dtos/exif.dto.ts} (100%) rename server/src/{domain/job => dtos}/job.dto.ts (100%) rename server/src/{domain/library => dtos}/library.dto.ts (100%) rename server/src/{domain/smart-info/dto => dtos}/model-config.dto.ts (100%) rename server/src/{domain/partner => dtos}/partner.dto.ts (71%) rename server/src/{domain/person => dtos}/person.dto.ts (98%) rename server/src/{domain/search/dto => dtos}/search.dto.ts (66%) rename server/src/{domain/server-info => dtos}/server-info.dto.ts (96%) rename server/src/{domain/shared-link/shared-link-response.dto.ts => dtos/shared-link.dto.ts} (57%) rename server/src/{domain/asset/dto/asset-stack.dto.ts => dtos/stack.dto.ts} (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-ffmpeg.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-job.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-library.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-logging.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-machine-learning.dto.ts (85%) rename server/src/{domain/system-config/dto => dtos}/system-config-map.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-new-version-check.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-oauth.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-password-login.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-reverse-geocoding.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-server.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-storage-template.dto.ts (53%) rename server/src/{domain/system-config/dto => dtos}/system-config-theme.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-thumbnail.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-trash.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config-user.dto.ts (100%) rename server/src/{domain/system-config/dto => dtos}/system-config.dto.ts (56%) rename server/src/{domain/tag/tag-response.dto.ts => dtos/tag.dto.ts} (54%) rename server/src/{domain/asset/dto => dtos}/time-bucket.dto.ts (88%) create mode 100644 server/src/dtos/user-profile.dto.ts rename server/src/{domain/user/dto/create-user.dto.spec.ts => dtos/user.dto.spec.ts} (79%) create mode 100644 server/src/dtos/user.dto.ts diff --git a/server/e2e/client/asset-api.ts b/server/e2e/client/asset-api.ts index 8f30e1f4a..f32d58611 100644 --- a/server/e2e/client/asset-api.ts +++ b/server/e2e/client/asset-api.ts @@ -1,4 +1,4 @@ -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import request from 'supertest'; export const assetApi = { diff --git a/server/e2e/client/auth-api.ts b/server/e2e/client/auth-api.ts index 46b21fb98..a8cfe4660 100644 --- a/server/e2e/client/auth-api.ts +++ b/server/e2e/client/auth-api.ts @@ -1,5 +1,5 @@ -import { LoginResponseDto } from 'src/domain/auth/auth.dto'; -import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; +import { LoginResponseDto } from 'src/dtos/auth.dto'; +import { UserResponseDto } from 'src/dtos/user.dto'; import request from 'supertest'; import { adminSignupStub, loginResponseStub, loginStub } from 'test/fixtures/auth.stub'; diff --git a/server/e2e/client/library-api.ts b/server/e2e/client/library-api.ts index 90b1b7451..70c8c4c36 100644 --- a/server/e2e/client/library-api.ts +++ b/server/e2e/client/library-api.ts @@ -1,4 +1,4 @@ -import { CreateLibraryDto, LibraryResponseDto, ScanLibraryDto } from 'src/domain/library/library.dto'; +import { CreateLibraryDto, LibraryResponseDto, ScanLibraryDto } from 'src/dtos/library.dto'; import request from 'supertest'; export const libraryApi = { diff --git a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts index 3d43227b7..0a005c7d5 100644 --- a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts +++ b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts @@ -1,9 +1,9 @@ import { api } from 'e2e/client'; import fs from 'node:fs/promises'; import path from 'node:path'; -import { LoginResponseDto } from 'src/domain/auth/auth.dto'; -import { LibraryResponseDto } from 'src/domain/library/library.dto'; import { LibraryService } from 'src/domain/library/library.service'; +import { LoginResponseDto } from 'src/dtos/auth.dto'; +import { LibraryResponseDto } from 'src/dtos/library.dto'; import { AssetType } from 'src/entities/asset.entity'; import { LibraryType } from 'src/entities/library.entity'; import { StorageEventType } from 'src/interfaces/storage.repository'; diff --git a/server/e2e/jobs/specs/library.e2e-spec.ts b/server/e2e/jobs/specs/library.e2e-spec.ts index 657c53fc2..3ae27e631 100644 --- a/server/e2e/jobs/specs/library.e2e-spec.ts +++ b/server/e2e/jobs/specs/library.e2e-spec.ts @@ -1,7 +1,7 @@ import { api } from 'e2e/client'; import fs from 'node:fs'; import { LibraryController } from 'src/controllers/library.controller'; -import { LoginResponseDto } from 'src/domain/auth/auth.dto'; +import { LoginResponseDto } from 'src/dtos/auth.dto'; import { LibraryType } from 'src/entities/library.entity'; import request from 'supertest'; import { errorStub } from 'test/fixtures/error.stub'; diff --git a/server/src/commands/reset-admin-password.command.ts b/server/src/commands/reset-admin-password.command.ts index ce0a897a8..b67ef418e 100644 --- a/server/src/commands/reset-admin-password.command.ts +++ b/server/src/commands/reset-admin-password.command.ts @@ -1,6 +1,6 @@ import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander'; -import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; import { UserService } from 'src/domain/user/user.service'; +import { UserResponseDto } from 'src/dtos/user.dto'; @Command({ name: 'reset-admin-password', diff --git a/server/src/controllers/activity.controller.ts b/server/src/controllers/activity.controller.ts index c405b0c6f..92e8797aa 100644 --- a/server/src/controllers/activity.controller.ts +++ b/server/src/controllers/activity.controller.ts @@ -1,15 +1,15 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Response } from 'express'; +import { ActivityService } from 'src/domain/activity/activity.service'; import { ActivityCreateDto, ActivityDto, ActivityResponseDto, ActivitySearchDto, ActivityStatisticsResponseDto, -} from 'src/domain/activity/activity.dto'; -import { ActivityService } from 'src/domain/activity/activity.service'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +} from 'src/dtos/activity.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/album.controller.ts b/server/src/controllers/album.controller.ts index 18fd549b6..7cc39a860 100644 --- a/server/src/controllers/album.controller.ts +++ b/server/src/controllers/album.controller.ts @@ -1,14 +1,17 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AlbumCountResponseDto, AlbumResponseDto } from 'src/domain/album/album-response.dto'; import { AlbumService } from 'src/domain/album/album.service'; -import { AddUsersDto } from 'src/domain/album/dto/album-add-users.dto'; -import { CreateAlbumDto } from 'src/domain/album/dto/album-create.dto'; -import { UpdateAlbumDto } from 'src/domain/album/dto/album-update.dto'; -import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; -import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; -import { BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { + AddUsersDto, + AlbumCountResponseDto, + AlbumInfoDto, + AlbumResponseDto, + CreateAlbumDto, + GetAlbumsDto, + UpdateAlbumDto, +} from 'src/dtos/album.dto'; +import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; import { ParseMeUUIDPipe, UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/api-key.controller.ts b/server/src/controllers/api-key.controller.ts index 2d4f8db15..9b6838f8d 100644 --- a/server/src/controllers/api-key.controller.ts +++ b/server/src/controllers/api-key.controller.ts @@ -1,13 +1,8 @@ import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { - APIKeyCreateDto, - APIKeyCreateResponseDto, - APIKeyResponseDto, - APIKeyUpdateDto, -} from 'src/domain/api-key/api-key.dto'; import { APIKeyService } from 'src/domain/api-key/api-key.service'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto, APIKeyUpdateDto } from 'src/dtos/api-key.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/asset.controller.ts b/server/src/controllers/asset.controller.ts index a6db59815..ca44aedfe 100644 --- a/server/src/controllers/asset.controller.ts +++ b/server/src/controllers/asset.controller.ts @@ -1,25 +1,22 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common'; import { ApiOperation, ApiTags } from '@nestjs/swagger'; import { AssetService } from 'src/domain/asset/asset.service'; -import { AssetJobsDto } from 'src/domain/asset/dto/asset-ids.dto'; -import { UpdateStackParentDto } from 'src/domain/asset/dto/asset-stack.dto'; -import { AssetStatsDto, AssetStatsResponseDto } from 'src/domain/asset/dto/asset-statistics.dto'; +import { SearchService } from 'src/domain/search/search.service'; +import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto'; import { AssetBulkDeleteDto, AssetBulkUpdateDto, + AssetJobsDto, + AssetStatsDto, + AssetStatsResponseDto, DeviceIdDto, RandomAssetsDto, UpdateAssetDto, -} from 'src/domain/asset/dto/asset.dto'; -import { MapMarkerDto } from 'src/domain/asset/dto/map-marker.dto'; -import { MemoryLaneDto } from 'src/domain/asset/dto/memory-lane.dto'; -import { TimeBucketAssetDto, TimeBucketDto } from 'src/domain/asset/dto/time-bucket.dto'; -import { AssetResponseDto, MemoryLaneResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; -import { MapMarkerResponseDto } from 'src/domain/asset/response-dto/map-marker-response.dto'; -import { TimeBucketResponseDto } from 'src/domain/asset/response-dto/time-bucket-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { MetadataSearchDto } from 'src/domain/search/dto/search.dto'; -import { SearchService } from 'src/domain/search/search.service'; +} from 'src/dtos/asset.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { MapMarkerDto, MapMarkerResponseDto, MemoryLaneDto, MetadataSearchDto } from 'src/dtos/search.dto'; +import { UpdateStackParentDto } from 'src/dtos/stack.dto'; +import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto'; import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; import { Route } from 'src/middleware/file-upload.interceptor'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/audit.controller.ts b/server/src/controllers/audit.controller.ts index bb92f990e..b4d27b4ce 100644 --- a/server/src/controllers/audit.controller.ts +++ b/server/src/controllers/audit.controller.ts @@ -1,5 +1,6 @@ import { Body, Controller, Get, Post, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; +import { AuditService } from 'src/domain/audit/audit.service'; import { AuditDeletesDto, AuditDeletesResponseDto, @@ -7,9 +8,8 @@ import { FileChecksumResponseDto, FileReportDto, FileReportFixDto, -} from 'src/domain/audit/audit.dto'; -import { AuditService } from 'src/domain/audit/audit.service'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +} from 'src/dtos/audit.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { AdminRoute, Auth, Authenticated } from 'src/middleware/auth.guard'; @ApiTags('Audit') diff --git a/server/src/controllers/auth.controller.ts b/server/src/controllers/auth.controller.ts index 941002fe6..6197c1e5f 100644 --- a/server/src/controllers/auth.controller.ts +++ b/server/src/controllers/auth.controller.ts @@ -2,6 +2,7 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Req, import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; import { IMMICH_ACCESS_COOKIE, IMMICH_AUTH_TYPE_COOKIE, IMMICH_IS_AUTHENTICATED } from 'src/domain/auth/auth.constant'; +import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; import { AuthDeviceResponseDto, AuthDto, @@ -11,9 +12,8 @@ import { LogoutResponseDto, SignUpDto, ValidateAccessTokenResponseDto, -} from 'src/domain/auth/auth.dto'; -import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; -import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +} from 'src/dtos/auth.dto'; +import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/download.controller.ts b/server/src/controllers/download.controller.ts index 0fb3520cf..8ba5d4281 100644 --- a/server/src/controllers/download.controller.ts +++ b/server/src/controllers/download.controller.ts @@ -1,10 +1,10 @@ import { Body, Controller, HttpCode, HttpStatus, Next, Param, Post, Res, StreamableFile } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/download.dto'; import { DownloadService } from 'src/domain/download/download.service'; +import { AssetIdsDto } from 'src/dtos/asset.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto'; import { asStreamableFile, sendFile } from 'src/immich/app.utils'; import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/face.controller.ts b/server/src/controllers/face.controller.ts index c7caba016..d5712d6b7 100644 --- a/server/src/controllers/face.controller.ts +++ b/server/src/controllers/face.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Get, Param, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { AssetFaceResponseDto, FaceDto, PersonResponseDto } from 'src/domain/person/person.dto'; import { PersonService } from 'src/domain/person/person.service'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { AssetFaceResponseDto, FaceDto, PersonResponseDto } from 'src/dtos/person.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/job.controller.ts b/server/src/controllers/job.controller.ts index f0e9ed2be..04dea79ee 100644 --- a/server/src/controllers/job.controller.ts +++ b/server/src/controllers/job.controller.ts @@ -1,7 +1,7 @@ import { Body, Controller, Get, Param, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobStatusDto } from 'src/domain/job/job.dto'; import { JobService } from 'src/domain/job/job.service'; +import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobStatusDto } from 'src/dtos/job.dto'; import { Authenticated } from 'src/middleware/auth.guard'; @ApiTags('Job') diff --git a/server/src/controllers/library.controller.ts b/server/src/controllers/library.controller.ts index 677773f2d..96c5f7415 100644 --- a/server/src/controllers/library.controller.ts +++ b/server/src/controllers/library.controller.ts @@ -1,5 +1,6 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; +import { LibraryService } from 'src/domain/library/library.service'; import { CreateLibraryDto, LibraryResponseDto, @@ -9,8 +10,7 @@ import { UpdateLibraryDto, ValidateLibraryDto, ValidateLibraryResponseDto, -} from 'src/domain/library/library.dto'; -import { LibraryService } from 'src/domain/library/library.service'; +} from 'src/dtos/library.dto'; import { AdminRoute, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/oauth.controller.ts b/server/src/controllers/oauth.controller.ts index 48b3eafd5..6da9faa17 100644 --- a/server/src/controllers/oauth.controller.ts +++ b/server/src/controllers/oauth.controller.ts @@ -1,15 +1,15 @@ import { Body, Controller, Get, HttpStatus, Post, Redirect, Req, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; +import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; import { AuthDto, LoginResponseDto, OAuthAuthorizeResponseDto, OAuthCallbackDto, OAuthConfigDto, -} from 'src/domain/auth/auth.dto'; -import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; -import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; +} from 'src/dtos/auth.dto'; +import { UserResponseDto } from 'src/dtos/user.dto'; import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard'; @ApiTags('OAuth') diff --git a/server/src/controllers/partner.controller.ts b/server/src/controllers/partner.controller.ts index 8ca55e73c..c4f22a04f 100644 --- a/server/src/controllers/partner.controller.ts +++ b/server/src/controllers/partner.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common'; import { ApiQuery, ApiTags } from '@nestjs/swagger'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; import { PartnerService } from 'src/domain/partner/partner.service'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { PartnerResponseDto, UpdatePartnerDto } from 'src/dtos/partner.dto'; import { PartnerDirection } from 'src/interfaces/partner.repository'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/person.controller.ts b/server/src/controllers/person.controller.ts index bc955fd2c..9c5602091 100644 --- a/server/src/controllers/person.controller.ts +++ b/server/src/controllers/person.controller.ts @@ -1,9 +1,10 @@ import { Body, Controller, Get, Next, Param, Post, Put, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { BulkIdResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { PersonService } from 'src/domain/person/person.service'; +import { BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { AssetFaceUpdateDto, MergePersonDto, @@ -14,8 +15,7 @@ import { PersonSearchDto, PersonStatisticsResponseDto, PersonUpdateDto, -} from 'src/domain/person/person.dto'; -import { PersonService } from 'src/domain/person/person.service'; +} from 'src/dtos/person.dto'; import { sendFile } from 'src/immich/app.utils'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/search.controller.ts b/server/src/controllers/search.controller.ts index 76fce1609..6b88f5ad8 100644 --- a/server/src/controllers/search.controller.ts +++ b/server/src/controllers/search.controller.ts @@ -1,20 +1,20 @@ import { Body, Controller, Get, HttpCode, HttpStatus, Post, Query } from '@nestjs/common'; import { ApiOperation, ApiTags } from '@nestjs/swagger'; -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { PersonResponseDto } from 'src/domain/person/person.dto'; -import { SearchSuggestionRequestDto } from 'src/domain/search/dto/search-suggestion.dto'; +import { SearchService } from 'src/domain/search/search.service'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { PersonResponseDto } from 'src/dtos/person.dto'; import { MetadataSearchDto, PlacesResponseDto, SearchDto, + SearchExploreResponseDto, SearchPeopleDto, SearchPlacesDto, + SearchResponseDto, + SearchSuggestionRequestDto, SmartSearchDto, -} from 'src/domain/search/dto/search.dto'; -import { SearchExploreResponseDto } from 'src/domain/search/response-dto/search-explore.response.dto'; -import { SearchResponseDto } from 'src/domain/search/response-dto/search-response.dto'; -import { SearchService } from 'src/domain/search/search.service'; +} from 'src/dtos/search.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; @ApiTags('Search') diff --git a/server/src/controllers/server-info.controller.ts b/server/src/controllers/server-info.controller.ts index aae617493..9937acde8 100644 --- a/server/src/controllers/server-info.controller.ts +++ b/server/src/controllers/server-info.controller.ts @@ -1,5 +1,6 @@ import { Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; +import { ServerInfoService } from 'src/domain/server-info/server-info.service'; import { ServerConfigDto, ServerFeaturesDto, @@ -9,8 +10,7 @@ import { ServerStatsResponseDto, ServerThemeDto, ServerVersionResponseDto, -} from 'src/domain/server-info/server-info.dto'; -import { ServerInfoService } from 'src/domain/server-info/server-info.service'; +} from 'src/dtos/server-info.dto'; import { AdminRoute, Authenticated, PublicRoute } from 'src/middleware/auth.guard'; @ApiTags('Server Info') diff --git a/server/src/controllers/shared-link.controller.ts b/server/src/controllers/shared-link.controller.ts index 1e03a5c42..90bbd6ee1 100644 --- a/server/src/controllers/shared-link.controller.ts +++ b/server/src/controllers/shared-link.controller.ts @@ -1,13 +1,17 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query, Req, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; -import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; -import { AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { IMMICH_SHARED_LINK_ACCESS_COOKIE } from 'src/domain/auth/auth.constant'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { SharedLinkResponseDto } from 'src/domain/shared-link/shared-link-response.dto'; -import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; +import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto'; +import { AssetIdsDto } from 'src/dtos/asset.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { + SharedLinkCreateDto, + SharedLinkEditDto, + SharedLinkPasswordDto, + SharedLinkResponseDto, +} from 'src/dtos/shared-link.dto'; import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/system-config.controller.ts b/server/src/controllers/system-config.controller.ts index d10bccee0..34f9f2e0e 100644 --- a/server/src/controllers/system-config.controller.ts +++ b/server/src/controllers/system-config.controller.ts @@ -1,9 +1,9 @@ import { Body, Controller, Get, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { SystemConfigDto } from 'src/domain/system-config/dto/system-config.dto'; -import { SystemConfigTemplateStorageOptionDto } from 'src/domain/system-config/response-dto/system-config-template-storage-option.dto'; import { MapThemeDto } from 'src/domain/system-config/system-config-map-theme.dto'; import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config-storage-template.dto'; +import { SystemConfigDto } from 'src/dtos/system-config.dto'; import { AdminRoute, Authenticated } from 'src/middleware/auth.guard'; @ApiTags('System Config') diff --git a/server/src/controllers/tag.controller.ts b/server/src/controllers/tag.controller.ts index e914e577e..bbca4a05d 100644 --- a/server/src/controllers/tag.controller.ts +++ b/server/src/controllers/tag.controller.ts @@ -1,12 +1,11 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; -import { AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { TagResponseDto } from 'src/domain/tag/tag-response.dto'; -import { CreateTagDto, UpdateTagDto } from 'src/domain/tag/tag.dto'; import { TagService } from 'src/domain/tag/tag.service'; +import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; +import { AssetIdsDto } from 'src/dtos/asset.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { CreateTagDto, TagResponseDto, UpdateTagDto } from 'src/dtos/tag.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; import { UUIDParamDto } from 'src/validation'; diff --git a/server/src/controllers/trash.controller.ts b/server/src/controllers/trash.controller.ts index 2c0b0c946..5ea692d48 100644 --- a/server/src/controllers/trash.controller.ts +++ b/server/src/controllers/trash.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; import { TrashService } from 'src/domain/trash/trash.service'; +import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; @ApiTags('Trash') diff --git a/server/src/controllers/user.controller.ts b/server/src/controllers/user.controller.ts index e573584ad..9fc0ff320 100644 --- a/server/src/controllers/user.controller.ts +++ b/server/src/controllers/user.controller.ts @@ -16,14 +16,10 @@ import { } from '@nestjs/common'; import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { CreateProfileImageDto } from 'src/domain/user/dto/create-profile-image.dto'; -import { CreateUserDto } from 'src/domain/user/dto/create-user.dto'; -import { DeleteUserDto } from 'src/domain/user/dto/delete-user.dto'; -import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; -import { CreateProfileImageResponseDto } from 'src/domain/user/response-dto/create-profile-image-response.dto'; -import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; import { UserService } from 'src/domain/user/user.service'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { CreateProfileImageDto, CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto'; +import { CreateUserDto, DeleteUserDto, UpdateUserDto, UserResponseDto } from 'src/dtos/user.dto'; import { sendFile } from 'src/immich/app.utils'; import { AdminRoute, Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { FileUploadInterceptor, Route } from 'src/middleware/file-upload.interceptor'; diff --git a/server/src/cores/access.core.ts b/server/src/cores/access.core.ts index f9e22bb6b..1c0b1dabb 100644 --- a/server/src/cores/access.core.ts +++ b/server/src/cores/access.core.ts @@ -1,5 +1,5 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { SharedLinkEntity } from 'src/entities/shared-link.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { setDifference, setIsEqual, setUnion } from 'src/utils'; diff --git a/server/src/cores/system-config.core.ts b/server/src/cores/system-config.core.ts index 295a0e5ed..a6692fa18 100644 --- a/server/src/cores/system-config.core.ts +++ b/server/src/cores/system-config.core.ts @@ -6,7 +6,7 @@ import { load as loadYaml } from 'js-yaml'; import * as _ from 'lodash'; import { Subject } from 'rxjs'; import { QueueName } from 'src/domain/job/job.constants'; -import { SystemConfigDto } from 'src/domain/system-config/dto/system-config.dto'; +import { SystemConfigDto } from 'src/dtos/system-config.dto'; import { AudioCodec, CQMode, diff --git a/server/src/cores/user.core.ts b/server/src/cores/user.core.ts index d91f2bae5..1640e8d07 100644 --- a/server/src/cores/user.core.ts +++ b/server/src/cores/user.core.ts @@ -1,6 +1,6 @@ import { BadRequestException, ForbiddenException } from '@nestjs/common'; import sanitize from 'sanitize-filename'; -import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; +import { UserResponseDto } from 'src/dtos/user.dto'; import { LibraryType } from 'src/entities/library.entity'; import { UserEntity } from 'src/entities/user.entity'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/domain/activity/activity.service.ts b/server/src/domain/activity/activity.service.ts index 81d77fa8d..ff310cb5d 100644 --- a/server/src/domain/activity/activity.service.ts +++ b/server/src/domain/activity/activity.service.ts @@ -10,8 +10,8 @@ import { ReactionLevel, ReactionType, mapActivity, -} from 'src/domain/activity/activity.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +} from 'src/dtos/activity.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { ActivityEntity } from 'src/entities/activity.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IActivityRepository } from 'src/interfaces/activity.repository'; diff --git a/server/src/domain/activity/activity.spec.ts b/server/src/domain/activity/activity.spec.ts index 467540be3..6013f0ff0 100644 --- a/server/src/domain/activity/activity.spec.ts +++ b/server/src/domain/activity/activity.spec.ts @@ -1,6 +1,6 @@ import { BadRequestException } from '@nestjs/common'; -import { ReactionType } from 'src/domain/activity/activity.dto'; import { ActivityService } from 'src/domain/activity/activity.service'; +import { ReactionType } from 'src/dtos/activity.dto'; import { IActivityRepository } from 'src/interfaces/activity.repository'; import { activityStub } from 'test/fixtures/activity.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/album/album.service.spec.ts b/server/src/domain/album/album.service.spec.ts index 5b3a91ecf..41b505ea6 100644 --- a/server/src/domain/album/album.service.spec.ts +++ b/server/src/domain/album/album.service.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException } from '@nestjs/common'; import _ from 'lodash'; import { AlbumService } from 'src/domain/album/album.service'; -import { BulkIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; +import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; diff --git a/server/src/domain/album/album.service.ts b/server/src/domain/album/album.service.ts index 4d459ea44..ea7178bed 100644 --- a/server/src/domain/album/album.service.ts +++ b/server/src/domain/album/album.service.ts @@ -1,19 +1,19 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { AccessCore, Permission } from 'src/cores/access.core'; import { + AddUsersDto, AlbumCountResponseDto, + AlbumInfoDto, AlbumResponseDto, + CreateAlbumDto, + GetAlbumsDto, + UpdateAlbumDto, mapAlbum, mapAlbumWithAssets, mapAlbumWithoutAssets, -} from 'src/domain/album/album-response.dto'; -import { AddUsersDto } from 'src/domain/album/dto/album-add-users.dto'; -import { CreateAlbumDto } from 'src/domain/album/dto/album-create.dto'; -import { UpdateAlbumDto } from 'src/domain/album/dto/album-update.dto'; -import { AlbumInfoDto } from 'src/domain/album/dto/album.dto'; -import { GetAlbumsDto } from 'src/domain/album/dto/get-albums.dto'; -import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +} from 'src/dtos/album.dto'; +import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { AlbumEntity } from 'src/entities/album.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { UserEntity } from 'src/entities/user.entity'; diff --git a/server/src/domain/album/dto/album-add-users.dto.ts b/server/src/domain/album/dto/album-add-users.dto.ts deleted file mode 100644 index 1a6be4823..000000000 --- a/server/src/domain/album/dto/album-add-users.dto.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { ArrayNotEmpty } from 'class-validator'; -import { ValidateUUID } from 'src/validation'; - -export class AddUsersDto { - @ValidateUUID({ each: true }) - @ArrayNotEmpty() - sharedUserIds!: string[]; -} diff --git a/server/src/domain/album/dto/album-create.dto.ts b/server/src/domain/album/dto/album-create.dto.ts deleted file mode 100644 index 1b4a75332..000000000 --- a/server/src/domain/album/dto/album-create.dto.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsString } from 'class-validator'; -import { Optional, ValidateUUID } from 'src/validation'; - -export class CreateAlbumDto { - @IsString() - @ApiProperty() - albumName!: string; - - @IsString() - @Optional() - description?: string; - - @ValidateUUID({ optional: true, each: true }) - sharedWithUserIds?: string[]; - - @ValidateUUID({ optional: true, each: true }) - assetIds?: string[]; -} diff --git a/server/src/domain/album/dto/album-update.dto.ts b/server/src/domain/album/dto/album-update.dto.ts deleted file mode 100644 index cf2d5f8c2..000000000 --- a/server/src/domain/album/dto/album-update.dto.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum, IsString } from 'class-validator'; -import { AssetOrder } from 'src/entities/album.entity'; -import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; - -export class UpdateAlbumDto { - @Optional() - @IsString() - albumName?: string; - - @Optional() - @IsString() - description?: string; - - @ValidateUUID({ optional: true }) - albumThumbnailAssetId?: string; - - @ValidateBoolean({ optional: true }) - isActivityEnabled?: boolean; - - @IsEnum(AssetOrder) - @Optional() - @ApiProperty({ enum: AssetOrder, enumName: 'AssetOrder' }) - order?: AssetOrder; -} diff --git a/server/src/domain/album/dto/album.dto.ts b/server/src/domain/album/dto/album.dto.ts deleted file mode 100644 index fe0eb0d5c..000000000 --- a/server/src/domain/album/dto/album.dto.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ValidateBoolean } from 'src/validation'; - -export class AlbumInfoDto { - @ValidateBoolean({ optional: true }) - withoutAssets?: boolean; -} diff --git a/server/src/domain/album/dto/get-albums.dto.ts b/server/src/domain/album/dto/get-albums.dto.ts deleted file mode 100644 index 15e4f1cf2..000000000 --- a/server/src/domain/album/dto/get-albums.dto.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ValidateBoolean, ValidateUUID } from 'src/validation'; - -export class GetAlbumsDto { - @ValidateBoolean({ optional: true }) - /** - * true: only shared albums - * false: only non-shared own albums - * undefined: shared and owned albums - */ - shared?: boolean; - - /** - * Only returns albums that contain the asset - * Ignores the shared parameter - * undefined: get all albums - */ - @ValidateUUID({ optional: true }) - assetId?: string; -} diff --git a/server/src/domain/api-key/api-key.service.ts b/server/src/domain/api-key/api-key.service.ts index 540c1d71f..6c874895b 100644 --- a/server/src/domain/api-key/api-key.service.ts +++ b/server/src/domain/api-key/api-key.service.ts @@ -1,6 +1,6 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto } from 'src/domain/api-key/api-key.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto } from 'src/dtos/api-key.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { APIKeyEntity } from 'src/entities/api-key.entity'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/domain/asset/asset.service.spec.ts b/server/src/domain/asset/asset.service.spec.ts index 7b49cfef9..a3603c3da 100644 --- a/server/src/domain/asset/asset.service.spec.ts +++ b/server/src/domain/asset/asset.service.spec.ts @@ -1,10 +1,9 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { when } from 'jest-when'; -import { AssetService, UploadFieldName } from 'src/domain/asset/asset.service'; -import { AssetJobName } from 'src/domain/asset/dto/asset-ids.dto'; -import { AssetStatsResponseDto } from 'src/domain/asset/dto/asset-statistics.dto'; -import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AssetService } from 'src/domain/asset/asset.service'; import { JobName } from 'src/domain/job/job.constants'; +import { mapAsset } from 'src/dtos/asset-response.dto'; +import { AssetJobName, AssetStatsResponseDto, UploadFieldName } from 'src/dtos/asset.dto'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; import { AssetStats, IAssetRepository, TimeBucketSize } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/asset/asset.service.ts b/server/src/domain/asset/asset.service.ts index 38446b576..51a587a67 100644 --- a/server/src/domain/asset/asset.service.ts +++ b/server/src/domain/asset/asset.service.ts @@ -6,25 +6,29 @@ import sanitize from 'sanitize-filename'; import { AccessCore, Permission } from 'src/cores/access.core'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { AssetJobName, AssetJobsDto } from 'src/domain/asset/dto/asset-ids.dto'; -import { UpdateStackParentDto } from 'src/domain/asset/dto/asset-stack.dto'; -import { AssetStatsDto, mapStats } from 'src/domain/asset/dto/asset-statistics.dto'; -import { AssetBulkDeleteDto, AssetBulkUpdateDto, UpdateAssetDto } from 'src/domain/asset/dto/asset.dto'; -import { MapMarkerDto } from 'src/domain/asset/dto/map-marker.dto'; -import { MemoryLaneDto } from 'src/domain/asset/dto/memory-lane.dto'; -import { TimeBucketAssetDto, TimeBucketDto } from 'src/domain/asset/dto/time-bucket.dto'; +import { mimeTypes } from 'src/domain/domain.constant'; +import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; +import { IAssetDeletionJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; import { AssetResponseDto, MemoryLaneResponseDto, SanitizedAssetResponseDto, mapAsset, -} from 'src/domain/asset/response-dto/asset-response.dto'; -import { MapMarkerResponseDto } from 'src/domain/asset/response-dto/map-marker-response.dto'; -import { TimeBucketResponseDto } from 'src/domain/asset/response-dto/time-bucket-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { mimeTypes } from 'src/domain/domain.constant'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; -import { IAssetDeletionJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; +} from 'src/dtos/asset-response.dto'; +import { + AssetBulkDeleteDto, + AssetBulkUpdateDto, + AssetJobName, + AssetJobsDto, + AssetStatsDto, + UpdateAssetDto, + UploadFieldName, + mapStats, +} from 'src/dtos/asset.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { MapMarkerDto, MapMarkerResponseDto, MemoryLaneDto } from 'src/dtos/search.dto'; +import { UpdateStackParentDto } from 'src/dtos/stack.dto'; +import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { LibraryType } from 'src/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; @@ -39,13 +43,6 @@ import { ISystemConfigRepository } from 'src/interfaces/system-config.repository import { IUserRepository } from 'src/interfaces/user.repository'; import { usePagination } from 'src/utils'; -export enum UploadFieldName { - ASSET_DATA = 'assetData', - LIVE_PHOTO_DATA = 'livePhotoData', - SIDECAR_DATA = 'sidecarData', - PROFILE_DATA = 'file', -} - export interface UploadRequest { auth: AuthDto | null; fieldName: UploadFieldName; diff --git a/server/src/domain/asset/dto/asset-ids.dto.ts b/server/src/domain/asset/dto/asset-ids.dto.ts deleted file mode 100644 index ea875e85e..000000000 --- a/server/src/domain/asset/dto/asset-ids.dto.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum } from 'class-validator'; -import { ValidateUUID } from 'src/validation'; - -export class AssetIdsDto { - @ValidateUUID({ each: true }) - assetIds!: string[]; -} - -export enum AssetJobName { - REGENERATE_THUMBNAIL = 'regenerate-thumbnail', - REFRESH_METADATA = 'refresh-metadata', - TRANSCODE_VIDEO = 'transcode-video', -} - -export class AssetJobsDto extends AssetIdsDto { - @ApiProperty({ enumName: 'AssetJobName', enum: AssetJobName }) - @IsEnum(AssetJobName) - name!: AssetJobName; -} diff --git a/server/src/domain/asset/dto/asset-statistics.dto.ts b/server/src/domain/asset/dto/asset-statistics.dto.ts deleted file mode 100644 index 93e007029..000000000 --- a/server/src/domain/asset/dto/asset-statistics.dto.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { AssetType } from 'src/entities/asset.entity'; -import { AssetStats } from 'src/interfaces/asset.repository'; -import { ValidateBoolean } from 'src/validation'; - -export class AssetStatsDto { - @ValidateBoolean({ optional: true }) - isArchived?: boolean; - - @ValidateBoolean({ optional: true }) - isFavorite?: boolean; - - @ValidateBoolean({ optional: true }) - isTrashed?: boolean; -} - -export class AssetStatsResponseDto { - @ApiProperty({ type: 'integer' }) - images!: number; - - @ApiProperty({ type: 'integer' }) - videos!: number; - - @ApiProperty({ type: 'integer' }) - total!: number; -} - -export const mapStats = (stats: AssetStats): AssetStatsResponseDto => { - return { - images: stats[AssetType.IMAGE], - videos: stats[AssetType.VIDEO], - total: Object.values(stats).reduce((total, value) => total + value, 0), - }; -}; diff --git a/server/src/domain/asset/dto/asset.dto.ts b/server/src/domain/asset/dto/asset.dto.ts deleted file mode 100644 index a93a59ae3..000000000 --- a/server/src/domain/asset/dto/asset.dto.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Type } from 'class-transformer'; -import { - IsDateString, - IsInt, - IsLatitude, - IsLongitude, - IsNotEmpty, - IsPositive, - IsString, - ValidateIf, -} from 'class-validator'; -import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; - -export class DeviceIdDto { - @IsNotEmpty() - @IsString() - deviceId!: string; -} - -const hasGPS = (o: { latitude: undefined; longitude: undefined }) => - o.latitude !== undefined || o.longitude !== undefined; -const ValidateGPS = () => ValidateIf(hasGPS); - -export class UpdateAssetBase { - @ValidateBoolean({ optional: true }) - isFavorite?: boolean; - - @ValidateBoolean({ optional: true }) - isArchived?: boolean; - - @Optional() - @IsDateString() - dateTimeOriginal?: string; - - @ValidateGPS() - @IsLatitude() - @IsNotEmpty() - latitude?: number; - - @ValidateGPS() - @IsLongitude() - @IsNotEmpty() - longitude?: number; -} - -export class AssetBulkUpdateDto extends UpdateAssetBase { - @ValidateUUID({ each: true }) - ids!: string[]; - - @ValidateUUID({ optional: true }) - stackParentId?: string; - - @ValidateBoolean({ optional: true }) - removeParent?: boolean; -} - -export class UpdateAssetDto extends UpdateAssetBase { - @Optional() - @IsString() - description?: string; -} - -export class RandomAssetsDto { - @Optional() - @IsInt() - @IsPositive() - @Type(() => Number) - count?: number; -} - -export class AssetBulkDeleteDto extends BulkIdsDto { - @ValidateBoolean({ optional: true }) - force?: boolean; -} diff --git a/server/src/domain/asset/dto/map-marker.dto.ts b/server/src/domain/asset/dto/map-marker.dto.ts deleted file mode 100644 index 158750e51..000000000 --- a/server/src/domain/asset/dto/map-marker.dto.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { ValidateBoolean, ValidateDate } from 'src/validation'; - -export class MapMarkerDto { - @ValidateBoolean({ optional: true }) - isArchived?: boolean; - - @ValidateBoolean({ optional: true }) - isFavorite?: boolean; - - @ValidateDate({ optional: true }) - fileCreatedAfter?: Date; - - @ValidateDate({ optional: true }) - fileCreatedBefore?: Date; - - @ValidateBoolean({ optional: true }) - withPartners?: boolean; -} diff --git a/server/src/domain/asset/dto/memory-lane.dto.ts b/server/src/domain/asset/dto/memory-lane.dto.ts deleted file mode 100644 index 43f74aff1..000000000 --- a/server/src/domain/asset/dto/memory-lane.dto.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Type } from 'class-transformer'; -import { IsInt, Max, Min } from 'class-validator'; - -export class MemoryLaneDto { - @IsInt() - @Type(() => Number) - @Max(31) - @Min(1) - @ApiProperty({ type: 'integer' }) - day!: number; - - @IsInt() - @Type(() => Number) - @Max(12) - @Min(1) - @ApiProperty({ type: 'integer' }) - month!: number; -} diff --git a/server/src/domain/asset/response-dto/map-marker-response.dto.ts b/server/src/domain/asset/response-dto/map-marker-response.dto.ts deleted file mode 100644 index f5148883f..000000000 --- a/server/src/domain/asset/response-dto/map-marker-response.dto.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; - -export class MapMarkerResponseDto { - @ApiProperty() - id!: string; - - @ApiProperty({ format: 'double' }) - lat!: number; - - @ApiProperty({ format: 'double' }) - lon!: number; - - @ApiProperty() - city!: string | null; - - @ApiProperty() - state!: string | null; - - @ApiProperty() - country!: string | null; -} diff --git a/server/src/domain/asset/response-dto/smart-info-response.dto.ts b/server/src/domain/asset/response-dto/smart-info-response.dto.ts deleted file mode 100644 index c55c7ffb3..000000000 --- a/server/src/domain/asset/response-dto/smart-info-response.dto.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { SmartInfoEntity } from 'src/entities/smart-info.entity'; - -export class SmartInfoResponseDto { - tags?: string[] | null; - objects?: string[] | null; -} - -export function mapSmartInfo(entity: SmartInfoEntity): SmartInfoResponseDto { - return { - tags: entity.tags, - objects: entity.objects, - }; -} diff --git a/server/src/domain/asset/response-dto/time-bucket-response.dto.ts b/server/src/domain/asset/response-dto/time-bucket-response.dto.ts deleted file mode 100644 index e143dde46..000000000 --- a/server/src/domain/asset/response-dto/time-bucket-response.dto.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; - -export class TimeBucketResponseDto { - @ApiProperty({ type: 'string' }) - timeBucket!: string; - - @ApiProperty({ type: 'integer' }) - count!: number; -} diff --git a/server/src/domain/audit/audit.service.ts b/server/src/domain/audit/audit.service.ts index 91acb54d9..b84f3824d 100644 --- a/server/src/domain/audit/audit.service.ts +++ b/server/src/domain/audit/audit.service.ts @@ -3,6 +3,8 @@ import { DateTime } from 'luxon'; import { resolve } from 'node:path'; import { AccessCore, Permission } from 'src/cores/access.core'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; +import { AUDIT_LOG_MAX_DURATION } from 'src/domain/domain.constant'; +import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; import { AuditDeletesDto, AuditDeletesResponseDto, @@ -10,10 +12,8 @@ import { FileChecksumResponseDto, FileReportItemDto, PathEntityType, -} from 'src/domain/audit/audit.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { AUDIT_LOG_MAX_DURATION } from 'src/domain/domain.constant'; -import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; +} from 'src/dtos/audit.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { DatabaseAction } from 'src/entities/audit.entity'; import { AssetPathType, PersonPathType, UserPathType } from 'src/entities/move.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/auth/auth.service.spec.ts b/server/src/domain/auth/auth.service.spec.ts index e091cdcd9..37c759937 100644 --- a/server/src/domain/auth/auth.service.spec.ts +++ b/server/src/domain/auth/auth.service.spec.ts @@ -3,8 +3,8 @@ import { IncomingHttpHeaders } from 'node:http'; import { Issuer, generators } from 'openid-client'; import { Socket } from 'socket.io'; import { AuthType } from 'src/domain/auth/auth.constant'; -import { AuthDto, SignUpDto } from 'src/domain/auth/auth.dto'; import { AuthService } from 'src/domain/auth/auth.service'; +import { AuthDto, SignUpDto } from 'src/dtos/auth.dto'; import { UserEntity } from 'src/entities/user.entity'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/domain/auth/auth.service.ts b/server/src/domain/auth/auth.service.ts index 2d807a249..9ae41a4fc 100644 --- a/server/src/domain/auth/auth.service.ts +++ b/server/src/domain/auth/auth.service.ts @@ -35,8 +35,8 @@ import { SignUpDto, mapLoginResponse, mapUserToken, -} from 'src/domain/auth/auth.dto'; -import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +} from 'src/dtos/auth.dto'; +import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { SystemConfig } from 'src/entities/system-config.entity'; import { UserEntity } from 'src/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/download/download.service.spec.ts b/server/src/domain/download/download.service.spec.ts index 6e1eafbec..cfdff82b9 100644 --- a/server/src/domain/download/download.service.spec.ts +++ b/server/src/domain/download/download.service.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; -import { DownloadResponseDto } from 'src/domain/download/download.dto'; import { DownloadService } from 'src/domain/download/download.service'; +import { DownloadResponseDto } from 'src/dtos/download.dto'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { CacheControl, ImmichFileResponse } from 'src/utils'; diff --git a/server/src/domain/download/download.service.ts b/server/src/domain/download/download.service.ts index 8c0168a6c..b03951764 100644 --- a/server/src/domain/download/download.service.ts +++ b/server/src/domain/download/download.service.ts @@ -1,10 +1,10 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { parse } from 'node:path'; import { AccessCore, Permission } from 'src/cores/access.core'; -import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; -import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/domain/download/download.dto'; +import { AssetIdsDto } from 'src/dtos/asset.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/job/job.service.ts b/server/src/domain/job/job.service.ts index 192b093c1..8650b92d4 100644 --- a/server/src/domain/job/job.service.ts +++ b/server/src/domain/job/job.service.ts @@ -1,8 +1,8 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; -import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; import { ConcurrentQueueName, JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; -import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/domain/job/job.dto'; +import { mapAsset } from 'src/dtos/asset-response.dto'; +import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/dtos/job.dto'; import { AssetType } from 'src/entities/asset.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/domain/library/library.service.spec.ts index f34b6d5be..81bf1cc86 100644 --- a/server/src/domain/library/library.service.spec.ts +++ b/server/src/domain/library/library.service.spec.ts @@ -5,8 +5,8 @@ import { Stats } from 'node:fs'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { JobName } from 'src/domain/job/job.constants'; import { ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; -import { mapLibrary } from 'src/domain/library/library.dto'; import { LibraryService } from 'src/domain/library/library.service'; +import { mapLibrary } from 'src/dtos/library.dto'; import { AssetType } from 'src/entities/asset.entity'; import { LibraryType } from 'src/entities/library.entity'; import { SystemConfig, SystemConfigKey } from 'src/entities/system-config.entity'; diff --git a/server/src/domain/library/library.service.ts b/server/src/domain/library/library.service.ts index 1fc009149..f7b298797 100644 --- a/server/src/domain/library/library.service.ts +++ b/server/src/domain/library/library.service.ts @@ -22,7 +22,7 @@ import { ValidateLibraryImportPathResponseDto, ValidateLibraryResponseDto, mapLibrary, -} from 'src/domain/library/library.dto'; +} from 'src/dtos/library.dto'; import { AssetType } from 'src/entities/asset.entity'; import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/media/media.service.ts b/server/src/domain/media/media.service.ts index c254689b4..5c217f2a8 100644 --- a/server/src/domain/media/media.service.ts +++ b/server/src/domain/media/media.service.ts @@ -13,7 +13,7 @@ import { VAAPIConfig, VP9Config, } from 'src/domain/media/media.util'; -import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; +import { SystemConfigFFmpegDto } from 'src/dtos/system-config-ffmpeg.dto'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { AssetPathType } from 'src/entities/move.entity'; import { diff --git a/server/src/domain/media/media.util.ts b/server/src/domain/media/media.util.ts index 3e58ca81a..d6a5b53a6 100644 --- a/server/src/domain/media/media.util.ts +++ b/server/src/domain/media/media.util.ts @@ -1,4 +1,4 @@ -import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; +import { SystemConfigFFmpegDto } from 'src/dtos/system-config-ffmpeg.dto'; import { CQMode, ToneMapping, TranscodeHWAccel, TranscodeTarget, VideoCodec } from 'src/entities/system-config.entity'; import { AudioStreamInfo, diff --git a/server/src/domain/partner/partner.service.spec.ts b/server/src/domain/partner/partner.service.spec.ts index 7d4821282..1256a9ca0 100644 --- a/server/src/domain/partner/partner.service.spec.ts +++ b/server/src/domain/partner/partner.service.spec.ts @@ -1,6 +1,6 @@ import { BadRequestException } from '@nestjs/common'; -import { PartnerResponseDto } from 'src/domain/partner/partner.dto'; import { PartnerService } from 'src/domain/partner/partner.service'; +import { PartnerResponseDto } from 'src/dtos/partner.dto'; import { UserAvatarColor } from 'src/entities/user.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IPartnerRepository, PartnerDirection } from 'src/interfaces/partner.repository'; diff --git a/server/src/domain/partner/partner.service.ts b/server/src/domain/partner/partner.service.ts index 34a88a7ea..af3f98061 100644 --- a/server/src/domain/partner/partner.service.ts +++ b/server/src/domain/partner/partner.service.ts @@ -1,8 +1,8 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { AccessCore, Permission } from 'src/cores/access.core'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { PartnerResponseDto, UpdatePartnerDto } from 'src/domain/partner/partner.dto'; -import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { PartnerResponseDto, UpdatePartnerDto } from 'src/dtos/partner.dto'; +import { mapUser } from 'src/dtos/user.dto'; import { PartnerEntity } from 'src/entities/partner.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IPartnerRepository, PartnerDirection, PartnerIds } from 'src/interfaces/partner.repository'; diff --git a/server/src/domain/person/person.service.spec.ts b/server/src/domain/person/person.service.spec.ts index 9da66e868..3f555e34f 100644 --- a/server/src/domain/person/person.service.spec.ts +++ b/server/src/domain/person/person.service.spec.ts @@ -1,8 +1,8 @@ import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { BulkIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { JobName } from 'src/domain/job/job.constants'; -import { PersonResponseDto, mapFaces, mapPerson } from 'src/domain/person/person.dto'; import { PersonService } from 'src/domain/person/person.service'; +import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; +import { PersonResponseDto, mapFaces, mapPerson } from 'src/dtos/person.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { Colorspace, SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/person/person.service.ts b/server/src/domain/person/person.service.ts index cd7ba9224..7da482966 100644 --- a/server/src/domain/person/person.service.ts +++ b/server/src/domain/person/person.service.ts @@ -2,13 +2,13 @@ import { BadRequestException, Inject, Injectable, NotFoundException } from '@nes import { AccessCore, Permission } from 'src/cores/access.core'; import { StorageCore } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { BulkIdErrorReason, BulkIdResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; import { IBaseJob, IDeferrableJob, IEntityJob } from 'src/domain/job/job.interface'; import { FACE_THUMBNAIL_SIZE } from 'src/domain/media/media.constant'; +import { BulkIdErrorReason, BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; +import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { AssetFaceResponseDto, AssetFaceUpdateDto, @@ -23,7 +23,7 @@ import { PersonUpdateDto, mapFaces, mapPerson, -} from 'src/domain/person/person.dto'; +} from 'src/dtos/person.dto'; import { PersonPathType } from 'src/entities/move.entity'; import { PersonEntity } from 'src/entities/person.entity'; import { ImmichLogger } from 'src/infra/logger'; diff --git a/server/src/domain/search/dto/search-suggestion.dto.ts b/server/src/domain/search/dto/search-suggestion.dto.ts deleted file mode 100644 index f702293d0..000000000 --- a/server/src/domain/search/dto/search-suggestion.dto.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { Optional } from 'src/validation'; - -export enum SearchSuggestionType { - COUNTRY = 'country', - STATE = 'state', - CITY = 'city', - CAMERA_MAKE = 'camera-make', - CAMERA_MODEL = 'camera-model', -} - -export class SearchSuggestionRequestDto { - @IsEnum(SearchSuggestionType) - @IsNotEmpty() - @ApiProperty({ enumName: 'SearchSuggestionType', enum: SearchSuggestionType }) - type!: SearchSuggestionType; - - @IsString() - @Optional() - country?: string; - - @IsString() - @Optional() - state?: string; - - @IsString() - @Optional() - make?: string; - - @IsString() - @Optional() - model?: string; -} diff --git a/server/src/domain/search/response-dto/search-explore.response.dto.ts b/server/src/domain/search/response-dto/search-explore.response.dto.ts deleted file mode 100644 index 33689b979..000000000 --- a/server/src/domain/search/response-dto/search-explore.response.dto.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; - -class SearchExploreItem { - value!: string; - data!: AssetResponseDto; -} - -export class SearchExploreResponseDto { - fieldName!: string; - items!: SearchExploreItem[]; -} diff --git a/server/src/domain/search/response-dto/search-response.dto.ts b/server/src/domain/search/response-dto/search-response.dto.ts deleted file mode 100644 index 53563a9ac..000000000 --- a/server/src/domain/search/response-dto/search-response.dto.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { AlbumResponseDto } from 'src/domain/album/album-response.dto'; -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; - -class SearchFacetCountResponseDto { - @ApiProperty({ type: 'integer' }) - count!: number; - value!: string; -} - -class SearchFacetResponseDto { - fieldName!: string; - counts!: SearchFacetCountResponseDto[]; -} - -class SearchAlbumResponseDto { - @ApiProperty({ type: 'integer' }) - total!: number; - @ApiProperty({ type: 'integer' }) - count!: number; - items!: AlbumResponseDto[]; - facets!: SearchFacetResponseDto[]; -} - -class SearchAssetResponseDto { - @ApiProperty({ type: 'integer' }) - total!: number; - @ApiProperty({ type: 'integer' }) - count!: number; - items!: AssetResponseDto[]; - facets!: SearchFacetResponseDto[]; - nextPage!: string | null; -} - -export class SearchResponseDto { - albums!: SearchAlbumResponseDto; - assets!: SearchAssetResponseDto; -} diff --git a/server/src/domain/search/search.service.spec.ts b/server/src/domain/search/search.service.spec.ts index f72212809..7f83f2ff0 100644 --- a/server/src/domain/search/search.service.spec.ts +++ b/server/src/domain/search/search.service.spec.ts @@ -1,6 +1,6 @@ -import { mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; -import { SearchDto } from 'src/domain/search/dto/search.dto'; import { SearchService } from 'src/domain/search/search.service'; +import { mapAsset } from 'src/dtos/asset-response.dto'; +import { SearchDto } from 'src/dtos/search.dto'; import { SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; diff --git a/server/src/domain/search/search.service.ts b/server/src/domain/search/search.service.ts index cedee68d0..30819dc46 100644 --- a/server/src/domain/search/search.service.ts +++ b/server/src/domain/search/search.service.ts @@ -1,19 +1,20 @@ import { Inject, Injectable } from '@nestjs/common'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; -import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { PersonResponseDto } from 'src/domain/person/person.dto'; -import { SearchSuggestionRequestDto, SearchSuggestionType } from 'src/domain/search/dto/search-suggestion.dto'; +import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { PersonResponseDto } from 'src/dtos/person.dto'; import { MetadataSearchDto, PlacesResponseDto, SearchDto, SearchPeopleDto, SearchPlacesDto, + SearchResponseDto, + SearchSuggestionRequestDto, + SearchSuggestionType, SmartSearchDto, mapPlaces, -} from 'src/domain/search/dto/search.dto'; -import { SearchResponseDto } from 'src/domain/search/response-dto/search-response.dto'; +} from 'src/dtos/search.dto'; import { AssetOrder } from 'src/entities/album.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/domain/server-info/server-info.service.ts index 13921949c..a76ae4022 100644 --- a/server/src/domain/server-info/server-info.service.ts +++ b/server/src/domain/server-info/server-info.service.ts @@ -11,7 +11,7 @@ import { ServerPingResponse, ServerStatsResponseDto, UsageByUserDto, -} from 'src/domain/server-info/server-info.dto'; +} from 'src/dtos/server-info.dto'; import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; import { ImmichLogger } from 'src/infra/logger'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; diff --git a/server/src/domain/shared-link/shared-link.dto.ts b/server/src/domain/shared-link/shared-link.dto.ts deleted file mode 100644 index 73928aac2..000000000 --- a/server/src/domain/shared-link/shared-link.dto.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum, IsString } from 'class-validator'; -import { SharedLinkType } from 'src/entities/shared-link.entity'; -import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; - -export class SharedLinkCreateDto { - @IsEnum(SharedLinkType) - @ApiProperty({ enum: SharedLinkType, enumName: 'SharedLinkType' }) - type!: SharedLinkType; - - @ValidateUUID({ each: true, optional: true }) - assetIds?: string[]; - - @ValidateUUID({ optional: true }) - albumId?: string; - - @IsString() - @Optional() - description?: string; - - @IsString() - @Optional() - password?: string; - - @ValidateDate({ optional: true, nullable: true }) - expiresAt?: Date | null = null; - - @ValidateBoolean({ optional: true }) - allowUpload?: boolean; - - @ValidateBoolean({ optional: true }) - allowDownload?: boolean = true; - - @ValidateBoolean({ optional: true }) - showMetadata?: boolean = true; -} - -export class SharedLinkEditDto { - @Optional() - description?: string; - - @Optional() - password?: string; - - @Optional({ nullable: true }) - expiresAt?: Date | null; - - @Optional() - allowUpload?: boolean; - - @ValidateBoolean({ optional: true }) - allowDownload?: boolean; - - @ValidateBoolean({ optional: true }) - showMetadata?: boolean; - - /** - * Few clients cannot send null to set the expiryTime to never. - * Setting this flag and not sending expiryAt is considered as null instead. - * Clients that can send null values can ignore this. - */ - @ValidateBoolean({ optional: true }) - changeExpiryTime?: boolean; -} - -export class SharedLinkPasswordDto { - @IsString() - @Optional() - @ApiProperty({ example: 'password' }) - password?: string; - - @IsString() - @Optional() - token?: string; -} diff --git a/server/src/domain/shared-link/shared-link.service.spec.ts b/server/src/domain/shared-link/shared-link.service.spec.ts index 926ec16b1..e5e3ea6e2 100644 --- a/server/src/domain/shared-link/shared-link.service.spec.ts +++ b/server/src/domain/shared-link/shared-link.service.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException, ForbiddenException, UnauthorizedException } from '@nestjs/common'; import _ from 'lodash'; -import { AssetIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; +import { AssetIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { SharedLinkType } from 'src/entities/shared-link.entity'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; diff --git a/server/src/domain/shared-link/shared-link.service.ts b/server/src/domain/shared-link/shared-link.service.ts index e01deee7b..a84a1f120 100644 --- a/server/src/domain/shared-link/shared-link.service.ts +++ b/server/src/domain/shared-link/shared-link.service.ts @@ -1,14 +1,16 @@ import { BadRequestException, ForbiddenException, Inject, Injectable, UnauthorizedException } from '@nestjs/common'; import { AccessCore, Permission } from 'src/cores/access.core'; -import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; -import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto'; +import { AssetIdsDto } from 'src/dtos/asset.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { + SharedLinkCreateDto, + SharedLinkEditDto, + SharedLinkPasswordDto, SharedLinkResponseDto, mapSharedLink, mapSharedLinkWithoutMetadata, -} from 'src/domain/shared-link/shared-link-response.dto'; -import { SharedLinkCreateDto, SharedLinkEditDto, SharedLinkPasswordDto } from 'src/domain/shared-link/shared-link.dto'; +} from 'src/dtos/shared-link.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { SharedLinkEntity, SharedLinkType } from 'src/entities/shared-link.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; diff --git a/server/src/domain/system-config/response-dto/system-config-template-storage-option.dto.ts b/server/src/domain/system-config/response-dto/system-config-template-storage-option.dto.ts deleted file mode 100644 index f0c8b9b64..000000000 --- a/server/src/domain/system-config/response-dto/system-config-template-storage-option.dto.ts +++ /dev/null @@ -1,10 +0,0 @@ -export class SystemConfigTemplateStorageOptionDto { - yearOptions!: string[]; - monthOptions!: string[]; - weekOptions!: string[]; - dayOptions!: string[]; - hourOptions!: string[]; - minuteOptions!: string[]; - secondOptions!: string[]; - presetOptions!: string[]; -} diff --git a/server/src/domain/system-config/system-config.service.ts b/server/src/domain/system-config/system-config.service.ts index d69593d21..c5837dca2 100644 --- a/server/src/domain/system-config/system-config.service.ts +++ b/server/src/domain/system-config/system-config.service.ts @@ -3,8 +3,6 @@ import { OnEvent } from '@nestjs/event-emitter'; import { instanceToPlain } from 'class-transformer'; import _ from 'lodash'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { SystemConfigDto, mapConfig } from 'src/domain/system-config/dto/system-config.dto'; -import { SystemConfigTemplateStorageOptionDto } from 'src/domain/system-config/response-dto/system-config-template-storage-option.dto'; import { supportedDayTokens, supportedHourTokens, @@ -15,6 +13,8 @@ import { supportedWeekTokens, supportedYearTokens, } from 'src/domain/system-config/system-config.constants'; +import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config-storage-template.dto'; +import { SystemConfigDto, mapConfig } from 'src/dtos/system-config.dto'; import { LogLevel, SystemConfig } from 'src/entities/system-config.entity'; import { ImmichLogger } from 'src/infra/logger'; import { diff --git a/server/src/domain/tag/tag.dto.ts b/server/src/domain/tag/tag.dto.ts deleted file mode 100644 index abf9549d8..000000000 --- a/server/src/domain/tag/tag.dto.ts +++ /dev/null @@ -1,21 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; -import { TagType } from 'src/entities/tag.entity'; -import { Optional } from 'src/validation'; - -export class CreateTagDto { - @IsString() - @IsNotEmpty() - name!: string; - - @IsEnum(TagType) - @IsNotEmpty() - @ApiProperty({ enumName: 'TagTypeEnum', enum: TagType }) - type!: TagType; -} - -export class UpdateTagDto { - @IsString() - @Optional() - name?: string; -} diff --git a/server/src/domain/tag/tag.service.spec.ts b/server/src/domain/tag/tag.service.spec.ts index 9f630cdc0..c7aeba9f1 100644 --- a/server/src/domain/tag/tag.service.spec.ts +++ b/server/src/domain/tag/tag.service.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; -import { AssetIdErrorReason } from 'src/domain/asset/response-dto/asset-ids-response.dto'; import { TagService } from 'src/domain/tag/tag.service'; +import { AssetIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { TagType } from 'src/entities/tag.entity'; import { ITagRepository } from 'src/interfaces/tag.repository'; import { assetStub } from 'test/fixtures/asset.stub'; diff --git a/server/src/domain/tag/tag.service.ts b/server/src/domain/tag/tag.service.ts index b04e251f7..b53eac0d7 100644 --- a/server/src/domain/tag/tag.service.ts +++ b/server/src/domain/tag/tag.service.ts @@ -1,10 +1,9 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; -import { AssetIdsDto } from 'src/domain/asset/dto/asset-ids.dto'; -import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { TagResponseDto, mapTag } from 'src/domain/tag/tag-response.dto'; -import { CreateTagDto, UpdateTagDto } from 'src/domain/tag/tag.dto'; +import { AssetIdErrorReason, AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto'; +import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; +import { AssetIdsDto } from 'src/dtos/asset.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { CreateTagDto, TagResponseDto, UpdateTagDto, mapTag } from 'src/dtos/tag.dto'; import { ITagRepository } from 'src/interfaces/tag.repository'; @Injectable() diff --git a/server/src/domain/trash/trash.service.ts b/server/src/domain/trash/trash.service.ts index 2043b4248..9bece663b 100644 --- a/server/src/domain/trash/trash.service.ts +++ b/server/src/domain/trash/trash.service.ts @@ -1,9 +1,9 @@ import { Inject } from '@nestjs/common'; import { DateTime } from 'luxon'; import { AccessCore, Permission } from 'src/cores/access.core'; -import { BulkIdsDto } from 'src/domain/asset/response-dto/asset-ids-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; +import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; diff --git a/server/src/domain/user/dto/create-profile-image.dto.ts b/server/src/domain/user/dto/create-profile-image.dto.ts deleted file mode 100644 index 37a7d1340..000000000 --- a/server/src/domain/user/dto/create-profile-image.dto.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { UploadFieldName } from 'src/domain/asset/asset.service'; - -export class CreateProfileImageDto { - @ApiProperty({ type: 'string', format: 'binary' }) - [UploadFieldName.PROFILE_DATA]!: Express.Multer.File; -} diff --git a/server/src/domain/user/dto/create-user.dto.ts b/server/src/domain/user/dto/create-user.dto.ts deleted file mode 100644 index 7861c58c2..000000000 --- a/server/src/domain/user/dto/create-user.dto.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Transform } from 'class-transformer'; -import { IsEmail, IsNotEmpty, IsNumber, IsPositive, IsString } from 'class-validator'; -import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation'; - -export class CreateUserDto { - @IsEmail({ require_tld: false }) - @Transform(toEmail) - email!: string; - - @IsNotEmpty() - @IsString() - password!: string; - - @IsNotEmpty() - @IsString() - name!: string; - - @Optional({ nullable: true }) - @IsString() - @Transform(toSanitized) - storageLabel?: string | null; - - @ValidateBoolean({ optional: true }) - memoriesEnabled?: boolean; - - @Optional({ nullable: true }) - @IsNumber() - @IsPositive() - @ApiProperty({ type: 'integer', format: 'int64' }) - quotaSizeInBytes?: number | null; - - @ValidateBoolean({ optional: true }) - shouldChangePassword?: boolean; -} - -export class CreateAdminDto { - @IsNotEmpty() - isAdmin!: true; - - @IsEmail({ require_tld: false }) - @Transform(({ value }) => value?.toLowerCase()) - email!: string; - - @IsNotEmpty() - password!: string; - - @IsNotEmpty() - name!: string; -} - -export class CreateUserOAuthDto { - @IsEmail({ require_tld: false }) - @Transform(({ value }) => value?.toLowerCase()) - email!: string; - - @IsNotEmpty() - oauthId!: string; - - name?: string; -} diff --git a/server/src/domain/user/dto/delete-user.dto.ts b/server/src/domain/user/dto/delete-user.dto.ts deleted file mode 100644 index aa41e18aa..000000000 --- a/server/src/domain/user/dto/delete-user.dto.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { ValidateBoolean } from 'src/validation'; - -export class DeleteUserDto { - @ValidateBoolean({ optional: true }) - force?: boolean; -} diff --git a/server/src/domain/user/dto/update-user.dto.spec.ts b/server/src/domain/user/dto/update-user.dto.spec.ts deleted file mode 100644 index 0ad407be3..000000000 --- a/server/src/domain/user/dto/update-user.dto.spec.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { plainToInstance } from 'class-transformer'; -import { validate } from 'class-validator'; -import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; - -describe('update user DTO', () => { - it('should allow emails without a tld', async () => { - const someEmail = 'test@test'; - - const dto = plainToInstance(UpdateUserDto, { - email: someEmail, - id: '3fe388e4-2078-44d7-b36c-39d9dee3a657', - }); - const errors = await validate(dto); - expect(errors).toHaveLength(0); - expect(dto.email).toEqual(someEmail); - }); -}); diff --git a/server/src/domain/user/dto/update-user.dto.ts b/server/src/domain/user/dto/update-user.dto.ts deleted file mode 100644 index 059971e6c..000000000 --- a/server/src/domain/user/dto/update-user.dto.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { Transform } from 'class-transformer'; -import { IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator'; -import { UserAvatarColor } from 'src/entities/user.entity'; -import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation'; - -export class UpdateUserDto { - @Optional() - @IsEmail({ require_tld: false }) - @Transform(toEmail) - email?: string; - - @Optional() - @IsNotEmpty() - @IsString() - password?: string; - - @Optional() - @IsString() - @IsNotEmpty() - name?: string; - - @Optional() - @IsString() - @Transform(toSanitized) - storageLabel?: string; - - @IsNotEmpty() - @IsUUID('4') - @ApiProperty({ format: 'uuid' }) - id!: string; - - @ValidateBoolean({ optional: true }) - isAdmin?: boolean; - - @ValidateBoolean({ optional: true }) - shouldChangePassword?: boolean; - - @ValidateBoolean({ optional: true }) - memoriesEnabled?: boolean; - - @Optional() - @IsEnum(UserAvatarColor) - @ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor }) - avatarColor?: UserAvatarColor; - - @Optional({ nullable: true }) - @IsNumber() - @IsPositive() - @ApiProperty({ type: 'integer', format: 'int64' }) - quotaSizeInBytes?: number | null; -} diff --git a/server/src/domain/user/response-dto/create-profile-image-response.dto.ts b/server/src/domain/user/response-dto/create-profile-image-response.dto.ts deleted file mode 100644 index 2c7fd17be..000000000 --- a/server/src/domain/user/response-dto/create-profile-image-response.dto.ts +++ /dev/null @@ -1,11 +0,0 @@ -export class CreateProfileImageResponseDto { - userId!: string; - profileImagePath!: string; -} - -export function mapCreateProfileImageResponse(userId: string, profileImagePath: string): CreateProfileImageResponseDto { - return { - userId: userId, - profileImagePath: profileImagePath, - }; -} diff --git a/server/src/domain/user/response-dto/user-response.dto.ts b/server/src/domain/user/response-dto/user-response.dto.ts deleted file mode 100644 index 12ffca48c..000000000 --- a/server/src/domain/user/response-dto/user-response.dto.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { ApiProperty } from '@nestjs/swagger'; -import { IsEnum } from 'class-validator'; -import { UserAvatarColor, UserEntity, UserStatus } from 'src/entities/user.entity'; - -export const getRandomAvatarColor = (user: UserEntity): UserAvatarColor => { - const values = Object.values(UserAvatarColor); - const randomIndex = Math.floor( - [...user.email].map((letter) => letter.codePointAt(0) ?? 0).reduce((a, b) => a + b, 0) % values.length, - ); - return values[randomIndex] as UserAvatarColor; -}; - -export class UserDto { - id!: string; - name!: string; - email!: string; - profileImagePath!: string; - @IsEnum(UserAvatarColor) - @ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor }) - avatarColor!: UserAvatarColor; -} - -export class UserResponseDto extends UserDto { - storageLabel!: string | null; - shouldChangePassword!: boolean; - isAdmin!: boolean; - createdAt!: Date; - deletedAt!: Date | null; - updatedAt!: Date; - oauthId!: string; - memoriesEnabled?: boolean; - @ApiProperty({ type: 'integer', format: 'int64' }) - quotaSizeInBytes!: number | null; - @ApiProperty({ type: 'integer', format: 'int64' }) - quotaUsageInBytes!: number | null; - @ApiProperty({ enumName: 'UserStatus', enum: UserStatus }) - status!: string; -} - -export const mapSimpleUser = (entity: UserEntity): UserDto => { - return { - id: entity.id, - email: entity.email, - name: entity.name, - profileImagePath: entity.profileImagePath, - avatarColor: entity.avatarColor ?? getRandomAvatarColor(entity), - }; -}; - -export function mapUser(entity: UserEntity): UserResponseDto { - return { - ...mapSimpleUser(entity), - storageLabel: entity.storageLabel, - shouldChangePassword: entity.shouldChangePassword, - isAdmin: entity.isAdmin, - createdAt: entity.createdAt, - deletedAt: entity.deletedAt, - updatedAt: entity.updatedAt, - oauthId: entity.oauthId, - memoriesEnabled: entity.memoriesEnabled, - quotaSizeInBytes: entity.quotaSizeInBytes, - quotaUsageInBytes: entity.quotaUsageInBytes, - status: entity.status, - }; -} diff --git a/server/src/domain/user/user.service.spec.ts b/server/src/domain/user/user.service.spec.ts index 5b9a1de95..804a892c7 100644 --- a/server/src/domain/user/user.service.spec.ts +++ b/server/src/domain/user/user.service.spec.ts @@ -6,9 +6,8 @@ import { } from '@nestjs/common'; import { when } from 'jest-when'; import { JobName } from 'src/domain/job/job.constants'; -import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; -import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; import { UserService } from 'src/domain/user/user.service'; +import { UpdateUserDto, mapUser } from 'src/dtos/user.dto'; import { UserEntity, UserStatus } from 'src/entities/user.entity'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; diff --git a/server/src/domain/user/user.service.ts b/server/src/domain/user/user.service.ts index 349a775ec..ef742123f 100644 --- a/server/src/domain/user/user.service.ts +++ b/server/src/domain/user/user.service.ts @@ -4,17 +4,11 @@ import { randomBytes } from 'node:crypto'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { UserCore } from 'src/cores/user.core'; -import { AuthDto } from 'src/domain/auth/auth.dto'; import { JobName } from 'src/domain/job/job.constants'; import { IEntityJob } from 'src/domain/job/job.interface'; -import { CreateUserDto } from 'src/domain/user/dto/create-user.dto'; -import { DeleteUserDto } from 'src/domain/user/dto/delete-user.dto'; -import { UpdateUserDto } from 'src/domain/user/dto/update-user.dto'; -import { - CreateProfileImageResponseDto, - mapCreateProfileImageResponse, -} from 'src/domain/user/response-dto/create-profile-image-response.dto'; -import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { CreateProfileImageResponseDto, mapCreateProfileImageResponse } from 'src/dtos/user-profile.dto'; +import { CreateUserDto, DeleteUserDto, UpdateUserDto, UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { UserEntity, UserStatus } from 'src/entities/user.entity'; import { ImmichLogger } from 'src/infra/logger'; import { IAlbumRepository } from 'src/interfaces/album.repository'; diff --git a/server/src/domain/activity/activity.dto.ts b/server/src/dtos/activity.dto.ts similarity index 95% rename from server/src/domain/activity/activity.dto.ts rename to server/src/dtos/activity.dto.ts index a9d865778..bd0d40095 100644 --- a/server/src/domain/activity/activity.dto.ts +++ b/server/src/dtos/activity.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty, IsString, ValidateIf } from 'class-validator'; -import { UserDto, mapSimpleUser } from 'src/domain/user/response-dto/user-response.dto'; +import { UserDto, mapSimpleUser } from 'src/dtos/user.dto'; import { ActivityEntity } from 'src/entities/activity.entity'; import { Optional, ValidateUUID } from 'src/validation'; diff --git a/server/src/domain/album/album-response.dto.spec.ts b/server/src/dtos/album-response.dto.spec.ts similarity index 89% rename from server/src/domain/album/album-response.dto.spec.ts rename to server/src/dtos/album-response.dto.spec.ts index 568b416b4..2a6d59abf 100644 --- a/server/src/domain/album/album-response.dto.spec.ts +++ b/server/src/dtos/album-response.dto.spec.ts @@ -1,4 +1,4 @@ -import { mapAlbum } from 'src/domain/album/album-response.dto'; +import { mapAlbum } from 'src/dtos/album.dto'; import { albumStub } from 'test/fixtures/album.stub'; describe('mapAlbum', () => { diff --git a/server/src/domain/album/album-response.dto.ts b/server/src/dtos/album.dto.ts similarity index 59% rename from server/src/domain/album/album-response.dto.ts rename to server/src/dtos/album.dto.ts index b016a1200..3f7af0f53 100644 --- a/server/src/domain/album/album-response.dto.ts +++ b/server/src/dtos/album.dto.ts @@ -1,9 +1,87 @@ import { ApiProperty } from '@nestjs/swagger'; -import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { ArrayNotEmpty, IsEnum, IsString } from 'class-validator'; +import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { AlbumEntity, AssetOrder } from 'src/entities/album.entity'; -import { Optional } from 'src/validation'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; + +export class AlbumInfoDto { + @ValidateBoolean({ optional: true }) + withoutAssets?: boolean; +} + +export class AddUsersDto { + @ValidateUUID({ each: true }) + @ArrayNotEmpty() + sharedUserIds!: string[]; +} + +export class CreateAlbumDto { + @IsString() + @ApiProperty() + albumName!: string; + + @IsString() + @Optional() + description?: string; + + @ValidateUUID({ optional: true, each: true }) + sharedWithUserIds?: string[]; + + @ValidateUUID({ optional: true, each: true }) + assetIds?: string[]; +} + +export class UpdateAlbumDto { + @Optional() + @IsString() + albumName?: string; + + @Optional() + @IsString() + description?: string; + + @ValidateUUID({ optional: true }) + albumThumbnailAssetId?: string; + + @ValidateBoolean({ optional: true }) + isActivityEnabled?: boolean; + + @IsEnum(AssetOrder) + @Optional() + @ApiProperty({ enum: AssetOrder, enumName: 'AssetOrder' }) + order?: AssetOrder; +} + +export class GetAlbumsDto { + @ValidateBoolean({ optional: true }) + /** + * true: only shared albums + * false: only non-shared own albums + * undefined: shared and owned albums + */ + shared?: boolean; + + /** + * Only returns albums that contain the asset + * Ignores the shared parameter + * undefined: get all albums + */ + @ValidateUUID({ optional: true }) + assetId?: string; +} + +export class AlbumCountResponseDto { + @ApiProperty({ type: 'integer' }) + owned!: number; + + @ApiProperty({ type: 'integer' }) + shared!: number; + + @ApiProperty({ type: 'integer' }) + notShared!: number; +} export class AlbumResponseDto { id!: string; @@ -73,14 +151,3 @@ export const mapAlbum = (entity: AlbumEntity, withAssets: boolean, auth?: AuthDt export const mapAlbumWithAssets = (entity: AlbumEntity) => mapAlbum(entity, true); export const mapAlbumWithoutAssets = (entity: AlbumEntity) => mapAlbum(entity, false); - -export class AlbumCountResponseDto { - @ApiProperty({ type: 'integer' }) - owned!: number; - - @ApiProperty({ type: 'integer' }) - shared!: number; - - @ApiProperty({ type: 'integer' }) - notShared!: number; -} diff --git a/server/src/domain/api-key/api-key.dto.ts b/server/src/dtos/api-key.dto.ts similarity index 100% rename from server/src/domain/api-key/api-key.dto.ts rename to server/src/dtos/api-key.dto.ts diff --git a/server/src/domain/asset/response-dto/asset-ids-response.dto.ts b/server/src/dtos/asset-ids.response.dto.ts similarity index 100% rename from server/src/domain/asset/response-dto/asset-ids-response.dto.ts rename to server/src/dtos/asset-ids.response.dto.ts diff --git a/server/src/domain/asset/response-dto/asset-response.dto.ts b/server/src/dtos/asset-response.dto.ts similarity index 88% rename from server/src/domain/asset/response-dto/asset-response.dto.ts rename to server/src/dtos/asset-response.dto.ts index dff12d481..04e36645e 100644 --- a/server/src/domain/asset/response-dto/asset-response.dto.ts +++ b/server/src/dtos/asset-response.dto.ts @@ -1,12 +1,12 @@ import { ApiProperty } from '@nestjs/swagger'; -import { ExifResponseDto, mapExif } from 'src/domain/asset/response-dto/exif-response.dto'; -import { SmartInfoResponseDto, mapSmartInfo } from 'src/domain/asset/response-dto/smart-info-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; -import { PersonWithFacesResponseDto, mapFacesWithoutPerson, mapPerson } from 'src/domain/person/person.dto'; -import { TagResponseDto, mapTag } from 'src/domain/tag/tag-response.dto'; -import { UserResponseDto, mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; +import { ExifResponseDto, mapExif } from 'src/dtos/exif.dto'; +import { PersonWithFacesResponseDto, mapFacesWithoutPerson, mapPerson } from 'src/dtos/person.dto'; +import { TagResponseDto, mapTag } from 'src/dtos/tag.dto'; +import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; +import { SmartInfoEntity } from 'src/entities/smart-info.entity'; export class SanitizedAssetResponseDto { id!: string; @@ -134,3 +134,15 @@ export class MemoryLaneResponseDto { title!: string; assets!: AssetResponseDto[]; } + +export class SmartInfoResponseDto { + tags?: string[] | null; + objects?: string[] | null; +} + +export function mapSmartInfo(entity: SmartInfoEntity): SmartInfoResponseDto { + return { + tags: entity.tags, + objects: entity.objects, + }; +} diff --git a/server/src/dtos/asset.dto.ts b/server/src/dtos/asset.dto.ts new file mode 100644 index 000000000..5ccf63c98 --- /dev/null +++ b/server/src/dtos/asset.dto.ts @@ -0,0 +1,132 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Type } from 'class-transformer'; +import { + IsDateString, + IsEnum, + IsInt, + IsLatitude, + IsLongitude, + IsNotEmpty, + IsPositive, + IsString, + ValidateIf, +} from 'class-validator'; +import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; +import { AssetType } from 'src/entities/asset.entity'; +import { AssetStats } from 'src/interfaces/asset.repository'; +import { Optional, ValidateBoolean, ValidateUUID } from 'src/validation'; + +export class DeviceIdDto { + @IsNotEmpty() + @IsString() + deviceId!: string; +} + +const hasGPS = (o: { latitude: undefined; longitude: undefined }) => + o.latitude !== undefined || o.longitude !== undefined; +const ValidateGPS = () => ValidateIf(hasGPS); + +export class UpdateAssetBase { + @ValidateBoolean({ optional: true }) + isFavorite?: boolean; + + @ValidateBoolean({ optional: true }) + isArchived?: boolean; + + @Optional() + @IsDateString() + dateTimeOriginal?: string; + + @ValidateGPS() + @IsLatitude() + @IsNotEmpty() + latitude?: number; + + @ValidateGPS() + @IsLongitude() + @IsNotEmpty() + longitude?: number; +} + +export class AssetBulkUpdateDto extends UpdateAssetBase { + @ValidateUUID({ each: true }) + ids!: string[]; + + @ValidateUUID({ optional: true }) + stackParentId?: string; + + @ValidateBoolean({ optional: true }) + removeParent?: boolean; +} + +export class UpdateAssetDto extends UpdateAssetBase { + @Optional() + @IsString() + description?: string; +} + +export class RandomAssetsDto { + @Optional() + @IsInt() + @IsPositive() + @Type(() => Number) + count?: number; +} + +export class AssetBulkDeleteDto extends BulkIdsDto { + @ValidateBoolean({ optional: true }) + force?: boolean; +} + +export class AssetIdsDto { + @ValidateUUID({ each: true }) + assetIds!: string[]; +} + +export enum AssetJobName { + REGENERATE_THUMBNAIL = 'regenerate-thumbnail', + REFRESH_METADATA = 'refresh-metadata', + TRANSCODE_VIDEO = 'transcode-video', +} + +export class AssetJobsDto extends AssetIdsDto { + @ApiProperty({ enumName: 'AssetJobName', enum: AssetJobName }) + @IsEnum(AssetJobName) + name!: AssetJobName; +} + +export class AssetStatsDto { + @ValidateBoolean({ optional: true }) + isArchived?: boolean; + + @ValidateBoolean({ optional: true }) + isFavorite?: boolean; + + @ValidateBoolean({ optional: true }) + isTrashed?: boolean; +} + +export class AssetStatsResponseDto { + @ApiProperty({ type: 'integer' }) + images!: number; + + @ApiProperty({ type: 'integer' }) + videos!: number; + + @ApiProperty({ type: 'integer' }) + total!: number; +} + +export const mapStats = (stats: AssetStats): AssetStatsResponseDto => { + return { + images: stats[AssetType.IMAGE], + videos: stats[AssetType.VIDEO], + total: Object.values(stats).reduce((total, value) => total + value, 0), + }; +}; +export enum UploadFieldName { + ASSET_DATA = 'assetData', + LIVE_PHOTO_DATA = 'livePhotoData', + SIDECAR_DATA = 'sidecarData', + PROFILE_DATA = 'file', +} diff --git a/server/src/domain/audit/audit.dto.ts b/server/src/dtos/audit.dto.ts similarity index 100% rename from server/src/domain/audit/audit.dto.ts rename to server/src/dtos/audit.dto.ts diff --git a/server/src/domain/auth/auth.dto.ts b/server/src/dtos/auth.dto.ts similarity index 100% rename from server/src/domain/auth/auth.dto.ts rename to server/src/dtos/auth.dto.ts diff --git a/server/src/domain/download/download.dto.ts b/server/src/dtos/download.dto.ts similarity index 100% rename from server/src/domain/download/download.dto.ts rename to server/src/dtos/download.dto.ts diff --git a/server/src/domain/asset/response-dto/exif-response.dto.ts b/server/src/dtos/exif.dto.ts similarity index 100% rename from server/src/domain/asset/response-dto/exif-response.dto.ts rename to server/src/dtos/exif.dto.ts diff --git a/server/src/domain/job/job.dto.ts b/server/src/dtos/job.dto.ts similarity index 100% rename from server/src/domain/job/job.dto.ts rename to server/src/dtos/job.dto.ts diff --git a/server/src/domain/library/library.dto.ts b/server/src/dtos/library.dto.ts similarity index 100% rename from server/src/domain/library/library.dto.ts rename to server/src/dtos/library.dto.ts diff --git a/server/src/domain/smart-info/dto/model-config.dto.ts b/server/src/dtos/model-config.dto.ts similarity index 100% rename from server/src/domain/smart-info/dto/model-config.dto.ts rename to server/src/dtos/model-config.dto.ts diff --git a/server/src/domain/partner/partner.dto.ts b/server/src/dtos/partner.dto.ts similarity index 71% rename from server/src/domain/partner/partner.dto.ts rename to server/src/dtos/partner.dto.ts index c197d2079..187f8f341 100644 --- a/server/src/domain/partner/partner.dto.ts +++ b/server/src/dtos/partner.dto.ts @@ -1,5 +1,5 @@ import { IsNotEmpty } from 'class-validator'; -import { UserResponseDto } from 'src/domain/user/response-dto/user-response.dto'; +import { UserResponseDto } from 'src/dtos/user.dto'; export class UpdatePartnerDto { @IsNotEmpty() diff --git a/server/src/domain/person/person.dto.ts b/server/src/dtos/person.dto.ts similarity index 98% rename from server/src/domain/person/person.dto.ts rename to server/src/dtos/person.dto.ts index 4153ba813..b28f18603 100644 --- a/server/src/domain/person/person.dto.ts +++ b/server/src/dtos/person.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsArray, IsNotEmpty, IsString, MaxDate, ValidateNested } from 'class-validator'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { PersonEntity } from 'src/entities/person.entity'; import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; diff --git a/server/src/domain/search/dto/search.dto.ts b/server/src/dtos/search.dto.ts similarity index 66% rename from server/src/domain/search/dto/search.dto.ts rename to server/src/dtos/search.dto.ts index 4f77517b3..799baddee 100644 --- a/server/src/domain/search/dto/search.dto.ts +++ b/server/src/dtos/search.dto.ts @@ -1,6 +1,8 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsEnum, IsInt, IsNotEmpty, IsString, Max, Min } from 'class-validator'; +import { AlbumResponseDto } from 'src/dtos/album.dto'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AssetOrder } from 'src/entities/album.entity'; import { AssetType } from 'src/entities/asset.entity'; import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; @@ -264,3 +266,130 @@ export function mapPlaces(place: GeodataPlacesEntity): PlacesResponseDto { admin2name: place.admin2Name, }; } +export enum SearchSuggestionType { + COUNTRY = 'country', + STATE = 'state', + CITY = 'city', + CAMERA_MAKE = 'camera-make', + CAMERA_MODEL = 'camera-model', +} + +export class SearchSuggestionRequestDto { + @IsEnum(SearchSuggestionType) + @IsNotEmpty() + @ApiProperty({ enumName: 'SearchSuggestionType', enum: SearchSuggestionType }) + type!: SearchSuggestionType; + + @IsString() + @Optional() + country?: string; + + @IsString() + @Optional() + state?: string; + + @IsString() + @Optional() + make?: string; + + @IsString() + @Optional() + model?: string; +} + +class SearchFacetCountResponseDto { + @ApiProperty({ type: 'integer' }) + count!: number; + value!: string; +} + +class SearchFacetResponseDto { + fieldName!: string; + counts!: SearchFacetCountResponseDto[]; +} + +class SearchAlbumResponseDto { + @ApiProperty({ type: 'integer' }) + total!: number; + @ApiProperty({ type: 'integer' }) + count!: number; + items!: AlbumResponseDto[]; + facets!: SearchFacetResponseDto[]; +} + +class SearchAssetResponseDto { + @ApiProperty({ type: 'integer' }) + total!: number; + @ApiProperty({ type: 'integer' }) + count!: number; + items!: AssetResponseDto[]; + facets!: SearchFacetResponseDto[]; + nextPage!: string | null; +} + +export class SearchResponseDto { + albums!: SearchAlbumResponseDto; + assets!: SearchAssetResponseDto; +} + +class SearchExploreItem { + value!: string; + data!: AssetResponseDto; +} + +export class SearchExploreResponseDto { + fieldName!: string; + items!: SearchExploreItem[]; +} + +export class MapMarkerDto { + @ValidateBoolean({ optional: true }) + isArchived?: boolean; + + @ValidateBoolean({ optional: true }) + isFavorite?: boolean; + + @ValidateDate({ optional: true }) + fileCreatedAfter?: Date; + + @ValidateDate({ optional: true }) + fileCreatedBefore?: Date; + + @ValidateBoolean({ optional: true }) + withPartners?: boolean; +} + +export class MemoryLaneDto { + @IsInt() + @Type(() => Number) + @Max(31) + @Min(1) + @ApiProperty({ type: 'integer' }) + day!: number; + + @IsInt() + @Type(() => Number) + @Max(12) + @Min(1) + @ApiProperty({ type: 'integer' }) + month!: number; +} +export class MapMarkerResponseDto { + @ApiProperty() + id!: string; + + @ApiProperty({ format: 'double' }) + lat!: number; + + @ApiProperty({ format: 'double' }) + lon!: number; + + @ApiProperty() + city!: string | null; + + @ApiProperty() + state!: string | null; + + @ApiProperty() + country!: string | null; +} diff --git a/server/src/domain/server-info/server-info.dto.ts b/server/src/dtos/server-info.dto.ts similarity index 96% rename from server/src/domain/server-info/server-info.dto.ts rename to server/src/dtos/server-info.dto.ts index 0cbfbe773..33fe83044 100644 --- a/server/src/domain/server-info/server-info.dto.ts +++ b/server/src/dtos/server-info.dto.ts @@ -2,7 +2,7 @@ import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger'; import type { DateTime } from 'luxon'; import { FeatureFlags } from 'src/cores/system-config.core'; import { IVersion, VersionType } from 'src/domain/domain.constant'; -import { SystemConfigThemeDto } from 'src/domain/system-config/dto/system-config-theme.dto'; +import { SystemConfigThemeDto } from 'src/dtos/system-config-theme.dto'; export class ServerPingResponse { @ApiResponseProperty({ type: String, example: 'pong' }) diff --git a/server/src/domain/shared-link/shared-link-response.dto.ts b/server/src/dtos/shared-link.dto.ts similarity index 57% rename from server/src/domain/shared-link/shared-link-response.dto.ts rename to server/src/dtos/shared-link.dto.ts index 44024506f..9a90901d2 100644 --- a/server/src/domain/shared-link/shared-link-response.dto.ts +++ b/server/src/dtos/shared-link.dto.ts @@ -1,9 +1,81 @@ import { ApiProperty } from '@nestjs/swagger'; +import { IsEnum, IsString } from 'class-validator'; import _ from 'lodash'; -import { AlbumResponseDto, mapAlbumWithoutAssets } from 'src/domain/album/album-response.dto'; -import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; +import { AlbumResponseDto, mapAlbumWithoutAssets } from 'src/dtos/album.dto'; +import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; import { SharedLinkEntity, SharedLinkType } from 'src/entities/shared-link.entity'; +import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; +export class SharedLinkCreateDto { + @IsEnum(SharedLinkType) + @ApiProperty({ enum: SharedLinkType, enumName: 'SharedLinkType' }) + type!: SharedLinkType; + + @ValidateUUID({ each: true, optional: true }) + assetIds?: string[]; + + @ValidateUUID({ optional: true }) + albumId?: string; + + @IsString() + @Optional() + description?: string; + + @IsString() + @Optional() + password?: string; + + @ValidateDate({ optional: true, nullable: true }) + expiresAt?: Date | null = null; + + @ValidateBoolean({ optional: true }) + allowUpload?: boolean; + + @ValidateBoolean({ optional: true }) + allowDownload?: boolean = true; + + @ValidateBoolean({ optional: true }) + showMetadata?: boolean = true; +} + +export class SharedLinkEditDto { + @Optional() + description?: string; + + @Optional() + password?: string; + + @Optional({ nullable: true }) + expiresAt?: Date | null; + + @Optional() + allowUpload?: boolean; + + @ValidateBoolean({ optional: true }) + allowDownload?: boolean; + + @ValidateBoolean({ optional: true }) + showMetadata?: boolean; + + /** + * Few clients cannot send null to set the expiryTime to never. + * Setting this flag and not sending expiryAt is considered as null instead. + * Clients that can send null values can ignore this. + */ + @ValidateBoolean({ optional: true }) + changeExpiryTime?: boolean; +} + +export class SharedLinkPasswordDto { + @IsString() + @Optional() + @ApiProperty({ example: 'password' }) + password?: string; + + @IsString() + @Optional() + token?: string; +} export class SharedLinkResponseDto { id!: string; description!: string | null; diff --git a/server/src/domain/asset/dto/asset-stack.dto.ts b/server/src/dtos/stack.dto.ts similarity index 100% rename from server/src/domain/asset/dto/asset-stack.dto.ts rename to server/src/dtos/stack.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts b/server/src/dtos/system-config-ffmpeg.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-ffmpeg.dto.ts rename to server/src/dtos/system-config-ffmpeg.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-job.dto.ts b/server/src/dtos/system-config-job.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-job.dto.ts rename to server/src/dtos/system-config-job.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-library.dto.ts b/server/src/dtos/system-config-library.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-library.dto.ts rename to server/src/dtos/system-config-library.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-logging.dto.ts b/server/src/dtos/system-config-logging.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-logging.dto.ts rename to server/src/dtos/system-config-logging.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts b/server/src/dtos/system-config-machine-learning.dto.ts similarity index 85% rename from server/src/domain/system-config/dto/system-config-machine-learning.dto.ts rename to server/src/dtos/system-config-machine-learning.dto.ts index 058585992..7abc9ac88 100644 --- a/server/src/domain/system-config/dto/system-config-machine-learning.dto.ts +++ b/server/src/dtos/system-config-machine-learning.dto.ts @@ -1,6 +1,6 @@ import { Type } from 'class-transformer'; import { IsObject, IsUrl, ValidateIf, ValidateNested } from 'class-validator'; -import { CLIPConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; +import { CLIPConfig, RecognitionConfig } from 'src/dtos/model-config.dto'; import { ValidateBoolean } from 'src/validation'; export class SystemConfigMachineLearningDto { diff --git a/server/src/domain/system-config/dto/system-config-map.dto.ts b/server/src/dtos/system-config-map.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-map.dto.ts rename to server/src/dtos/system-config-map.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-new-version-check.dto.ts b/server/src/dtos/system-config-new-version-check.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-new-version-check.dto.ts rename to server/src/dtos/system-config-new-version-check.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-oauth.dto.ts b/server/src/dtos/system-config-oauth.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-oauth.dto.ts rename to server/src/dtos/system-config-oauth.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-password-login.dto.ts b/server/src/dtos/system-config-password-login.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-password-login.dto.ts rename to server/src/dtos/system-config-password-login.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts b/server/src/dtos/system-config-reverse-geocoding.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-reverse-geocoding.dto.ts rename to server/src/dtos/system-config-reverse-geocoding.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-server.dto.ts b/server/src/dtos/system-config-server.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-server.dto.ts rename to server/src/dtos/system-config-server.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-storage-template.dto.ts b/server/src/dtos/system-config-storage-template.dto.ts similarity index 53% rename from server/src/domain/system-config/dto/system-config-storage-template.dto.ts rename to server/src/dtos/system-config-storage-template.dto.ts index 77204b46e..d56cfedb8 100644 --- a/server/src/domain/system-config/dto/system-config-storage-template.dto.ts +++ b/server/src/dtos/system-config-storage-template.dto.ts @@ -12,3 +12,14 @@ export class SystemConfigStorageTemplateDto { @IsString() template!: string; } + +export class SystemConfigTemplateStorageOptionDto { + yearOptions!: string[]; + monthOptions!: string[]; + weekOptions!: string[]; + dayOptions!: string[]; + hourOptions!: string[]; + minuteOptions!: string[]; + secondOptions!: string[]; + presetOptions!: string[]; +} diff --git a/server/src/domain/system-config/dto/system-config-theme.dto.ts b/server/src/dtos/system-config-theme.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-theme.dto.ts rename to server/src/dtos/system-config-theme.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-thumbnail.dto.ts b/server/src/dtos/system-config-thumbnail.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-thumbnail.dto.ts rename to server/src/dtos/system-config-thumbnail.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-trash.dto.ts b/server/src/dtos/system-config-trash.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-trash.dto.ts rename to server/src/dtos/system-config-trash.dto.ts diff --git a/server/src/domain/system-config/dto/system-config-user.dto.ts b/server/src/dtos/system-config-user.dto.ts similarity index 100% rename from server/src/domain/system-config/dto/system-config-user.dto.ts rename to server/src/dtos/system-config-user.dto.ts diff --git a/server/src/domain/system-config/dto/system-config.dto.ts b/server/src/dtos/system-config.dto.ts similarity index 56% rename from server/src/domain/system-config/dto/system-config.dto.ts rename to server/src/dtos/system-config.dto.ts index 9aef92303..7c3237629 100644 --- a/server/src/domain/system-config/dto/system-config.dto.ts +++ b/server/src/dtos/system-config.dto.ts @@ -1,21 +1,21 @@ import { Type } from 'class-transformer'; import { IsObject, ValidateNested } from 'class-validator'; -import { SystemConfigFFmpegDto } from 'src/domain/system-config/dto/system-config-ffmpeg.dto'; -import { SystemConfigJobDto } from 'src/domain/system-config/dto/system-config-job.dto'; -import { SystemConfigLibraryDto } from 'src/domain/system-config/dto/system-config-library.dto'; -import { SystemConfigLoggingDto } from 'src/domain/system-config/dto/system-config-logging.dto'; -import { SystemConfigMachineLearningDto } from 'src/domain/system-config/dto/system-config-machine-learning.dto'; -import { SystemConfigMapDto } from 'src/domain/system-config/dto/system-config-map.dto'; -import { SystemConfigNewVersionCheckDto } from 'src/domain/system-config/dto/system-config-new-version-check.dto'; -import { SystemConfigOAuthDto } from 'src/domain/system-config/dto/system-config-oauth.dto'; -import { SystemConfigPasswordLoginDto } from 'src/domain/system-config/dto/system-config-password-login.dto'; -import { SystemConfigReverseGeocodingDto } from 'src/domain/system-config/dto/system-config-reverse-geocoding.dto'; -import { SystemConfigServerDto } from 'src/domain/system-config/dto/system-config-server.dto'; -import { SystemConfigStorageTemplateDto } from 'src/domain/system-config/dto/system-config-storage-template.dto'; -import { SystemConfigThemeDto } from 'src/domain/system-config/dto/system-config-theme.dto'; -import { SystemConfigThumbnailDto } from 'src/domain/system-config/dto/system-config-thumbnail.dto'; -import { SystemConfigTrashDto } from 'src/domain/system-config/dto/system-config-trash.dto'; -import { SystemConfigUserDto } from 'src/domain/system-config/dto/system-config-user.dto'; +import { SystemConfigFFmpegDto } from 'src/dtos/system-config-ffmpeg.dto'; +import { SystemConfigJobDto } from 'src/dtos/system-config-job.dto'; +import { SystemConfigLibraryDto } from 'src/dtos/system-config-library.dto'; +import { SystemConfigLoggingDto } from 'src/dtos/system-config-logging.dto'; +import { SystemConfigMachineLearningDto } from 'src/dtos/system-config-machine-learning.dto'; +import { SystemConfigMapDto } from 'src/dtos/system-config-map.dto'; +import { SystemConfigNewVersionCheckDto } from 'src/dtos/system-config-new-version-check.dto'; +import { SystemConfigOAuthDto } from 'src/dtos/system-config-oauth.dto'; +import { SystemConfigPasswordLoginDto } from 'src/dtos/system-config-password-login.dto'; +import { SystemConfigReverseGeocodingDto } from 'src/dtos/system-config-reverse-geocoding.dto'; +import { SystemConfigServerDto } from 'src/dtos/system-config-server.dto'; +import { SystemConfigStorageTemplateDto } from 'src/dtos/system-config-storage-template.dto'; +import { SystemConfigThemeDto } from 'src/dtos/system-config-theme.dto'; +import { SystemConfigThumbnailDto } from 'src/dtos/system-config-thumbnail.dto'; +import { SystemConfigTrashDto } from 'src/dtos/system-config-trash.dto'; +import { SystemConfigUserDto } from 'src/dtos/system-config-user.dto'; import { SystemConfig } from 'src/entities/system-config.entity'; export class SystemConfigDto implements SystemConfig { diff --git a/server/src/domain/tag/tag-response.dto.ts b/server/src/dtos/tag.dto.ts similarity index 54% rename from server/src/domain/tag/tag-response.dto.ts rename to server/src/dtos/tag.dto.ts index 535efcf43..1094d70df 100644 --- a/server/src/domain/tag/tag-response.dto.ts +++ b/server/src/dtos/tag.dto.ts @@ -1,5 +1,24 @@ import { ApiProperty } from '@nestjs/swagger'; +import { IsEnum, IsNotEmpty, IsString } from 'class-validator'; import { TagEntity, TagType } from 'src/entities/tag.entity'; +import { Optional } from 'src/validation'; + +export class CreateTagDto { + @IsString() + @IsNotEmpty() + name!: string; + + @IsEnum(TagType) + @IsNotEmpty() + @ApiProperty({ enumName: 'TagTypeEnum', enum: TagType }) + type!: TagType; +} + +export class UpdateTagDto { + @IsString() + @Optional() + name?: string; +} export class TagResponseDto { id!: string; diff --git a/server/src/domain/asset/dto/time-bucket.dto.ts b/server/src/dtos/time-bucket.dto.ts similarity index 88% rename from server/src/domain/asset/dto/time-bucket.dto.ts rename to server/src/dtos/time-bucket.dto.ts index a5ff023d1..40dbb84e6 100644 --- a/server/src/domain/asset/dto/time-bucket.dto.ts +++ b/server/src/dtos/time-bucket.dto.ts @@ -44,3 +44,11 @@ export class TimeBucketAssetDto extends TimeBucketDto { @IsString() timeBucket!: string; } + +export class TimeBucketResponseDto { + @ApiProperty({ type: 'string' }) + timeBucket!: string; + + @ApiProperty({ type: 'integer' }) + count!: number; +} diff --git a/server/src/dtos/user-profile.dto.ts b/server/src/dtos/user-profile.dto.ts new file mode 100644 index 000000000..2f3d8cf22 --- /dev/null +++ b/server/src/dtos/user-profile.dto.ts @@ -0,0 +1,28 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { UploadFieldName } from 'src/dtos/asset.dto'; +import { UserAvatarColor, UserEntity } from 'src/entities/user.entity'; + +export class CreateProfileImageDto { + @ApiProperty({ type: 'string', format: 'binary' }) + [UploadFieldName.PROFILE_DATA]!: Express.Multer.File; +} + +export class CreateProfileImageResponseDto { + userId!: string; + profileImagePath!: string; +} + +export function mapCreateProfileImageResponse(userId: string, profileImagePath: string): CreateProfileImageResponseDto { + return { + userId: userId, + profileImagePath: profileImagePath, + }; +} + +export const getRandomAvatarColor = (user: UserEntity): UserAvatarColor => { + const values = Object.values(UserAvatarColor); + const randomIndex = Math.floor( + [...user.email].map((letter) => letter.codePointAt(0) ?? 0).reduce((a, b) => a + b, 0) % values.length, + ); + return values[randomIndex] as UserAvatarColor; +}; diff --git a/server/src/domain/user/dto/create-user.dto.spec.ts b/server/src/dtos/user.dto.spec.ts similarity index 79% rename from server/src/domain/user/dto/create-user.dto.spec.ts rename to server/src/dtos/user.dto.spec.ts index 28abc44ad..d07399f0e 100644 --- a/server/src/domain/user/dto/create-user.dto.spec.ts +++ b/server/src/dtos/user.dto.spec.ts @@ -1,6 +1,20 @@ import { plainToInstance } from 'class-transformer'; import { validate } from 'class-validator'; -import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto } from 'src/domain/user/dto/create-user.dto'; +import { CreateAdminDto, CreateUserDto, CreateUserOAuthDto, UpdateUserDto } from 'src/dtos/user.dto'; + +describe('update user DTO', () => { + it('should allow emails without a tld', async () => { + const someEmail = 'test@test'; + + const dto = plainToInstance(UpdateUserDto, { + email: someEmail, + id: '3fe388e4-2078-44d7-b36c-39d9dee3a657', + }); + const errors = await validate(dto); + expect(errors).toHaveLength(0); + expect(dto.email).toEqual(someEmail); + }); +}); describe('create user DTO', () => { it('validates the email', async () => { diff --git a/server/src/dtos/user.dto.ts b/server/src/dtos/user.dto.ts new file mode 100644 index 000000000..309006822 --- /dev/null +++ b/server/src/dtos/user.dto.ts @@ -0,0 +1,169 @@ +import { ApiProperty } from '@nestjs/swagger'; +import { Transform } from 'class-transformer'; +import { IsEmail, IsEnum, IsNotEmpty, IsNumber, IsPositive, IsString, IsUUID } from 'class-validator'; +import { getRandomAvatarColor } from 'src/dtos/user-profile.dto'; +import { UserAvatarColor, UserEntity, UserStatus } from 'src/entities/user.entity'; +import { Optional, ValidateBoolean, toEmail, toSanitized } from 'src/validation'; + +export class CreateUserDto { + @IsEmail({ require_tld: false }) + @Transform(toEmail) + email!: string; + + @IsNotEmpty() + @IsString() + password!: string; + + @IsNotEmpty() + @IsString() + name!: string; + + @Optional({ nullable: true }) + @IsString() + @Transform(toSanitized) + storageLabel?: string | null; + + @ValidateBoolean({ optional: true }) + memoriesEnabled?: boolean; + + @Optional({ nullable: true }) + @IsNumber() + @IsPositive() + @ApiProperty({ type: 'integer', format: 'int64' }) + quotaSizeInBytes?: number | null; + + @ValidateBoolean({ optional: true }) + shouldChangePassword?: boolean; +} + +export class CreateAdminDto { + @IsNotEmpty() + isAdmin!: true; + + @IsEmail({ require_tld: false }) + @Transform(({ value }) => value?.toLowerCase()) + email!: string; + + @IsNotEmpty() + password!: string; + + @IsNotEmpty() + name!: string; +} + +export class CreateUserOAuthDto { + @IsEmail({ require_tld: false }) + @Transform(({ value }) => value?.toLowerCase()) + email!: string; + + @IsNotEmpty() + oauthId!: string; + + name?: string; +} + +export class DeleteUserDto { + @ValidateBoolean({ optional: true }) + force?: boolean; +} + +export class UpdateUserDto { + @Optional() + @IsEmail({ require_tld: false }) + @Transform(toEmail) + email?: string; + + @Optional() + @IsNotEmpty() + @IsString() + password?: string; + + @Optional() + @IsString() + @IsNotEmpty() + name?: string; + + @Optional() + @IsString() + @Transform(toSanitized) + storageLabel?: string; + + @IsNotEmpty() + @IsUUID('4') + @ApiProperty({ format: 'uuid' }) + id!: string; + + @ValidateBoolean({ optional: true }) + isAdmin?: boolean; + + @ValidateBoolean({ optional: true }) + shouldChangePassword?: boolean; + + @ValidateBoolean({ optional: true }) + memoriesEnabled?: boolean; + + @Optional() + @IsEnum(UserAvatarColor) + @ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor }) + avatarColor?: UserAvatarColor; + + @Optional({ nullable: true }) + @IsNumber() + @IsPositive() + @ApiProperty({ type: 'integer', format: 'int64' }) + quotaSizeInBytes?: number | null; +} + +export class UserDto { + id!: string; + name!: string; + email!: string; + profileImagePath!: string; + @IsEnum(UserAvatarColor) + @ApiProperty({ enumName: 'UserAvatarColor', enum: UserAvatarColor }) + avatarColor!: UserAvatarColor; +} + +export class UserResponseDto extends UserDto { + storageLabel!: string | null; + shouldChangePassword!: boolean; + isAdmin!: boolean; + createdAt!: Date; + deletedAt!: Date | null; + updatedAt!: Date; + oauthId!: string; + memoriesEnabled?: boolean; + @ApiProperty({ type: 'integer', format: 'int64' }) + quotaSizeInBytes!: number | null; + @ApiProperty({ type: 'integer', format: 'int64' }) + quotaUsageInBytes!: number | null; + @ApiProperty({ enumName: 'UserStatus', enum: UserStatus }) + status!: string; +} + +export const mapSimpleUser = (entity: UserEntity): UserDto => { + return { + id: entity.id, + email: entity.email, + name: entity.name, + profileImagePath: entity.profileImagePath, + avatarColor: entity.avatarColor ?? getRandomAvatarColor(entity), + }; +}; + +export function mapUser(entity: UserEntity): UserResponseDto { + return { + ...mapSimpleUser(entity), + storageLabel: entity.storageLabel, + shouldChangePassword: entity.shouldChangePassword, + isAdmin: entity.isAdmin, + createdAt: entity.createdAt, + deletedAt: entity.deletedAt, + updatedAt: entity.updatedAt, + oauthId: entity.oauthId, + memoriesEnabled: entity.memoriesEnabled, + quotaSizeInBytes: entity.quotaSizeInBytes, + quotaUsageInBytes: entity.quotaUsageInBytes, + status: entity.status, + }; +} diff --git a/server/src/immich/api-v1/asset/asset.controller.ts b/server/src/immich/api-v1/asset/asset.controller.ts index d29f61fdd..5f57eb558 100644 --- a/server/src/immich/api-v1/asset/asset.controller.ts +++ b/server/src/immich/api-v1/asset/asset.controller.ts @@ -15,8 +15,8 @@ import { } from '@nestjs/common'; import { ApiBody, ApiConsumes, ApiHeader, ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { AssetService as AssetServiceV1 } from 'src/immich/api-v1/asset/asset.service'; import { AssetBulkUploadCheckDto } from 'src/immich/api-v1/asset/dto/asset-check.dto'; import { AssetSearchDto } from 'src/immich/api-v1/asset/dto/asset-search.dto'; diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 0a5722690..ee310c377 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -7,10 +7,10 @@ import { } from '@nestjs/common'; import { AccessCore, Permission } from 'src/cores/access.core'; import { UploadFile } from 'src/domain/asset/asset.service'; -import { AssetResponseDto, mapAsset } from 'src/domain/asset/response-dto/asset-response.dto'; -import { AuthDto } from 'src/domain/auth/auth.dto'; import { mimeTypes } from 'src/domain/domain.constant'; import { JobName } from 'src/domain/job/job.constants'; +import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/entities/asset.entity'; import { LibraryType } from 'src/entities/library.entity'; import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; diff --git a/server/src/immich/api-v1/asset/dto/create-asset.dto.ts b/server/src/immich/api-v1/asset/dto/create-asset.dto.ts index d16a9c05c..7e5b9a0c8 100644 --- a/server/src/immich/api-v1/asset/dto/create-asset.dto.ts +++ b/server/src/immich/api-v1/asset/dto/create-asset.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsNotEmpty, IsString } from 'class-validator'; -import { UploadFieldName } from 'src/domain/asset/asset.service'; +import { UploadFieldName } from 'src/dtos/asset.dto'; import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation'; export class CreateAssetDto { diff --git a/server/src/interfaces/communication.repository.ts b/server/src/interfaces/communication.repository.ts index 870c0d937..4627e5265 100644 --- a/server/src/interfaces/communication.repository.ts +++ b/server/src/interfaces/communication.repository.ts @@ -1,5 +1,5 @@ -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; -import { ReleaseNotification, ServerVersionResponseDto } from 'src/domain/server-info/server-info.dto'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; +import { ReleaseNotification, ServerVersionResponseDto } from 'src/dtos/server-info.dto'; import { SystemConfig } from 'src/entities/system-config.entity'; export const ICommunicationRepository = 'ICommunicationRepository'; diff --git a/server/src/interfaces/library.repository.ts b/server/src/interfaces/library.repository.ts index 5638d6024..dbc7fab81 100644 --- a/server/src/interfaces/library.repository.ts +++ b/server/src/interfaces/library.repository.ts @@ -1,4 +1,4 @@ -import { LibraryStatsResponseDto } from 'src/domain/library/library.dto'; +import { LibraryStatsResponseDto } from 'src/dtos/library.dto'; import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; export const ILibraryRepository = 'ILibraryRepository'; diff --git a/server/src/interfaces/machine-learning.repository.ts b/server/src/interfaces/machine-learning.repository.ts index d11e2e8f7..0aeed7635 100644 --- a/server/src/interfaces/machine-learning.repository.ts +++ b/server/src/interfaces/machine-learning.repository.ts @@ -1,4 +1,4 @@ -import { CLIPConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; +import { CLIPConfig, RecognitionConfig } from 'src/dtos/model-config.dto'; export const IMachineLearningRepository = 'IMachineLearningRepository'; diff --git a/server/src/interfaces/storage.repository.ts b/server/src/interfaces/storage.repository.ts index 505e535b0..e78bb0195 100644 --- a/server/src/interfaces/storage.repository.ts +++ b/server/src/interfaces/storage.repository.ts @@ -2,7 +2,7 @@ import { WatchOptions } from 'chokidar'; import { Stats } from 'node:fs'; import { FileReadOptions } from 'node:fs/promises'; import { Readable } from 'node:stream'; -import { CrawlOptionsDto } from 'src/domain/library/library.dto'; +import { CrawlOptionsDto } from 'src/dtos/library.dto'; export interface ImmichReadStream { stream: Readable; diff --git a/server/src/middleware/auth.guard.ts b/server/src/middleware/auth.guard.ts index 070bf15e8..765e24354 100644 --- a/server/src/middleware/auth.guard.ts +++ b/server/src/middleware/auth.guard.ts @@ -10,8 +10,8 @@ import { Reflector } from '@nestjs/core'; import { ApiBearerAuth, ApiCookieAuth, ApiOkResponse, ApiQuery, ApiSecurity } from '@nestjs/swagger'; import { Request } from 'express'; import { IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; -import { AuthDto } from 'src/domain/auth/auth.dto'; import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; +import { AuthDto } from 'src/dtos/auth.dto'; import { ImmichLogger } from 'src/infra/logger'; import { UAParser } from 'ua-parser-js'; diff --git a/server/src/middleware/file-upload.interceptor.ts b/server/src/middleware/file-upload.interceptor.ts index a7598f99d..9d6abaa3d 100644 --- a/server/src/middleware/file-upload.interceptor.ts +++ b/server/src/middleware/file-upload.interceptor.ts @@ -6,7 +6,8 @@ import { NextFunction, RequestHandler } from 'express'; import multer, { StorageEngine, diskStorage } from 'multer'; import { createHash, randomUUID } from 'node:crypto'; import { Observable } from 'rxjs'; -import { AssetService, UploadFieldName, UploadFile } from 'src/domain/asset/asset.service'; +import { AssetService, UploadFile } from 'src/domain/asset/asset.service'; +import { UploadFieldName } from 'src/dtos/asset.dto'; import { ImmichLogger } from 'src/infra/logger'; import { AuthRequest } from 'src/middleware/auth.guard'; diff --git a/server/src/repositories/filesystem.provider.spec.ts b/server/src/repositories/filesystem.provider.spec.ts index 56f54b036..c9790767c 100644 --- a/server/src/repositories/filesystem.provider.spec.ts +++ b/server/src/repositories/filesystem.provider.spec.ts @@ -1,5 +1,5 @@ import mockfs from 'mock-fs'; -import { CrawlOptionsDto } from 'src/domain/library/library.dto'; +import { CrawlOptionsDto } from 'src/dtos/library.dto'; import { FilesystemProvider } from 'src/repositories/filesystem.provider'; interface Test { diff --git a/server/src/repositories/filesystem.provider.ts b/server/src/repositories/filesystem.provider.ts index 2da49625e..1e65f9664 100644 --- a/server/src/repositories/filesystem.provider.ts +++ b/server/src/repositories/filesystem.provider.ts @@ -5,7 +5,7 @@ import { constants, createReadStream, existsSync, mkdirSync } from 'node:fs'; import fs from 'node:fs/promises'; import path from 'node:path'; import { mimeTypes } from 'src/domain/domain.constant'; -import { CrawlOptionsDto } from 'src/domain/library/library.dto'; +import { CrawlOptionsDto } from 'src/dtos/library.dto'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; import { diff --git a/server/src/repositories/library.repository.ts b/server/src/repositories/library.repository.ts index 7171aad0d..152f544ce 100644 --- a/server/src/repositories/library.repository.ts +++ b/server/src/repositories/library.repository.ts @@ -1,7 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { LibraryStatsResponseDto } from 'src/domain/library/library.dto'; +import { LibraryStatsResponseDto } from 'src/dtos/library.dto'; import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; import { Instrumentation } from 'src/infra/instrumentation'; import { ILibraryRepository } from 'src/interfaces/library.repository'; diff --git a/server/src/repositories/machine-learning.repository.ts b/server/src/repositories/machine-learning.repository.ts index 46d16dcd7..34f0cdbfc 100644 --- a/server/src/repositories/machine-learning.repository.ts +++ b/server/src/repositories/machine-learning.repository.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; import { readFile } from 'node:fs/promises'; -import { CLIPConfig, ModelConfig, RecognitionConfig } from 'src/domain/smart-info/dto/model-config.dto'; +import { CLIPConfig, ModelConfig, RecognitionConfig } from 'src/dtos/model-config.dto'; import { Instrumentation } from 'src/infra/instrumentation'; import { CLIPMode, diff --git a/server/test/fixtures/auth.stub.ts b/server/test/fixtures/auth.stub.ts index e0add44d2..2e56d0001 100644 --- a/server/test/fixtures/auth.stub.ts +++ b/server/test/fixtures/auth.stub.ts @@ -1,4 +1,4 @@ -import { AuthDto } from 'src/domain/auth/auth.dto'; +import { AuthDto } from 'src/dtos/auth.dto'; import { SharedLinkEntity } from 'src/entities/shared-link.entity'; import { UserTokenEntity } from 'src/entities/user-token.entity'; import { UserEntity } from 'src/entities/user.entity'; diff --git a/server/test/fixtures/shared-link.stub.ts b/server/test/fixtures/shared-link.stub.ts index 6855c8c7a..34e3da515 100644 --- a/server/test/fixtures/shared-link.stub.ts +++ b/server/test/fixtures/shared-link.stub.ts @@ -1,8 +1,8 @@ -import { AlbumResponseDto } from 'src/domain/album/album-response.dto'; -import { AssetResponseDto } from 'src/domain/asset/response-dto/asset-response.dto'; -import { ExifResponseDto } from 'src/domain/asset/response-dto/exif-response.dto'; -import { SharedLinkResponseDto } from 'src/domain/shared-link/shared-link-response.dto'; -import { mapUser } from 'src/domain/user/response-dto/user-response.dto'; +import { AlbumResponseDto } from 'src/dtos/album.dto'; +import { AssetResponseDto } from 'src/dtos/asset-response.dto'; +import { ExifResponseDto } from 'src/dtos/exif.dto'; +import { SharedLinkResponseDto } from 'src/dtos/shared-link.dto'; +import { mapUser } from 'src/dtos/user.dto'; import { AssetOrder } from 'src/entities/album.entity'; import { AssetType } from 'src/entities/asset.entity'; import { SharedLinkEntity, SharedLinkType } from 'src/entities/shared-link.entity'; diff --git a/server/test/fixtures/tag.stub.ts b/server/test/fixtures/tag.stub.ts index 27123ddb6..537c65db4 100644 --- a/server/test/fixtures/tag.stub.ts +++ b/server/test/fixtures/tag.stub.ts @@ -1,4 +1,4 @@ -import { TagResponseDto } from 'src/domain/tag/tag-response.dto'; +import { TagResponseDto } from 'src/dtos/tag.dto'; import { TagEntity, TagType } from 'src/entities/tag.entity'; import { userStub } from 'test/fixtures/user.stub'; From ef4a492cb14424de3a791004af6604a795e1eae9 Mon Sep 17 00:00:00 2001 From: Daniel Dietzler <36593685+danieldietzler@users.noreply.github.com> Date: Thu, 21 Mar 2024 00:07:30 +0100 Subject: [PATCH 042/152] chore(server): move services (#8133) move services --- .vscode/settings.json | 4 ++ .../jobs/specs/library-watcher.e2e-spec.ts | 2 +- server/src/apps/api.service.ts | 14 +++--- server/src/apps/app.module.ts | 48 +++++++++---------- server/src/apps/microservices.service.ts | 26 +++++----- server/src/commands/list-users.command.ts | 2 +- server/src/commands/oauth-login.ts | 2 +- server/src/commands/password-login.ts | 2 +- .../commands/reset-admin-password.command.ts | 2 +- server/src/controllers/activity.controller.ts | 2 +- server/src/controllers/album.controller.ts | 2 +- server/src/controllers/api-key.controller.ts | 2 +- server/src/controllers/app.controller.ts | 2 +- server/src/controllers/asset.controller.ts | 4 +- server/src/controllers/audit.controller.ts | 2 +- server/src/controllers/auth.controller.ts | 2 +- server/src/controllers/download.controller.ts | 2 +- server/src/controllers/face.controller.ts | 2 +- server/src/controllers/job.controller.ts | 2 +- server/src/controllers/library.controller.ts | 2 +- server/src/controllers/oauth.controller.ts | 2 +- server/src/controllers/partner.controller.ts | 2 +- server/src/controllers/person.controller.ts | 2 +- server/src/controllers/search.controller.ts | 2 +- .../src/controllers/server-info.controller.ts | 2 +- .../src/controllers/shared-link.controller.ts | 2 +- .../controllers/system-config.controller.ts | 4 +- server/src/controllers/tag.controller.ts | 2 +- server/src/controllers/trash.controller.ts | 2 +- server/src/controllers/user.controller.ts | 2 +- .../system-config-map-theme.dto.ts | 0 .../src/immich/api-v1/asset/asset.service.ts | 2 +- server/src/middleware/auth.guard.ts | 2 +- .../src/middleware/file-upload.interceptor.ts | 2 +- .../repositories/communication.repository.ts | 2 +- .../activity.service.spec.ts} | 2 +- .../activity => services}/activity.service.ts | 0 .../album => services}/album.service.spec.ts | 2 +- .../album => services}/album.service.ts | 0 .../api-key.service.spec.ts | 2 +- .../api-key => services}/api-key.service.ts | 0 .../asset => services}/asset.service.spec.ts | 2 +- .../asset => services}/asset.service.ts | 0 .../audit => services}/audit.service.spec.ts | 2 +- .../audit => services}/audit.service.ts | 0 .../auth => services}/auth.service.spec.ts | 2 +- .../{domain/auth => services}/auth.service.ts | 0 .../database.service.spec.ts | 2 +- .../database => services}/database.service.ts | 0 .../download.service.spec.ts | 2 +- .../download => services}/download.service.ts | 0 .../job => services}/job.service.spec.ts | 2 +- .../{domain/job => services}/job.service.ts | 0 .../library.service.spec.ts | 2 +- .../library => services}/library.service.ts | 0 .../media => services}/media.service.spec.ts | 2 +- .../media => services}/media.service.ts | 0 .../metadata.service.spec.ts | 2 +- .../metadata => services}/metadata.service.ts | 0 .../partner.service.spec.ts | 2 +- .../partner => services}/partner.service.ts | 0 .../person.service.spec.ts | 2 +- .../person => services}/person.service.ts | 0 .../search.service.spec.ts | 2 +- .../search => services}/search.service.ts | 0 .../server-info.service.spec.ts | 2 +- .../server-info.service.ts | 0 .../shared-link.service.spec.ts | 2 +- .../shared-link.service.ts | 0 .../smart-info.service.spec.ts | 2 +- .../smart-info.service.ts | 0 .../storage-template.service.spec.ts | 2 +- .../storage-template.service.ts | 0 .../storage.service.spec.ts | 2 +- .../storage => services}/storage.service.ts | 0 .../system-config.service.spec.ts | 2 +- .../system-config.service.ts | 0 .../tag => services}/tag.service.spec.ts | 2 +- .../{domain/tag => services}/tag.service.ts | 0 .../trash => services}/trash.service.spec.ts | 2 +- .../trash => services}/trash.service.ts | 0 .../user => services}/user.service.spec.ts | 2 +- .../{domain/user => services}/user.service.ts | 0 83 files changed, 104 insertions(+), 100 deletions(-) rename server/src/{domain/system-config => dtos}/system-config-map-theme.dto.ts (100%) rename server/src/{domain/activity/activity.spec.ts => services/activity.service.spec.ts} (98%) rename server/src/{domain/activity => services}/activity.service.ts (100%) rename server/src/{domain/album => services}/album.service.spec.ts (99%) rename server/src/{domain/album => services}/album.service.ts (100%) rename server/src/{domain/api-key => services}/api-key.service.spec.ts (98%) rename server/src/{domain/api-key => services}/api-key.service.ts (100%) rename server/src/{domain/asset => services}/asset.service.spec.ts (99%) rename server/src/{domain/asset => services}/asset.service.ts (100%) rename server/src/{domain/audit => services}/audit.service.spec.ts (98%) rename server/src/{domain/audit => services}/audit.service.ts (100%) rename server/src/{domain/auth => services}/auth.service.spec.ts (99%) rename server/src/{domain/auth => services}/auth.service.ts (100%) rename server/src/{domain/database => services}/database.service.spec.ts (99%) rename server/src/{domain/database => services}/database.service.ts (100%) rename server/src/{domain/download => services}/download.service.spec.ts (99%) rename server/src/{domain/download => services}/download.service.ts (100%) rename server/src/{domain/job => services}/job.service.spec.ts (99%) rename server/src/{domain/job => services}/job.service.ts (100%) rename server/src/{domain/library => services}/library.service.spec.ts (99%) rename server/src/{domain/library => services}/library.service.ts (100%) rename server/src/{domain/media => services}/media.service.spec.ts (99%) rename server/src/{domain/media => services}/media.service.ts (100%) rename server/src/{domain/metadata => services}/metadata.service.spec.ts (99%) rename server/src/{domain/metadata => services}/metadata.service.ts (100%) rename server/src/{domain/partner => services}/partner.service.spec.ts (98%) rename server/src/{domain/partner => services}/partner.service.ts (100%) rename server/src/{domain/person => services}/person.service.spec.ts (99%) rename server/src/{domain/person => services}/person.service.ts (100%) rename server/src/{domain/search => services}/search.service.spec.ts (99%) rename server/src/{domain/search => services}/search.service.ts (100%) rename server/src/{domain/server-info => services}/server-info.service.spec.ts (99%) rename server/src/{domain/server-info => services}/server-info.service.ts (100%) rename server/src/{domain/shared-link => services}/shared-link.service.spec.ts (99%) rename server/src/{domain/shared-link => services}/shared-link.service.ts (100%) rename server/src/{domain/smart-info => services}/smart-info.service.spec.ts (98%) rename server/src/{domain/smart-info => services}/smart-info.service.ts (100%) rename server/src/{domain/storage-template => services}/storage-template.service.spec.ts (99%) rename server/src/{domain/storage-template => services}/storage-template.service.ts (100%) rename server/src/{domain/storage => services}/storage.service.spec.ts (95%) rename server/src/{domain/storage => services}/storage.service.ts (100%) rename server/src/{domain/system-config => services}/system-config.service.spec.ts (99%) rename server/src/{domain/system-config => services}/system-config.service.ts (100%) rename server/src/{domain/tag => services}/tag.service.spec.ts (99%) rename server/src/{domain/tag => services}/tag.service.ts (100%) rename server/src/{domain/trash => services}/trash.service.spec.ts (98%) rename server/src/{domain/trash => services}/trash.service.ts (100%) rename server/src/{domain/user => services}/user.service.spec.ts (99%) rename server/src/{domain/user => services}/user.service.ts (100%) diff --git a/.vscode/settings.json b/.vscode/settings.json index eae6e1a16..3267c6713 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -27,4 +27,8 @@ "cSpell.words": [ "immich" ], + "explorer.fileNesting.enabled": true, + "explorer.fileNesting.patterns": { + "*.ts": "${capture}.spec.ts,${capture}.mock.ts" + } } \ No newline at end of file diff --git a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts index 0a005c7d5..5ce0868b9 100644 --- a/server/e2e/jobs/specs/library-watcher.e2e-spec.ts +++ b/server/e2e/jobs/specs/library-watcher.e2e-spec.ts @@ -1,12 +1,12 @@ import { api } from 'e2e/client'; import fs from 'node:fs/promises'; import path from 'node:path'; -import { LibraryService } from 'src/domain/library/library.service'; import { LoginResponseDto } from 'src/dtos/auth.dto'; import { LibraryResponseDto } from 'src/dtos/library.dto'; import { AssetType } from 'src/entities/asset.entity'; import { LibraryType } from 'src/entities/library.entity'; import { StorageEventType } from 'src/interfaces/storage.repository'; +import { LibraryService } from 'src/services/library.service'; import { IMMICH_TEST_ASSET_PATH, IMMICH_TEST_ASSET_TEMP_PATH, diff --git a/server/src/apps/api.service.ts b/server/src/apps/api.service.ts index 31134cefa..fbd0d0e4a 100644 --- a/server/src/apps/api.service.ts +++ b/server/src/apps/api.service.ts @@ -3,15 +3,15 @@ import { Cron, CronExpression, Interval } from '@nestjs/schedule'; import { NextFunction, Request, Response } from 'express'; import { readFileSync } from 'node:fs'; import { join } from 'node:path'; -import { AuthService } from 'src/domain/auth/auth.service'; -import { DatabaseService } from 'src/domain/database/database.service'; import { ONE_HOUR, WEB_ROOT } from 'src/domain/domain.constant'; -import { JobService } from 'src/domain/job/job.service'; -import { ServerInfoService } from 'src/domain/server-info/server-info.service'; -import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; -import { StorageService } from 'src/domain/storage/storage.service'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; import { ImmichLogger } from 'src/infra/logger'; +import { AuthService } from 'src/services/auth.service'; +import { DatabaseService } from 'src/services/database.service'; +import { JobService } from 'src/services/job.service'; +import { ServerInfoService } from 'src/services/server-info.service'; +import { SharedLinkService } from 'src/services/shared-link.service'; +import { StorageService } from 'src/services/storage.service'; +import { SystemConfigService } from 'src/services/system-config.service'; import { OpenGraphTags } from 'src/utils'; const render = (index: string, meta: OpenGraphTags) => { diff --git a/server/src/apps/app.module.ts b/server/src/apps/app.module.ts index f134d3363..964e2d4e1 100644 --- a/server/src/apps/app.module.ts +++ b/server/src/apps/app.module.ts @@ -6,30 +6,6 @@ import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpenTelemetryModule } from 'nestjs-otel'; import { bullConfig, bullQueues, immichAppConfig } from 'src/config'; -import { ActivityService } from 'src/domain/activity/activity.service'; -import { AlbumService } from 'src/domain/album/album.service'; -import { APIKeyService } from 'src/domain/api-key/api-key.service'; -import { AssetService } from 'src/domain/asset/asset.service'; -import { AuditService } from 'src/domain/audit/audit.service'; -import { AuthService } from 'src/domain/auth/auth.service'; -import { DatabaseService } from 'src/domain/database/database.service'; -import { DownloadService } from 'src/domain/download/download.service'; -import { JobService } from 'src/domain/job/job.service'; -import { LibraryService } from 'src/domain/library/library.service'; -import { MediaService } from 'src/domain/media/media.service'; -import { MetadataService } from 'src/domain/metadata/metadata.service'; -import { PartnerService } from 'src/domain/partner/partner.service'; -import { PersonService } from 'src/domain/person/person.service'; -import { SearchService } from 'src/domain/search/search.service'; -import { ServerInfoService } from 'src/domain/server-info/server-info.service'; -import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; -import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; -import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; -import { StorageService } from 'src/domain/storage/storage.service'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; -import { TagService } from 'src/domain/tag/tag.service'; -import { TrashService } from 'src/domain/trash/trash.service'; -import { UserService } from 'src/domain/user/user.service'; import { databaseEntities } from 'src/entities'; import { databaseConfig } from 'src/infra/database.config'; import { otelConfig } from 'src/infra/instrumentation'; @@ -88,6 +64,30 @@ import { SystemMetadataRepository } from 'src/repositories/system-metadata.repos import { TagRepository } from 'src/repositories/tag.repository'; import { UserTokenRepository } from 'src/repositories/user-token.repository'; import { UserRepository } from 'src/repositories/user.repository'; +import { ActivityService } from 'src/services/activity.service'; +import { AlbumService } from 'src/services/album.service'; +import { APIKeyService } from 'src/services/api-key.service'; +import { AssetService } from 'src/services/asset.service'; +import { AuditService } from 'src/services/audit.service'; +import { AuthService } from 'src/services/auth.service'; +import { DatabaseService } from 'src/services/database.service'; +import { DownloadService } from 'src/services/download.service'; +import { JobService } from 'src/services/job.service'; +import { LibraryService } from 'src/services/library.service'; +import { MediaService } from 'src/services/media.service'; +import { MetadataService } from 'src/services/metadata.service'; +import { PartnerService } from 'src/services/partner.service'; +import { PersonService } from 'src/services/person.service'; +import { SearchService } from 'src/services/search.service'; +import { ServerInfoService } from 'src/services/server-info.service'; +import { SharedLinkService } from 'src/services/shared-link.service'; +import { SmartInfoService } from 'src/services/smart-info.service'; +import { StorageTemplateService } from 'src/services/storage-template.service'; +import { StorageService } from 'src/services/storage.service'; +import { SystemConfigService } from 'src/services/system-config.service'; +import { TagService } from 'src/services/tag.service'; +import { TrashService } from 'src/services/trash.service'; +import { UserService } from 'src/services/user.service'; const services: Provider[] = [ APIKeyService, diff --git a/server/src/apps/microservices.service.ts b/server/src/apps/microservices.service.ts index bfdc37576..8f11583be 100644 --- a/server/src/apps/microservices.service.ts +++ b/server/src/apps/microservices.service.ts @@ -1,20 +1,20 @@ import { Injectable } from '@nestjs/common'; -import { AssetService } from 'src/domain/asset/asset.service'; -import { AuditService } from 'src/domain/audit/audit.service'; -import { DatabaseService } from 'src/domain/database/database.service'; import { JobName } from 'src/domain/job/job.constants'; import { IDeleteFilesJob } from 'src/domain/job/job.interface'; -import { JobService } from 'src/domain/job/job.service'; -import { LibraryService } from 'src/domain/library/library.service'; -import { MediaService } from 'src/domain/media/media.service'; -import { MetadataService } from 'src/domain/metadata/metadata.service'; -import { PersonService } from 'src/domain/person/person.service'; -import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; -import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; -import { StorageService } from 'src/domain/storage/storage.service'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; -import { UserService } from 'src/domain/user/user.service'; import { otelSDK } from 'src/infra/instrumentation'; +import { AssetService } from 'src/services/asset.service'; +import { AuditService } from 'src/services/audit.service'; +import { DatabaseService } from 'src/services/database.service'; +import { JobService } from 'src/services/job.service'; +import { LibraryService } from 'src/services/library.service'; +import { MediaService } from 'src/services/media.service'; +import { MetadataService } from 'src/services/metadata.service'; +import { PersonService } from 'src/services/person.service'; +import { SmartInfoService } from 'src/services/smart-info.service'; +import { StorageTemplateService } from 'src/services/storage-template.service'; +import { StorageService } from 'src/services/storage.service'; +import { SystemConfigService } from 'src/services/system-config.service'; +import { UserService } from 'src/services/user.service'; @Injectable() export class MicroservicesService { diff --git a/server/src/commands/list-users.command.ts b/server/src/commands/list-users.command.ts index 222833fad..32bcc35d9 100644 --- a/server/src/commands/list-users.command.ts +++ b/server/src/commands/list-users.command.ts @@ -1,6 +1,6 @@ import { Command, CommandRunner } from 'nest-commander'; -import { UserService } from 'src/domain/user/user.service'; import { UserEntity } from 'src/entities/user.entity'; +import { UserService } from 'src/services/user.service'; @Command({ name: 'list-users', diff --git a/server/src/commands/oauth-login.ts b/server/src/commands/oauth-login.ts index 12562fae1..c9bb4d5ef 100644 --- a/server/src/commands/oauth-login.ts +++ b/server/src/commands/oauth-login.ts @@ -1,5 +1,5 @@ import { Command, CommandRunner } from 'nest-commander'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { SystemConfigService } from 'src/services/system-config.service'; @Command({ name: 'enable-oauth-login', diff --git a/server/src/commands/password-login.ts b/server/src/commands/password-login.ts index 953a1293a..3d992f858 100644 --- a/server/src/commands/password-login.ts +++ b/server/src/commands/password-login.ts @@ -1,5 +1,5 @@ import { Command, CommandRunner } from 'nest-commander'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { SystemConfigService } from 'src/services/system-config.service'; @Command({ name: 'enable-password-login', diff --git a/server/src/commands/reset-admin-password.command.ts b/server/src/commands/reset-admin-password.command.ts index b67ef418e..a186603a3 100644 --- a/server/src/commands/reset-admin-password.command.ts +++ b/server/src/commands/reset-admin-password.command.ts @@ -1,6 +1,6 @@ import { Command, CommandRunner, InquirerService, Question, QuestionSet } from 'nest-commander'; -import { UserService } from 'src/domain/user/user.service'; import { UserResponseDto } from 'src/dtos/user.dto'; +import { UserService } from 'src/services/user.service'; @Command({ name: 'reset-admin-password', diff --git a/server/src/controllers/activity.controller.ts b/server/src/controllers/activity.controller.ts index 92e8797aa..a65b284ca 100644 --- a/server/src/controllers/activity.controller.ts +++ b/server/src/controllers/activity.controller.ts @@ -1,7 +1,6 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Response } from 'express'; -import { ActivityService } from 'src/domain/activity/activity.service'; import { ActivityCreateDto, ActivityDto, @@ -11,6 +10,7 @@ import { } from 'src/dtos/activity.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; +import { ActivityService } from 'src/services/activity.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Activity') diff --git a/server/src/controllers/album.controller.ts b/server/src/controllers/album.controller.ts index 7cc39a860..c4b11fbb4 100644 --- a/server/src/controllers/album.controller.ts +++ b/server/src/controllers/album.controller.ts @@ -1,6 +1,5 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AlbumService } from 'src/domain/album/album.service'; import { AddUsersDto, AlbumCountResponseDto, @@ -13,6 +12,7 @@ import { import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; +import { AlbumService } from 'src/services/album.service'; import { ParseMeUUIDPipe, UUIDParamDto } from 'src/validation'; @ApiTags('Album') diff --git a/server/src/controllers/api-key.controller.ts b/server/src/controllers/api-key.controller.ts index 9b6838f8d..564b90387 100644 --- a/server/src/controllers/api-key.controller.ts +++ b/server/src/controllers/api-key.controller.ts @@ -1,9 +1,9 @@ import { Body, Controller, Delete, Get, Param, Post, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { APIKeyService } from 'src/domain/api-key/api-key.service'; import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto, APIKeyUpdateDto } from 'src/dtos/api-key.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; +import { APIKeyService } from 'src/services/api-key.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('API Key') diff --git a/server/src/controllers/app.controller.ts b/server/src/controllers/app.controller.ts index d4c7ea5b4..472d0da3f 100644 --- a/server/src/controllers/app.controller.ts +++ b/server/src/controllers/app.controller.ts @@ -1,7 +1,7 @@ import { Controller, Get, Header } from '@nestjs/common'; import { ApiExcludeEndpoint } from '@nestjs/swagger'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; import { PublicRoute } from 'src/middleware/auth.guard'; +import { SystemConfigService } from 'src/services/system-config.service'; @Controller() export class AppController { diff --git a/server/src/controllers/asset.controller.ts b/server/src/controllers/asset.controller.ts index ca44aedfe..37e169113 100644 --- a/server/src/controllers/asset.controller.ts +++ b/server/src/controllers/asset.controller.ts @@ -1,7 +1,5 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common'; import { ApiOperation, ApiTags } from '@nestjs/swagger'; -import { AssetService } from 'src/domain/asset/asset.service'; -import { SearchService } from 'src/domain/search/search.service'; import { AssetResponseDto, MemoryLaneResponseDto } from 'src/dtos/asset-response.dto'; import { AssetBulkDeleteDto, @@ -19,6 +17,8 @@ import { UpdateStackParentDto } from 'src/dtos/stack.dto'; import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto'; import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; import { Route } from 'src/middleware/file-upload.interceptor'; +import { AssetService } from 'src/services/asset.service'; +import { SearchService } from 'src/services/search.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Asset') diff --git a/server/src/controllers/audit.controller.ts b/server/src/controllers/audit.controller.ts index b4d27b4ce..1487e78d4 100644 --- a/server/src/controllers/audit.controller.ts +++ b/server/src/controllers/audit.controller.ts @@ -1,6 +1,5 @@ import { Body, Controller, Get, Post, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { AuditService } from 'src/domain/audit/audit.service'; import { AuditDeletesDto, AuditDeletesResponseDto, @@ -11,6 +10,7 @@ import { } from 'src/dtos/audit.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { AdminRoute, Auth, Authenticated } from 'src/middleware/auth.guard'; +import { AuditService } from 'src/services/audit.service'; @ApiTags('Audit') @Controller('audit') diff --git a/server/src/controllers/auth.controller.ts b/server/src/controllers/auth.controller.ts index 6197c1e5f..cbb649dc0 100644 --- a/server/src/controllers/auth.controller.ts +++ b/server/src/controllers/auth.controller.ts @@ -2,7 +2,6 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Req, import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; import { IMMICH_ACCESS_COOKIE, IMMICH_AUTH_TYPE_COOKIE, IMMICH_IS_AUTHENTICATED } from 'src/domain/auth/auth.constant'; -import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; import { AuthDeviceResponseDto, AuthDto, @@ -15,6 +14,7 @@ import { } from 'src/dtos/auth.dto'; import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard'; +import { AuthService, LoginDetails } from 'src/services/auth.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Authentication') diff --git a/server/src/controllers/download.controller.ts b/server/src/controllers/download.controller.ts index 8ba5d4281..66cdc1fac 100644 --- a/server/src/controllers/download.controller.ts +++ b/server/src/controllers/download.controller.ts @@ -1,12 +1,12 @@ import { Body, Controller, HttpCode, HttpStatus, Next, Param, Post, Res, StreamableFile } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { DownloadService } from 'src/domain/download/download.service'; import { AssetIdsDto } from 'src/dtos/asset.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto'; import { asStreamableFile, sendFile } from 'src/immich/app.utils'; import { Auth, Authenticated, FileResponse, SharedLinkRoute } from 'src/middleware/auth.guard'; +import { DownloadService } from 'src/services/download.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Download') diff --git a/server/src/controllers/face.controller.ts b/server/src/controllers/face.controller.ts index d5712d6b7..a3f33fb86 100644 --- a/server/src/controllers/face.controller.ts +++ b/server/src/controllers/face.controller.ts @@ -1,9 +1,9 @@ import { Body, Controller, Get, Param, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { PersonService } from 'src/domain/person/person.service'; import { AuthDto } from 'src/dtos/auth.dto'; import { AssetFaceResponseDto, FaceDto, PersonResponseDto } from 'src/dtos/person.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; +import { PersonService } from 'src/services/person.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Face') diff --git a/server/src/controllers/job.controller.ts b/server/src/controllers/job.controller.ts index 04dea79ee..d6bd45b1e 100644 --- a/server/src/controllers/job.controller.ts +++ b/server/src/controllers/job.controller.ts @@ -1,8 +1,8 @@ import { Body, Controller, Get, Param, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { JobService } from 'src/domain/job/job.service'; import { AllJobStatusResponseDto, JobCommandDto, JobIdParamDto, JobStatusDto } from 'src/dtos/job.dto'; import { Authenticated } from 'src/middleware/auth.guard'; +import { JobService } from 'src/services/job.service'; @ApiTags('Job') @Controller('jobs') diff --git a/server/src/controllers/library.controller.ts b/server/src/controllers/library.controller.ts index 96c5f7415..70d357187 100644 --- a/server/src/controllers/library.controller.ts +++ b/server/src/controllers/library.controller.ts @@ -1,6 +1,5 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { LibraryService } from 'src/domain/library/library.service'; import { CreateLibraryDto, LibraryResponseDto, @@ -12,6 +11,7 @@ import { ValidateLibraryResponseDto, } from 'src/dtos/library.dto'; import { AdminRoute, Authenticated } from 'src/middleware/auth.guard'; +import { LibraryService } from 'src/services/library.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Library') diff --git a/server/src/controllers/oauth.controller.ts b/server/src/controllers/oauth.controller.ts index 6da9faa17..debbd4e67 100644 --- a/server/src/controllers/oauth.controller.ts +++ b/server/src/controllers/oauth.controller.ts @@ -1,7 +1,6 @@ import { Body, Controller, Get, HttpStatus, Post, Redirect, Req, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; -import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; import { AuthDto, LoginResponseDto, @@ -11,6 +10,7 @@ import { } from 'src/dtos/auth.dto'; import { UserResponseDto } from 'src/dtos/user.dto'; import { Auth, Authenticated, GetLoginDetails, PublicRoute } from 'src/middleware/auth.guard'; +import { AuthService, LoginDetails } from 'src/services/auth.service'; @ApiTags('OAuth') @Controller('oauth') diff --git a/server/src/controllers/partner.controller.ts b/server/src/controllers/partner.controller.ts index c4f22a04f..c7d5613f7 100644 --- a/server/src/controllers/partner.controller.ts +++ b/server/src/controllers/partner.controller.ts @@ -1,10 +1,10 @@ import { Body, Controller, Delete, Get, Param, Post, Put, Query } from '@nestjs/common'; import { ApiQuery, ApiTags } from '@nestjs/swagger'; -import { PartnerService } from 'src/domain/partner/partner.service'; import { AuthDto } from 'src/dtos/auth.dto'; import { PartnerResponseDto, UpdatePartnerDto } from 'src/dtos/partner.dto'; import { PartnerDirection } from 'src/interfaces/partner.repository'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; +import { PartnerService } from 'src/services/partner.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Partner') diff --git a/server/src/controllers/person.controller.ts b/server/src/controllers/person.controller.ts index 9c5602091..5e45fc929 100644 --- a/server/src/controllers/person.controller.ts +++ b/server/src/controllers/person.controller.ts @@ -1,7 +1,6 @@ import { Body, Controller, Get, Next, Param, Post, Put, Query, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { PersonService } from 'src/domain/person/person.service'; import { BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; @@ -18,6 +17,7 @@ import { } from 'src/dtos/person.dto'; import { sendFile } from 'src/immich/app.utils'; import { Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; +import { PersonService } from 'src/services/person.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Person') diff --git a/server/src/controllers/search.controller.ts b/server/src/controllers/search.controller.ts index 6b88f5ad8..eaf45be29 100644 --- a/server/src/controllers/search.controller.ts +++ b/server/src/controllers/search.controller.ts @@ -1,6 +1,5 @@ import { Body, Controller, Get, HttpCode, HttpStatus, Post, Query } from '@nestjs/common'; import { ApiOperation, ApiTags } from '@nestjs/swagger'; -import { SearchService } from 'src/domain/search/search.service'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { PersonResponseDto } from 'src/dtos/person.dto'; @@ -16,6 +15,7 @@ import { SmartSearchDto, } from 'src/dtos/search.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; +import { SearchService } from 'src/services/search.service'; @ApiTags('Search') @Controller('search') diff --git a/server/src/controllers/server-info.controller.ts b/server/src/controllers/server-info.controller.ts index 9937acde8..e32b0d191 100644 --- a/server/src/controllers/server-info.controller.ts +++ b/server/src/controllers/server-info.controller.ts @@ -1,6 +1,5 @@ import { Controller, Get, HttpCode, HttpStatus, Post } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { ServerInfoService } from 'src/domain/server-info/server-info.service'; import { ServerConfigDto, ServerFeaturesDto, @@ -12,6 +11,7 @@ import { ServerVersionResponseDto, } from 'src/dtos/server-info.dto'; import { AdminRoute, Authenticated, PublicRoute } from 'src/middleware/auth.guard'; +import { ServerInfoService } from 'src/services/server-info.service'; @ApiTags('Server Info') @Controller('server-info') diff --git a/server/src/controllers/shared-link.controller.ts b/server/src/controllers/shared-link.controller.ts index 90bbd6ee1..61dd6605a 100644 --- a/server/src/controllers/shared-link.controller.ts +++ b/server/src/controllers/shared-link.controller.ts @@ -2,7 +2,6 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query, Req, Res import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; import { IMMICH_SHARED_LINK_ACCESS_COOKIE } from 'src/domain/auth/auth.constant'; -import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto'; import { AssetIdsDto } from 'src/dtos/asset.dto'; import { AuthDto } from 'src/dtos/auth.dto'; @@ -13,6 +12,7 @@ import { SharedLinkResponseDto, } from 'src/dtos/shared-link.dto'; import { Auth, Authenticated, SharedLinkRoute } from 'src/middleware/auth.guard'; +import { SharedLinkService } from 'src/services/shared-link.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Shared Link') diff --git a/server/src/controllers/system-config.controller.ts b/server/src/controllers/system-config.controller.ts index 34f9f2e0e..ca2bbb5f5 100644 --- a/server/src/controllers/system-config.controller.ts +++ b/server/src/controllers/system-config.controller.ts @@ -1,10 +1,10 @@ import { Body, Controller, Get, Put, Query } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { MapThemeDto } from 'src/domain/system-config/system-config-map-theme.dto'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; +import { MapThemeDto } from 'src/dtos/system-config-map-theme.dto'; import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config-storage-template.dto'; import { SystemConfigDto } from 'src/dtos/system-config.dto'; import { AdminRoute, Authenticated } from 'src/middleware/auth.guard'; +import { SystemConfigService } from 'src/services/system-config.service'; @ApiTags('System Config') @Controller('system-config') diff --git a/server/src/controllers/tag.controller.ts b/server/src/controllers/tag.controller.ts index bbca4a05d..1caed8d52 100644 --- a/server/src/controllers/tag.controller.ts +++ b/server/src/controllers/tag.controller.ts @@ -1,12 +1,12 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { TagService } from 'src/domain/tag/tag.service'; import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto'; import { AssetResponseDto } from 'src/dtos/asset-response.dto'; import { AssetIdsDto } from 'src/dtos/asset.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { CreateTagDto, TagResponseDto, UpdateTagDto } from 'src/dtos/tag.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; +import { TagService } from 'src/services/tag.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('Tag') diff --git a/server/src/controllers/trash.controller.ts b/server/src/controllers/trash.controller.ts index 5ea692d48..25df3543c 100644 --- a/server/src/controllers/trash.controller.ts +++ b/server/src/controllers/trash.controller.ts @@ -1,9 +1,9 @@ import { Body, Controller, HttpCode, HttpStatus, Post } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; -import { TrashService } from 'src/domain/trash/trash.service'; import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { Auth, Authenticated } from 'src/middleware/auth.guard'; +import { TrashService } from 'src/services/trash.service'; @ApiTags('Trash') @Controller('trash') diff --git a/server/src/controllers/user.controller.ts b/server/src/controllers/user.controller.ts index 9fc0ff320..0663ae197 100644 --- a/server/src/controllers/user.controller.ts +++ b/server/src/controllers/user.controller.ts @@ -16,13 +16,13 @@ import { } from '@nestjs/common'; import { ApiBody, ApiConsumes, ApiTags } from '@nestjs/swagger'; import { NextFunction, Response } from 'express'; -import { UserService } from 'src/domain/user/user.service'; import { AuthDto } from 'src/dtos/auth.dto'; import { CreateProfileImageDto, CreateProfileImageResponseDto } from 'src/dtos/user-profile.dto'; import { CreateUserDto, DeleteUserDto, UpdateUserDto, UserResponseDto } from 'src/dtos/user.dto'; import { sendFile } from 'src/immich/app.utils'; import { AdminRoute, Auth, Authenticated, FileResponse } from 'src/middleware/auth.guard'; import { FileUploadInterceptor, Route } from 'src/middleware/file-upload.interceptor'; +import { UserService } from 'src/services/user.service'; import { UUIDParamDto } from 'src/validation'; @ApiTags('User') diff --git a/server/src/domain/system-config/system-config-map-theme.dto.ts b/server/src/dtos/system-config-map-theme.dto.ts similarity index 100% rename from server/src/domain/system-config/system-config-map-theme.dto.ts rename to server/src/dtos/system-config-map-theme.dto.ts diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index ee310c377..023017130 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -6,7 +6,6 @@ import { NotFoundException, } from '@nestjs/common'; import { AccessCore, Permission } from 'src/cores/access.core'; -import { UploadFile } from 'src/domain/asset/asset.service'; import { mimeTypes } from 'src/domain/domain.constant'; import { JobName } from 'src/domain/job/job.constants'; import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; @@ -36,6 +35,7 @@ import { IJobRepository } from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { UploadFile } from 'src/services/asset.service'; import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/utils'; import { QueryFailedError } from 'typeorm'; diff --git a/server/src/middleware/auth.guard.ts b/server/src/middleware/auth.guard.ts index 765e24354..48befd9a2 100644 --- a/server/src/middleware/auth.guard.ts +++ b/server/src/middleware/auth.guard.ts @@ -10,9 +10,9 @@ import { Reflector } from '@nestjs/core'; import { ApiBearerAuth, ApiCookieAuth, ApiOkResponse, ApiQuery, ApiSecurity } from '@nestjs/swagger'; import { Request } from 'express'; import { IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; -import { AuthService, LoginDetails } from 'src/domain/auth/auth.service'; import { AuthDto } from 'src/dtos/auth.dto'; import { ImmichLogger } from 'src/infra/logger'; +import { AuthService, LoginDetails } from 'src/services/auth.service'; import { UAParser } from 'ua-parser-js'; export enum Metadata { diff --git a/server/src/middleware/file-upload.interceptor.ts b/server/src/middleware/file-upload.interceptor.ts index 9d6abaa3d..f1d5c5c34 100644 --- a/server/src/middleware/file-upload.interceptor.ts +++ b/server/src/middleware/file-upload.interceptor.ts @@ -6,10 +6,10 @@ import { NextFunction, RequestHandler } from 'express'; import multer, { StorageEngine, diskStorage } from 'multer'; import { createHash, randomUUID } from 'node:crypto'; import { Observable } from 'rxjs'; -import { AssetService, UploadFile } from 'src/domain/asset/asset.service'; import { UploadFieldName } from 'src/dtos/asset.dto'; import { ImmichLogger } from 'src/infra/logger'; import { AuthRequest } from 'src/middleware/auth.guard'; +import { AssetService, UploadFile } from 'src/services/asset.service'; export enum Route { ASSET = 'asset', diff --git a/server/src/repositories/communication.repository.ts b/server/src/repositories/communication.repository.ts index e92fe1387..549975c74 100644 --- a/server/src/repositories/communication.repository.ts +++ b/server/src/repositories/communication.repository.ts @@ -7,7 +7,6 @@ import { WebSocketServer, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; -import { AuthService } from 'src/domain/auth/auth.service'; import { Instrumentation } from 'src/infra/instrumentation'; import { ImmichLogger } from 'src/infra/logger'; import { @@ -18,6 +17,7 @@ import { OnServerEventCallback, ServerEvent, } from 'src/interfaces/communication.repository'; +import { AuthService } from 'src/services/auth.service'; @Instrumentation() @WebSocketGateway({ diff --git a/server/src/domain/activity/activity.spec.ts b/server/src/services/activity.service.spec.ts similarity index 98% rename from server/src/domain/activity/activity.spec.ts rename to server/src/services/activity.service.spec.ts index 6013f0ff0..a36d82554 100644 --- a/server/src/domain/activity/activity.spec.ts +++ b/server/src/services/activity.service.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException } from '@nestjs/common'; -import { ActivityService } from 'src/domain/activity/activity.service'; import { ReactionType } from 'src/dtos/activity.dto'; import { IActivityRepository } from 'src/interfaces/activity.repository'; +import { ActivityService } from 'src/services/activity.service'; import { activityStub } from 'test/fixtures/activity.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; diff --git a/server/src/domain/activity/activity.service.ts b/server/src/services/activity.service.ts similarity index 100% rename from server/src/domain/activity/activity.service.ts rename to server/src/services/activity.service.ts diff --git a/server/src/domain/album/album.service.spec.ts b/server/src/services/album.service.spec.ts similarity index 99% rename from server/src/domain/album/album.service.spec.ts rename to server/src/services/album.service.spec.ts index 41b505ea6..6a09f54d1 100644 --- a/server/src/domain/album/album.service.spec.ts +++ b/server/src/services/album.service.spec.ts @@ -1,10 +1,10 @@ import { BadRequestException } from '@nestjs/common'; import _ from 'lodash'; -import { AlbumService } from 'src/domain/album/album.service'; import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { AlbumService } from 'src/services/album.service'; import { albumStub } from 'test/fixtures/album.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/src/domain/album/album.service.ts b/server/src/services/album.service.ts similarity index 100% rename from server/src/domain/album/album.service.ts rename to server/src/services/album.service.ts diff --git a/server/src/domain/api-key/api-key.service.spec.ts b/server/src/services/api-key.service.spec.ts similarity index 98% rename from server/src/domain/api-key/api-key.service.spec.ts rename to server/src/services/api-key.service.spec.ts index 0400c13a2..66dd70d0f 100644 --- a/server/src/domain/api-key/api-key.service.spec.ts +++ b/server/src/services/api-key.service.spec.ts @@ -1,7 +1,7 @@ import { BadRequestException } from '@nestjs/common'; -import { APIKeyService } from 'src/domain/api-key/api-key.service'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { APIKeyService } from 'src/services/api-key.service'; import { keyStub } from 'test/fixtures/api-key.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { newKeyRepositoryMock } from 'test/repositories/api-key.repository.mock'; diff --git a/server/src/domain/api-key/api-key.service.ts b/server/src/services/api-key.service.ts similarity index 100% rename from server/src/domain/api-key/api-key.service.ts rename to server/src/services/api-key.service.ts diff --git a/server/src/domain/asset/asset.service.spec.ts b/server/src/services/asset.service.spec.ts similarity index 99% rename from server/src/domain/asset/asset.service.spec.ts rename to server/src/services/asset.service.spec.ts index a3603c3da..3a6385c03 100644 --- a/server/src/domain/asset/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -1,6 +1,5 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { when } from 'jest-when'; -import { AssetService } from 'src/domain/asset/asset.service'; import { JobName } from 'src/domain/job/job.constants'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AssetJobName, AssetStatsResponseDto, UploadFieldName } from 'src/dtos/asset.dto'; @@ -13,6 +12,7 @@ import { IPartnerRepository } from 'src/interfaces/partner.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { AssetService } from 'src/services/asset.service'; import { assetStackStub, assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { faceStub } from 'test/fixtures/face.stub'; diff --git a/server/src/domain/asset/asset.service.ts b/server/src/services/asset.service.ts similarity index 100% rename from server/src/domain/asset/asset.service.ts rename to server/src/services/asset.service.ts diff --git a/server/src/domain/audit/audit.service.spec.ts b/server/src/services/audit.service.spec.ts similarity index 98% rename from server/src/domain/audit/audit.service.spec.ts rename to server/src/services/audit.service.spec.ts index ecda57b08..14d08f916 100644 --- a/server/src/domain/audit/audit.service.spec.ts +++ b/server/src/services/audit.service.spec.ts @@ -1,4 +1,3 @@ -import { AuditService } from 'src/domain/audit/audit.service'; import { DatabaseAction, EntityType } from 'src/entities/audit.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IAuditRepository } from 'src/interfaces/audit.repository'; @@ -7,6 +6,7 @@ import { JobStatus } from 'src/interfaces/job.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { AuditService } from 'src/services/audit.service'; import { auditStub } from 'test/fixtures/audit.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; diff --git a/server/src/domain/audit/audit.service.ts b/server/src/services/audit.service.ts similarity index 100% rename from server/src/domain/audit/audit.service.ts rename to server/src/services/audit.service.ts diff --git a/server/src/domain/auth/auth.service.spec.ts b/server/src/services/auth.service.spec.ts similarity index 99% rename from server/src/domain/auth/auth.service.spec.ts rename to server/src/services/auth.service.spec.ts index 37c759937..dc7565e4d 100644 --- a/server/src/domain/auth/auth.service.spec.ts +++ b/server/src/services/auth.service.spec.ts @@ -3,7 +3,6 @@ import { IncomingHttpHeaders } from 'node:http'; import { Issuer, generators } from 'openid-client'; import { Socket } from 'socket.io'; import { AuthType } from 'src/domain/auth/auth.constant'; -import { AuthService } from 'src/domain/auth/auth.service'; import { AuthDto, SignUpDto } from 'src/dtos/auth.dto'; import { UserEntity } from 'src/entities/user.entity'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; @@ -13,6 +12,7 @@ import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { AuthService } from 'src/services/auth.service'; import { keyStub } from 'test/fixtures/api-key.stub'; import { authStub, loginResponseStub } from 'test/fixtures/auth.stub'; import { sharedLinkStub } from 'test/fixtures/shared-link.stub'; diff --git a/server/src/domain/auth/auth.service.ts b/server/src/services/auth.service.ts similarity index 100% rename from server/src/domain/auth/auth.service.ts rename to server/src/services/auth.service.ts diff --git a/server/src/domain/database/database.service.spec.ts b/server/src/services/database.service.spec.ts similarity index 99% rename from server/src/domain/database/database.service.spec.ts rename to server/src/services/database.service.spec.ts index 191c0221b..dac857a07 100644 --- a/server/src/domain/database/database.service.spec.ts +++ b/server/src/services/database.service.spec.ts @@ -1,7 +1,7 @@ -import { DatabaseService } from 'src/domain/database/database.service'; import { Version, VersionType } from 'src/domain/domain.constant'; import { ImmichLogger } from 'src/infra/logger'; import { DatabaseExtension, IDatabaseRepository, VectorIndex } from 'src/interfaces/database.repository'; +import { DatabaseService } from 'src/services/database.service'; import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; describe(DatabaseService.name, () => { diff --git a/server/src/domain/database/database.service.ts b/server/src/services/database.service.ts similarity index 100% rename from server/src/domain/database/database.service.ts rename to server/src/services/database.service.ts diff --git a/server/src/domain/download/download.service.spec.ts b/server/src/services/download.service.spec.ts similarity index 99% rename from server/src/domain/download/download.service.spec.ts rename to server/src/services/download.service.spec.ts index cfdff82b9..ab8389955 100644 --- a/server/src/domain/download/download.service.spec.ts +++ b/server/src/services/download.service.spec.ts @@ -1,9 +1,9 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; -import { DownloadService } from 'src/domain/download/download.service'; import { DownloadResponseDto } from 'src/dtos/download.dto'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { DownloadService } from 'src/services/download.service'; import { CacheControl, ImmichFileResponse } from 'src/utils'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/download/download.service.ts b/server/src/services/download.service.ts similarity index 100% rename from server/src/domain/download/download.service.ts rename to server/src/services/download.service.ts diff --git a/server/src/domain/job/job.service.spec.ts b/server/src/services/job.service.spec.ts similarity index 99% rename from server/src/domain/job/job.service.spec.ts rename to server/src/services/job.service.spec.ts index ec905b062..4be9786a2 100644 --- a/server/src/domain/job/job.service.spec.ts +++ b/server/src/services/job.service.spec.ts @@ -1,13 +1,13 @@ import { BadRequestException } from '@nestjs/common'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; import { JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; -import { JobService } from 'src/domain/job/job.service'; import { SystemConfig, SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ICommunicationRepository } from 'src/interfaces/communication.repository'; import { IJobRepository, JobHandler, JobItem, JobStatus } from 'src/interfaces/job.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { JobService } from 'src/services/job.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; diff --git a/server/src/domain/job/job.service.ts b/server/src/services/job.service.ts similarity index 100% rename from server/src/domain/job/job.service.ts rename to server/src/services/job.service.ts diff --git a/server/src/domain/library/library.service.spec.ts b/server/src/services/library.service.spec.ts similarity index 99% rename from server/src/domain/library/library.service.spec.ts rename to server/src/services/library.service.spec.ts index 81bf1cc86..2382d83c2 100644 --- a/server/src/domain/library/library.service.spec.ts +++ b/server/src/services/library.service.spec.ts @@ -5,7 +5,6 @@ import { Stats } from 'node:fs'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { JobName } from 'src/domain/job/job.constants'; import { ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; -import { LibraryService } from 'src/domain/library/library.service'; import { mapLibrary } from 'src/dtos/library.dto'; import { AssetType } from 'src/entities/asset.entity'; import { LibraryType } from 'src/entities/library.entity'; @@ -18,6 +17,7 @@ import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository, StorageEventType } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { LibraryService } from 'src/services/library.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { libraryStub } from 'test/fixtures/library.stub'; diff --git a/server/src/domain/library/library.service.ts b/server/src/services/library.service.ts similarity index 100% rename from server/src/domain/library/library.service.ts rename to server/src/services/library.service.ts diff --git a/server/src/domain/media/media.service.spec.ts b/server/src/services/media.service.spec.ts similarity index 99% rename from server/src/domain/media/media.service.spec.ts rename to server/src/services/media.service.spec.ts index 97a6d161b..eb9407e12 100644 --- a/server/src/domain/media/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -1,6 +1,5 @@ import { Stats } from 'node:fs'; import { JobName } from 'src/domain/job/job.constants'; -import { MediaService } from 'src/domain/media/media.service'; import { AssetType } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { @@ -20,6 +19,7 @@ import { IMoveRepository } from 'src/interfaces/move.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { MediaService } from 'src/services/media.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { faceStub } from 'test/fixtures/face.stub'; import { probeStub } from 'test/fixtures/media.stub'; diff --git a/server/src/domain/media/media.service.ts b/server/src/services/media.service.ts similarity index 100% rename from server/src/domain/media/media.service.ts rename to server/src/services/media.service.ts diff --git a/server/src/domain/metadata/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts similarity index 99% rename from server/src/domain/metadata/metadata.service.spec.ts rename to server/src/services/metadata.service.spec.ts index 2108c5fc4..a235aca04 100644 --- a/server/src/domain/metadata/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -4,7 +4,6 @@ import { randomBytes } from 'node:crypto'; import { Stats } from 'node:fs'; import { constants } from 'node:fs/promises'; import { JobName } from 'src/domain/job/job.constants'; -import { MetadataService, Orientation } from 'src/domain/metadata/metadata.service'; import { AssetType } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { SystemConfigKey } from 'src/entities/system-config.entity'; @@ -20,6 +19,7 @@ import { IMoveRepository } from 'src/interfaces/move.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { MetadataService, Orientation } from 'src/services/metadata.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { fileStub } from 'test/fixtures/file.stub'; import { probeStub } from 'test/fixtures/media.stub'; diff --git a/server/src/domain/metadata/metadata.service.ts b/server/src/services/metadata.service.ts similarity index 100% rename from server/src/domain/metadata/metadata.service.ts rename to server/src/services/metadata.service.ts diff --git a/server/src/domain/partner/partner.service.spec.ts b/server/src/services/partner.service.spec.ts similarity index 98% rename from server/src/domain/partner/partner.service.spec.ts rename to server/src/services/partner.service.spec.ts index 1256a9ca0..94ec3b099 100644 --- a/server/src/domain/partner/partner.service.spec.ts +++ b/server/src/services/partner.service.spec.ts @@ -1,9 +1,9 @@ import { BadRequestException } from '@nestjs/common'; -import { PartnerService } from 'src/domain/partner/partner.service'; import { PartnerResponseDto } from 'src/dtos/partner.dto'; import { UserAvatarColor } from 'src/entities/user.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IPartnerRepository, PartnerDirection } from 'src/interfaces/partner.repository'; +import { PartnerService } from 'src/services/partner.service'; import { authStub } from 'test/fixtures/auth.stub'; import { partnerStub } from 'test/fixtures/partner.stub'; import { newPartnerRepositoryMock } from 'test/repositories/partner.repository.mock'; diff --git a/server/src/domain/partner/partner.service.ts b/server/src/services/partner.service.ts similarity index 100% rename from server/src/domain/partner/partner.service.ts rename to server/src/services/partner.service.ts diff --git a/server/src/domain/person/person.service.spec.ts b/server/src/services/person.service.spec.ts similarity index 99% rename from server/src/domain/person/person.service.spec.ts rename to server/src/services/person.service.spec.ts index 3f555e34f..7abc9f3d9 100644 --- a/server/src/domain/person/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -1,6 +1,5 @@ import { BadRequestException, NotFoundException } from '@nestjs/common'; import { JobName } from 'src/domain/job/job.constants'; -import { PersonService } from 'src/domain/person/person.service'; import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { PersonResponseDto, mapFaces, mapPerson } from 'src/dtos/person.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; @@ -15,6 +14,7 @@ import { IPersonRepository } from 'src/interfaces/person.repository'; import { FaceSearchResult, ISearchRepository } from 'src/interfaces/search.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { PersonService } from 'src/services/person.service'; import { CacheControl, ImmichFileResponse } from 'src/utils'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/person/person.service.ts b/server/src/services/person.service.ts similarity index 100% rename from server/src/domain/person/person.service.ts rename to server/src/services/person.service.ts diff --git a/server/src/domain/search/search.service.spec.ts b/server/src/services/search.service.spec.ts similarity index 99% rename from server/src/domain/search/search.service.spec.ts rename to server/src/services/search.service.spec.ts index 7f83f2ff0..c7566ea94 100644 --- a/server/src/domain/search/search.service.spec.ts +++ b/server/src/services/search.service.spec.ts @@ -1,4 +1,3 @@ -import { SearchService } from 'src/domain/search/search.service'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { SearchDto } from 'src/dtos/search.dto'; import { SystemConfigKey } from 'src/entities/system-config.entity'; @@ -9,6 +8,7 @@ import { IPartnerRepository } from 'src/interfaces/partner.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { ISearchRepository } from 'src/interfaces/search.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { SearchService } from 'src/services/search.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { personStub } from 'test/fixtures/person.stub'; diff --git a/server/src/domain/search/search.service.ts b/server/src/services/search.service.ts similarity index 100% rename from server/src/domain/search/search.service.ts rename to server/src/services/search.service.ts diff --git a/server/src/domain/server-info/server-info.service.spec.ts b/server/src/services/server-info.service.spec.ts similarity index 99% rename from server/src/domain/server-info/server-info.service.spec.ts rename to server/src/services/server-info.service.spec.ts index 1685f8bda..0db7597b8 100644 --- a/server/src/domain/server-info/server-info.service.spec.ts +++ b/server/src/services/server-info.service.spec.ts @@ -1,5 +1,4 @@ import { serverVersion } from 'src/domain/domain.constant'; -import { ServerInfoService } from 'src/domain/server-info/server-info.service'; import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; import { ICommunicationRepository } from 'src/interfaces/communication.repository'; import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; @@ -7,6 +6,7 @@ import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { ServerInfoService } from 'src/services/server-info.service'; import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; diff --git a/server/src/domain/server-info/server-info.service.ts b/server/src/services/server-info.service.ts similarity index 100% rename from server/src/domain/server-info/server-info.service.ts rename to server/src/services/server-info.service.ts diff --git a/server/src/domain/shared-link/shared-link.service.spec.ts b/server/src/services/shared-link.service.spec.ts similarity index 99% rename from server/src/domain/shared-link/shared-link.service.spec.ts rename to server/src/services/shared-link.service.spec.ts index e5e3ea6e2..611d9b670 100644 --- a/server/src/domain/shared-link/shared-link.service.spec.ts +++ b/server/src/services/shared-link.service.spec.ts @@ -1,10 +1,10 @@ import { BadRequestException, ForbiddenException, UnauthorizedException } from '@nestjs/common'; import _ from 'lodash'; -import { SharedLinkService } from 'src/domain/shared-link/shared-link.service'; import { AssetIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { SharedLinkType } from 'src/entities/shared-link.entity'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; +import { SharedLinkService } from 'src/services/shared-link.service'; import { albumStub } from 'test/fixtures/album.stub'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/domain/shared-link/shared-link.service.ts b/server/src/services/shared-link.service.ts similarity index 100% rename from server/src/domain/shared-link/shared-link.service.ts rename to server/src/services/shared-link.service.ts diff --git a/server/src/domain/smart-info/smart-info.service.spec.ts b/server/src/services/smart-info.service.spec.ts similarity index 98% rename from server/src/domain/smart-info/smart-info.service.spec.ts rename to server/src/services/smart-info.service.spec.ts index 29ce75fb4..a1b8943f2 100644 --- a/server/src/domain/smart-info/smart-info.service.spec.ts +++ b/server/src/services/smart-info.service.spec.ts @@ -1,6 +1,5 @@ import { JobName } from 'src/domain/job/job.constants'; import { cleanModelName, getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; -import { SmartInfoService } from 'src/domain/smart-info/smart-info.service'; import { AssetEntity } from 'src/entities/asset.entity'; import { SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; @@ -9,6 +8,7 @@ import { IJobRepository } from 'src/interfaces/job.repository'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; import { ISearchRepository } from 'src/interfaces/search.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { SmartInfoService } from 'src/services/smart-info.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; diff --git a/server/src/domain/smart-info/smart-info.service.ts b/server/src/services/smart-info.service.ts similarity index 100% rename from server/src/domain/smart-info/smart-info.service.ts rename to server/src/services/smart-info.service.ts diff --git a/server/src/domain/storage-template/storage-template.service.spec.ts b/server/src/services/storage-template.service.spec.ts similarity index 99% rename from server/src/domain/storage-template/storage-template.service.spec.ts rename to server/src/services/storage-template.service.spec.ts index ecadb3e86..b11d1f534 100644 --- a/server/src/domain/storage-template/storage-template.service.spec.ts +++ b/server/src/services/storage-template.service.spec.ts @@ -1,7 +1,6 @@ import { when } from 'jest-when'; import { Stats } from 'node:fs'; import { SystemConfigCore, defaults } from 'src/cores/system-config.core'; -import { StorageTemplateService } from 'src/domain/storage-template/storage-template.service'; import { AssetPathType } from 'src/entities/move.entity'; import { SystemConfig, SystemConfigKey } from 'src/entities/system-config.entity'; import { IAlbumRepository } from 'src/interfaces/album.repository'; @@ -14,6 +13,7 @@ import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { StorageTemplateService } from 'src/services/storage-template.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { userStub } from 'test/fixtures/user.stub'; import { newAlbumRepositoryMock } from 'test/repositories/album.repository.mock'; diff --git a/server/src/domain/storage-template/storage-template.service.ts b/server/src/services/storage-template.service.ts similarity index 100% rename from server/src/domain/storage-template/storage-template.service.ts rename to server/src/services/storage-template.service.ts diff --git a/server/src/domain/storage/storage.service.spec.ts b/server/src/services/storage.service.spec.ts similarity index 95% rename from server/src/domain/storage/storage.service.spec.ts rename to server/src/services/storage.service.spec.ts index 2791c9630..4a5607efe 100644 --- a/server/src/domain/storage/storage.service.spec.ts +++ b/server/src/services/storage.service.spec.ts @@ -1,5 +1,5 @@ -import { StorageService } from 'src/domain/storage/storage.service'; import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { StorageService } from 'src/services/storage.service'; import { newStorageRepositoryMock } from 'test/repositories/storage.repository.mock'; describe(StorageService.name, () => { diff --git a/server/src/domain/storage/storage.service.ts b/server/src/services/storage.service.ts similarity index 100% rename from server/src/domain/storage/storage.service.ts rename to server/src/services/storage.service.ts diff --git a/server/src/domain/system-config/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts similarity index 99% rename from server/src/domain/system-config/system-config.service.spec.ts rename to server/src/services/system-config.service.spec.ts index f81d726eb..b5b5875d7 100644 --- a/server/src/domain/system-config/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -1,7 +1,6 @@ import { BadRequestException } from '@nestjs/common'; import { defaults } from 'src/cores/system-config.core'; import { QueueName } from 'src/domain/job/job.constants'; -import { SystemConfigService } from 'src/domain/system-config/system-config.service'; import { AudioCodec, CQMode, @@ -19,6 +18,7 @@ import { ImmichLogger } from 'src/infra/logger'; import { ICommunicationRepository, ServerEvent } from 'src/interfaces/communication.repository'; import { ISearchRepository } from 'src/interfaces/search.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { SystemConfigService } from 'src/services/system-config.service'; import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; diff --git a/server/src/domain/system-config/system-config.service.ts b/server/src/services/system-config.service.ts similarity index 100% rename from server/src/domain/system-config/system-config.service.ts rename to server/src/services/system-config.service.ts diff --git a/server/src/domain/tag/tag.service.spec.ts b/server/src/services/tag.service.spec.ts similarity index 99% rename from server/src/domain/tag/tag.service.spec.ts rename to server/src/services/tag.service.spec.ts index c7aeba9f1..0dca425c3 100644 --- a/server/src/domain/tag/tag.service.spec.ts +++ b/server/src/services/tag.service.spec.ts @@ -1,9 +1,9 @@ import { BadRequestException } from '@nestjs/common'; import { when } from 'jest-when'; -import { TagService } from 'src/domain/tag/tag.service'; import { AssetIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { TagType } from 'src/entities/tag.entity'; import { ITagRepository } from 'src/interfaces/tag.repository'; +import { TagService } from 'src/services/tag.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { tagResponseStub, tagStub } from 'test/fixtures/tag.stub'; diff --git a/server/src/domain/tag/tag.service.ts b/server/src/services/tag.service.ts similarity index 100% rename from server/src/domain/tag/tag.service.ts rename to server/src/services/tag.service.ts diff --git a/server/src/domain/trash/trash.service.spec.ts b/server/src/services/trash.service.spec.ts similarity index 98% rename from server/src/domain/trash/trash.service.spec.ts rename to server/src/services/trash.service.spec.ts index 021c8e526..09f668e6f 100644 --- a/server/src/domain/trash/trash.service.spec.ts +++ b/server/src/services/trash.service.spec.ts @@ -1,9 +1,9 @@ import { BadRequestException } from '@nestjs/common'; import { JobName } from 'src/domain/job/job.constants'; -import { TrashService } from 'src/domain/trash/trash.service'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; import { IJobRepository } from 'src/interfaces/job.repository'; +import { TrashService } from 'src/services/trash.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; diff --git a/server/src/domain/trash/trash.service.ts b/server/src/services/trash.service.ts similarity index 100% rename from server/src/domain/trash/trash.service.ts rename to server/src/services/trash.service.ts diff --git a/server/src/domain/user/user.service.spec.ts b/server/src/services/user.service.spec.ts similarity index 99% rename from server/src/domain/user/user.service.spec.ts rename to server/src/services/user.service.spec.ts index 804a892c7..51457b201 100644 --- a/server/src/domain/user/user.service.spec.ts +++ b/server/src/services/user.service.spec.ts @@ -6,7 +6,6 @@ import { } from '@nestjs/common'; import { when } from 'jest-when'; import { JobName } from 'src/domain/job/job.constants'; -import { UserService } from 'src/domain/user/user.service'; import { UpdateUserDto, mapUser } from 'src/dtos/user.dto'; import { UserEntity, UserStatus } from 'src/entities/user.entity'; import { IAlbumRepository } from 'src/interfaces/album.repository'; @@ -16,6 +15,7 @@ import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; +import { UserService } from 'src/services/user.service'; import { CacheControl, ImmichFileResponse } from 'src/utils'; import { authStub } from 'test/fixtures/auth.stub'; import { systemConfigStub } from 'test/fixtures/system-config.stub'; diff --git a/server/src/domain/user/user.service.ts b/server/src/services/user.service.ts similarity index 100% rename from server/src/domain/user/user.service.ts rename to server/src/services/user.service.ts From 28ad004b01c4f23981e784c08a23811a99d84658 Mon Sep 17 00:00:00 2001 From: Kirill <44521162+kirilldem@users.noreply.github.com> Date: Thu, 21 Mar 2024 03:58:52 +0100 Subject: [PATCH 043/152] Update remote-machine-learning.md (#8038) * Update remote-machine-learning.md provide an example to use cuda or another container * Update docs/docs/guides/remote-machine-learning.md Co-authored-by: aviv926 <51673860+aviv926@users.noreply.github.com> * Update docs/docs/guides/remote-machine-learning.md --------- Co-authored-by: Mert <101130780+mertalev@users.noreply.github.com> Co-authored-by: aviv926 <51673860+aviv926@users.noreply.github.com> --- docs/docs/guides/remote-machine-learning.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/docs/guides/remote-machine-learning.md b/docs/docs/guides/remote-machine-learning.md index b7865686c..087f9aab7 100644 --- a/docs/docs/guides/remote-machine-learning.md +++ b/docs/docs/guides/remote-machine-learning.md @@ -16,7 +16,12 @@ version: '3.8' services: immich-machine-learning: container_name: immich_machine_learning + # For hardware acceleration, add one of -[armnn, cuda, openvino] to the image tag. + # Example tag: ${IMMICH_VERSION:-release}-cuda image: ghcr.io/immich-app/immich-machine-learning:${IMMICH_VERSION:-release} + # extends: + # file: hwaccel.ml.yml + # service: # set to one of [armnn, cuda, openvino, openvino-wsl] for accelerated inference - use the `-wsl` version for WSL2 where applicable volumes: - model-cache:/cache restart: always From 9fd5d2ad9ca8ea7feda7973ee431fad1b03aa538 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 20 Mar 2024 22:59:15 -0400 Subject: [PATCH 044/152] fix(deps): update machine-learning (#8057) Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- machine-learning/export/Dockerfile | 2 +- machine-learning/poetry.lock | 42 +++++++++++++++--------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/machine-learning/export/Dockerfile b/machine-learning/export/Dockerfile index 1016b330c..b9aa8f1ed 100644 --- a/machine-learning/export/Dockerfile +++ b/machine-learning/export/Dockerfile @@ -1,4 +1,4 @@ -FROM mambaorg/micromamba:bookworm-slim@sha256:96586e238e2fed914b839e50cf91943b5655262348d141466b34ced2e0b5b155 as builder +FROM mambaorg/micromamba:bookworm-slim@sha256:881dbb68d115182b2c12e7e77dc54ea5005fd4e0123ca009d822adb5b0631785 as builder ENV NODE_ENV=production \ TRANSFORMERS_CACHE=/cache \ diff --git a/machine-learning/poetry.lock b/machine-learning/poetry.lock index 7a0c66bdc..8d53fc84e 100644 --- a/machine-learning/poetry.lock +++ b/machine-learning/poetry.lock @@ -877,13 +877,13 @@ tqdm = ["tqdm"] [[package]] name = "ftfy" -version = "6.1.3" +version = "6.2.0" description = "Fixes mojibake and other problems with Unicode, after the fact" optional = false python-versions = ">=3.8,<4" files = [ - {file = "ftfy-6.1.3-py3-none-any.whl", hash = "sha256:e49c306c06a97f4986faa7a8740cfe3c13f3106e85bcec73eb629817e671557c"}, - {file = "ftfy-6.1.3.tar.gz", hash = "sha256:693274aead811cff24c1e8784165aa755cd2f6e442a5ec535c7d697f6422a422"}, + {file = "ftfy-6.2.0-py3-none-any.whl", hash = "sha256:f94a2c34b76e07475720e3096f5ca80911d152406fbde66fdb45c4d0c9150026"}, + {file = "ftfy-6.2.0.tar.gz", hash = "sha256:5e42143c7025ef97944ca2619d6b61b0619fc6654f98771d39e862c1424c75c0"}, ] [package.dependencies] @@ -2844,28 +2844,28 @@ files = [ [[package]] name = "ruff" -version = "0.3.2" +version = "0.3.3" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.3.2-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:77f2612752e25f730da7421ca5e3147b213dca4f9a0f7e0b534e9562c5441f01"}, - {file = "ruff-0.3.2-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9966b964b2dd1107797be9ca7195002b874424d1d5472097701ae8f43eadef5d"}, - {file = "ruff-0.3.2-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b83d17ff166aa0659d1e1deaf9f2f14cbe387293a906de09bc4860717eb2e2da"}, - {file = "ruff-0.3.2-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:bb875c6cc87b3703aeda85f01c9aebdce3d217aeaca3c2e52e38077383f7268a"}, - {file = "ruff-0.3.2-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:be75e468a6a86426430373d81c041b7605137a28f7014a72d2fc749e47f572aa"}, - {file = "ruff-0.3.2-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:967978ac2d4506255e2f52afe70dda023fc602b283e97685c8447d036863a302"}, - {file = "ruff-0.3.2-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1231eacd4510f73222940727ac927bc5d07667a86b0cbe822024dd00343e77e9"}, - {file = "ruff-0.3.2-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c6d613b19e9a8021be2ee1d0e27710208d1603b56f47203d0abbde906929a9b"}, - {file = "ruff-0.3.2-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c8439338a6303585d27b66b4626cbde89bb3e50fa3cae86ce52c1db7449330a7"}, - {file = "ruff-0.3.2-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:de8b480d8379620cbb5ea466a9e53bb467d2fb07c7eca54a4aa8576483c35d36"}, - {file = "ruff-0.3.2-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:b74c3de9103bd35df2bb05d8b2899bf2dbe4efda6474ea9681280648ec4d237d"}, - {file = "ruff-0.3.2-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f380be9fc15a99765c9cf316b40b9da1f6ad2ab9639e551703e581a5e6da6745"}, - {file = "ruff-0.3.2-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0ac06a3759c3ab9ef86bbeca665d31ad3aa9a4b1c17684aadb7e61c10baa0df4"}, - {file = "ruff-0.3.2-py3-none-win32.whl", hash = "sha256:9bd640a8f7dd07a0b6901fcebccedadeb1a705a50350fb86b4003b805c81385a"}, - {file = "ruff-0.3.2-py3-none-win_amd64.whl", hash = "sha256:0c1bdd9920cab5707c26c8b3bf33a064a4ca7842d91a99ec0634fec68f9f4037"}, - {file = "ruff-0.3.2-py3-none-win_arm64.whl", hash = "sha256:5f65103b1d76e0d600cabd577b04179ff592064eaa451a70a81085930e907d0b"}, - {file = "ruff-0.3.2.tar.gz", hash = "sha256:fa78ec9418eb1ca3db392811df3376b46471ae93792a81af2d1cbb0e5dcb5142"}, + {file = "ruff-0.3.3-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:973a0e388b7bc2e9148c7f9be8b8c6ae7471b9be37e1cc732f8f44a6f6d7720d"}, + {file = "ruff-0.3.3-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:cfa60d23269d6e2031129b053fdb4e5a7b0637fc6c9c0586737b962b2f834493"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1eca7ff7a47043cf6ce5c7f45f603b09121a7cc047447744b029d1b719278eb5"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e7d3f6762217c1da954de24b4a1a70515630d29f71e268ec5000afe81377642d"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b24c19e8598916d9c6f5a5437671f55ee93c212a2c4c569605dc3842b6820386"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5a6cbf216b69c7090f0fe4669501a27326c34e119068c1494f35aaf4cc683778"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:352e95ead6964974b234e16ba8a66dad102ec7bf8ac064a23f95371d8b198aab"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8d6ab88c81c4040a817aa432484e838aaddf8bfd7ca70e4e615482757acb64f8"}, + {file = "ruff-0.3.3-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79bca3a03a759cc773fca69e0bdeac8abd1c13c31b798d5bb3c9da4a03144a9f"}, + {file = "ruff-0.3.3-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:2700a804d5336bcffe063fd789ca2c7b02b552d2e323a336700abb8ae9e6a3f8"}, + {file = "ruff-0.3.3-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:fd66469f1a18fdb9d32e22b79f486223052ddf057dc56dea0caaf1a47bdfaf4e"}, + {file = "ruff-0.3.3-py3-none-musllinux_1_2_i686.whl", hash = "sha256:45817af234605525cdf6317005923bf532514e1ea3d9270acf61ca2440691376"}, + {file = "ruff-0.3.3-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:0da458989ce0159555ef224d5b7c24d3d2e4bf4c300b85467b08c3261c6bc6a8"}, + {file = "ruff-0.3.3-py3-none-win32.whl", hash = "sha256:f2831ec6a580a97f1ea82ea1eda0401c3cdf512cf2045fa3c85e8ef109e87de0"}, + {file = "ruff-0.3.3-py3-none-win_amd64.whl", hash = "sha256:be90bcae57c24d9f9d023b12d627e958eb55f595428bafcb7fec0791ad25ddfc"}, + {file = "ruff-0.3.3-py3-none-win_arm64.whl", hash = "sha256:0171aab5fecdc54383993389710a3d1227f2da124d76a2784a7098e818f92d61"}, + {file = "ruff-0.3.3.tar.gz", hash = "sha256:38671be06f57a2f8aba957d9f701ea889aa5736be806f18c0cd03d6ff0cbca8d"}, ] [[package]] From 16d0df796c3dec465096db83d409aef85c1185bd Mon Sep 17 00:00:00 2001 From: Jason Rasmussen Date: Wed, 20 Mar 2024 22:15:09 -0500 Subject: [PATCH 045/152] refactor: infra folder (#8138) --- .github/workflows/test.yml | 2 +- docs/docs/developer/database-migrations.md | 2 +- server/package.json | 23 +-- server/src/apps/api.main.ts | 8 +- server/src/apps/api.service.ts | 6 +- server/src/apps/app.module.ts | 6 +- server/src/apps/microservices.main.ts | 8 +- server/src/apps/microservices.service.ts | 5 +- server/src/config.ts | 2 +- server/src/constants.ts | 105 ++++++++++ server/src/controllers/auth.controller.ts | 2 +- .../src/controllers/shared-link.controller.ts | 2 +- server/src/cores/access.core.ts | 2 +- server/src/cores/storage.core.ts | 4 +- server/src/cores/system-config.core.ts | 4 +- server/src/{infra => }/database.config.ts | 6 +- server/src/decorators.ts | 2 +- server/src/domain/auth/auth.constant.ts | 12 -- server/src/domain/job/job.constants.ts | 155 --------------- server/src/domain/job/job.interface.ts | 41 ---- server/src/domain/media/media.constant.ts | 1 - .../domain/smart-info/smart-info.constant.ts | 129 ------------- .../system-config/system-config.constants.ts | 27 --- server/src/dtos/job.dto.ts | 2 +- server/src/dtos/server-info.dto.ts | 2 +- server/src/dtos/system-config-job.dto.ts | 2 +- server/src/entities/system-config.entity.ts | 2 +- .../immich/api-v1/asset/asset-repository.ts | 2 +- .../immich/api-v1/asset/asset.service.spec.ts | 3 +- .../src/immich/api-v1/asset/asset.service.ts | 9 +- server/src/immich/app.utils.ts | 8 +- server/src/infra/sql-generator/sql.logger.ts | 25 --- server/src/interfaces/asset.repository.ts | 2 +- server/src/interfaces/database.repository.ts | 2 +- server/src/interfaces/job.repository.ts | 147 ++++++++++++-- server/src/interfaces/person.repository.ts | 2 +- server/src/interfaces/search.repository.ts | 2 +- server/src/middleware/auth.guard.ts | 4 +- server/src/middleware/error.interceptor.ts | 4 +- .../src/middleware/file-upload.interceptor.ts | 2 +- .../websocket.adapter.ts | 0 .../migrations/1700713871511-UsePgVectors.ts | 4 +- .../1700713994428-AddCLIPEmbeddingIndex.ts | 2 +- .../1700714033632-AddFaceEmbeddingIndex.ts | 2 +- .../sql => queries}/access.repository.sql | 0 .../sql => queries}/album.repository.sql | 0 .../sql => queries}/api.key.repository.sql | 0 .../sql => queries}/asset.repository.sql | 0 .../sql => queries}/audit.repository.sql | 0 .../sql => queries}/library.repository.sql | 0 .../sql => queries}/move.repository.sql | 0 .../sql => queries}/partner.repository.sql | 0 .../sql => queries}/person.repository.sql | 0 .../sql => queries}/search.repository.sql | 0 .../shared.link.repository.sql | 0 .../system.config.repository.sql | 0 .../system.metadata.repository.sql | 0 .../{infra/sql => queries}/tag.repository.sql | 0 .../sql => queries}/user.repository.sql | 0 .../sql => queries}/user.token.repository.sql | 0 server/src/repositories/access.repository.ts | 2 +- .../src/repositories/activity.repository.ts | 2 +- server/src/repositories/album.repository.ts | 6 +- server/src/repositories/api-key.repository.ts | 2 +- .../repositories/asset-stack.repository.ts | 2 +- server/src/repositories/asset.repository.ts | 6 +- server/src/repositories/audit.repository.ts | 2 +- .../repositories/communication.repository.ts | 4 +- server/src/repositories/crypto.repository.ts | 2 +- .../src/repositories/database.repository.ts | 8 +- .../src/repositories/filesystem.provider.ts | 6 +- server/src/repositories/job.repository.ts | 76 +++++++- server/src/repositories/library.repository.ts | 2 +- .../machine-learning.repository.ts | 2 +- server/src/repositories/media.repository.ts | 6 +- .../src/repositories/metadata.repository.ts | 12 +- server/src/repositories/move.repository.ts | 2 +- server/src/repositories/partner.repository.ts | 2 +- server/src/repositories/person.repository.ts | 6 +- server/src/repositories/search.repository.ts | 12 +- .../repositories/server-info.repository.ts | 2 +- .../repositories/shared-link.repository.ts | 2 +- .../repositories/system-config.repository.ts | 2 +- .../system-metadata.repository.ts | 2 +- server/src/repositories/tag.repository.ts | 2 +- .../src/repositories/user-token.repository.ts | 2 +- server/src/repositories/user.repository.ts | 2 +- server/src/services/album.service.ts | 2 +- server/src/services/asset.service.spec.ts | 3 +- server/src/services/asset.service.ts | 18 +- server/src/services/audit.service.ts | 9 +- server/src/services/auth.service.spec.ts | 2 +- server/src/services/auth.service.ts | 12 +- server/src/services/database.service.spec.ts | 4 +- server/src/services/database.service.ts | 4 +- server/src/services/download.service.spec.ts | 2 +- server/src/services/download.service.ts | 6 +- server/src/services/job.service.spec.ts | 11 +- server/src/services/job.service.ts | 15 +- server/src/services/library.service.spec.ts | 4 +- server/src/services/library.service.ts | 20 +- server/src/services/media.service.spec.ts | 3 +- server/src/services/media.service.ts | 37 ++-- server/src/services/metadata.service.spec.ts | 3 +- server/src/services/metadata.service.ts | 18 +- server/src/services/person.service.spec.ts | 5 +- server/src/services/person.service.ts | 23 ++- .../src/services/server-info.service.spec.ts | 2 +- server/src/services/server-info.service.ts | 8 +- server/src/services/shared-link.service.ts | 2 +- .../src/services/smart-info.service.spec.ts | 17 +- server/src/services/smart-info.service.ts | 16 +- .../src/services/storage-template.service.ts | 15 +- server/src/services/storage.service.ts | 5 +- .../services/system-config.service.spec.ts | 4 +- server/src/services/system-config.service.ts | 6 +- server/src/services/trash.service.spec.ts | 3 +- server/src/services/trash.service.ts | 5 +- server/src/services/user.service.spec.ts | 5 +- server/src/services/user.service.ts | 8 +- server/src/utils.spec.ts | 103 ---------- server/src/utils.ts | 181 ------------------ server/src/utils/bytes.ts | 24 +++ .../infra.utils.ts => utils/database.ts} | 54 +----- server/src/utils/file.ts | 25 +++ .../src/{infra => utils}/instrumentation.ts | 2 +- server/src/{infra => utils}/logger.ts | 0 .../media/media.util.ts => utils/media.ts} | 0 .../mime-types.spec.ts} | 73 +------ .../mime-types.ts} | 93 +-------- server/src/utils/misc.ts | 32 ++++ server/src/utils/pagination.ts | 79 ++++++++ server/src/utils/set.ts | 36 ++++ .../sql-generator/index.ts => utils/sql.ts} | 30 ++- server/src/utils/version.spec.ts | 72 +++++++ server/src/utils/version.ts | 64 +++++++ server/test/fixtures/library.stub.ts | 2 +- .../repositories/database.repository.mock.ts | 2 +- server/test/utils.ts | 5 +- 139 files changed, 968 insertions(+), 1164 deletions(-) create mode 100644 server/src/constants.ts rename server/src/{infra => }/database.config.ts (86%) delete mode 100644 server/src/domain/auth/auth.constant.ts delete mode 100644 server/src/domain/job/job.constants.ts delete mode 100644 server/src/domain/job/job.interface.ts delete mode 100644 server/src/domain/media/media.constant.ts delete mode 100644 server/src/domain/smart-info/smart-info.constant.ts delete mode 100644 server/src/domain/system-config/system-config.constants.ts delete mode 100644 server/src/infra/sql-generator/sql.logger.ts rename server/src/{infra => middleware}/websocket.adapter.ts (100%) rename server/src/{infra/sql => queries}/access.repository.sql (100%) rename server/src/{infra/sql => queries}/album.repository.sql (100%) rename server/src/{infra/sql => queries}/api.key.repository.sql (100%) rename server/src/{infra/sql => queries}/asset.repository.sql (100%) rename server/src/{infra/sql => queries}/audit.repository.sql (100%) rename server/src/{infra/sql => queries}/library.repository.sql (100%) rename server/src/{infra/sql => queries}/move.repository.sql (100%) rename server/src/{infra/sql => queries}/partner.repository.sql (100%) rename server/src/{infra/sql => queries}/person.repository.sql (100%) rename server/src/{infra/sql => queries}/search.repository.sql (100%) rename server/src/{infra/sql => queries}/shared.link.repository.sql (100%) rename server/src/{infra/sql => queries}/system.config.repository.sql (100%) rename server/src/{infra/sql => queries}/system.metadata.repository.sql (100%) rename server/src/{infra/sql => queries}/tag.repository.sql (100%) rename server/src/{infra/sql => queries}/user.repository.sql (100%) rename server/src/{infra/sql => queries}/user.token.repository.sql (100%) delete mode 100644 server/src/utils.spec.ts delete mode 100644 server/src/utils.ts create mode 100644 server/src/utils/bytes.ts rename server/src/{infra/infra.utils.ts => utils/database.ts} (75%) create mode 100644 server/src/utils/file.ts rename server/src/{infra => utils}/instrumentation.ts (98%) rename server/src/{infra => utils}/logger.ts (100%) rename server/src/{domain/media/media.util.ts => utils/media.ts} (100%) rename server/src/{domain/domain.constant.spec.ts => utils/mime-types.spec.ts} (68%) rename server/src/{domain/domain.constant.ts => utils/mime-types.ts} (56%) create mode 100644 server/src/utils/misc.ts create mode 100644 server/src/utils/pagination.ts create mode 100644 server/src/utils/set.ts rename server/src/{infra/sql-generator/index.ts => utils/sql.ts} (90%) create mode 100644 server/src/utils/version.spec.ts create mode 100644 server/src/utils/version.ts diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 13f5a73a1..6a5df111d 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -354,7 +354,7 @@ jobs: id: verify-changed-sql-files with: files: | - server/src/infra/sql + server/src/queries - name: Verify SQL files have not changed if: steps.verify-changed-sql-files.outputs.files_changed == 'true' diff --git a/docs/docs/developer/database-migrations.md b/docs/docs/developer/database-migrations.md index eccf78b44..2cddf5f38 100644 --- a/docs/docs/developer/database-migrations.md +++ b/docs/docs/developer/database-migrations.md @@ -5,7 +5,7 @@ After making any changes in the `server/src/entities`, a database migration need 1. Run the command ```bash -npm run typeorm:migrations:generate ./src/infra/ +npm run typeorm:migrations:generate ``` 2. Check if the migration file makes sense. diff --git a/server/package.json b/server/package.json index eb65eadf0..4776e418f 100644 --- a/server/package.json +++ b/server/package.json @@ -25,12 +25,12 @@ "e2e:jobs": "jest --config e2e/jobs/jest-e2e.json --runInBand", "typeorm": "typeorm", "typeorm:migrations:create": "typeorm migration:create", - "typeorm:migrations:generate": "typeorm migration:generate -d ./dist/infra/database.config.js", - "typeorm:migrations:run": "typeorm migration:run -d ./dist/infra/database.config.js", - "typeorm:migrations:revert": "typeorm migration:revert -d ./dist/infra/database.config.js", - "typeorm:schema:drop": "typeorm query -d ./dist/infra/database.config.js 'DROP schema public cascade; CREATE schema public;'", + "typeorm:migrations:generate": "typeorm migration:generate -d ./dist/database.config.js", + "typeorm:migrations:run": "typeorm migration:run -d ./dist/database.config.js", + "typeorm:migrations:revert": "typeorm migration:revert -d ./dist/database.config.js", + "typeorm:schema:drop": "typeorm query -d ./dist/database.config.js 'DROP schema public cascade; CREATE schema public;'", "typeorm:schema:reset": "npm run typeorm:schema:drop && npm run typeorm:migrations:run", - "sql:generate": "node ./dist/infra/sql-generator/" + "sql:generate": "node ./dist/utils/sql.js" }, "dependencies": { "@babel/runtime": "^7.22.11", @@ -146,15 +146,16 @@ "^.+\\.ts$": "ts-jest" }, "collectCoverageFrom": [ - "/src/**/*.(t|j)s", - "!/src/infra/**/*", - "!/src/migrations/**/*", - "!/src/subscribers/**/*", - "!/src/immich/controllers/**/*" + "/src/cores/*.(t|j)s", + "/src/dtos/*.(t|j)s", + "/src/interfaces/*.(t|j)s", + "/src/services/*.(t|j)s", + "/src/utils/*.(t|j)s", + "/src/*.t|j)s" ], "coverageDirectory": "./coverage", "coverageThreshold": { - "./src/domain/": { + "./src/": { "branches": 75, "functions": 80, "lines": 85, diff --git a/server/src/apps/api.main.ts b/server/src/apps/api.main.ts index 9ffdd1d48..07685308e 100644 --- a/server/src/apps/api.main.ts +++ b/server/src/apps/api.main.ts @@ -7,11 +7,11 @@ import sirv from 'sirv'; import { ApiModule } from 'src/apps/api.module'; import { ApiService } from 'src/apps/api.service'; import { excludePaths } from 'src/config'; -import { WEB_ROOT, envName, isDev, serverVersion } from 'src/domain/domain.constant'; +import { WEB_ROOT, envName, isDev, serverVersion } from 'src/constants'; import { useSwagger } from 'src/immich/app.utils'; -import { otelSDK } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; -import { WebSocketAdapter } from 'src/infra/websocket.adapter'; +import { WebSocketAdapter } from 'src/middleware/websocket.adapter'; +import { otelSDK } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; const logger = new ImmichLogger('ImmichServer'); const port = Number(process.env.SERVER_PORT) || 3001; diff --git a/server/src/apps/api.service.ts b/server/src/apps/api.service.ts index fbd0d0e4a..87107b23f 100644 --- a/server/src/apps/api.service.ts +++ b/server/src/apps/api.service.ts @@ -3,8 +3,7 @@ import { Cron, CronExpression, Interval } from '@nestjs/schedule'; import { NextFunction, Request, Response } from 'express'; import { readFileSync } from 'node:fs'; import { join } from 'node:path'; -import { ONE_HOUR, WEB_ROOT } from 'src/domain/domain.constant'; -import { ImmichLogger } from 'src/infra/logger'; +import { ONE_HOUR, WEB_ROOT } from 'src/constants'; import { AuthService } from 'src/services/auth.service'; import { DatabaseService } from 'src/services/database.service'; import { JobService } from 'src/services/job.service'; @@ -12,7 +11,8 @@ import { ServerInfoService } from 'src/services/server-info.service'; import { SharedLinkService } from 'src/services/shared-link.service'; import { StorageService } from 'src/services/storage.service'; import { SystemConfigService } from 'src/services/system-config.service'; -import { OpenGraphTags } from 'src/utils'; +import { ImmichLogger } from 'src/utils/logger'; +import { OpenGraphTags } from 'src/utils/misc'; const render = (index: string, meta: OpenGraphTags) => { const tags = ` diff --git a/server/src/apps/app.module.ts b/server/src/apps/app.module.ts index 964e2d4e1..14aae51d9 100644 --- a/server/src/apps/app.module.ts +++ b/server/src/apps/app.module.ts @@ -6,10 +6,8 @@ import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule'; import { TypeOrmModule } from '@nestjs/typeorm'; import { OpenTelemetryModule } from 'nestjs-otel'; import { bullConfig, bullQueues, immichAppConfig } from 'src/config'; +import { databaseConfig } from 'src/database.config'; import { databaseEntities } from 'src/entities'; -import { databaseConfig } from 'src/infra/database.config'; -import { otelConfig } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IActivityRepository } from 'src/interfaces/activity.repository'; import { IAlbumRepository } from 'src/interfaces/album.repository'; @@ -88,6 +86,8 @@ import { SystemConfigService } from 'src/services/system-config.service'; import { TagService } from 'src/services/tag.service'; import { TrashService } from 'src/services/trash.service'; import { UserService } from 'src/services/user.service'; +import { otelConfig } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; const services: Provider[] = [ APIKeyService, diff --git a/server/src/apps/microservices.main.ts b/server/src/apps/microservices.main.ts index 552fb714c..d35483d72 100644 --- a/server/src/apps/microservices.main.ts +++ b/server/src/apps/microservices.main.ts @@ -1,9 +1,9 @@ import { NestFactory } from '@nestjs/core'; import { MicroservicesModule } from 'src/apps/microservices.module'; -import { envName, serverVersion } from 'src/domain/domain.constant'; -import { otelSDK } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; -import { WebSocketAdapter } from 'src/infra/websocket.adapter'; +import { envName, serverVersion } from 'src/constants'; +import { WebSocketAdapter } from 'src/middleware/websocket.adapter'; +import { otelSDK } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; const logger = new ImmichLogger('ImmichMicroservice'); const port = Number(process.env.MICROSERVICES_PORT) || 3002; diff --git a/server/src/apps/microservices.service.ts b/server/src/apps/microservices.service.ts index 8f11583be..a6b7f3869 100644 --- a/server/src/apps/microservices.service.ts +++ b/server/src/apps/microservices.service.ts @@ -1,7 +1,5 @@ import { Injectable } from '@nestjs/common'; -import { JobName } from 'src/domain/job/job.constants'; -import { IDeleteFilesJob } from 'src/domain/job/job.interface'; -import { otelSDK } from 'src/infra/instrumentation'; +import { IDeleteFilesJob, JobName } from 'src/interfaces/job.repository'; import { AssetService } from 'src/services/asset.service'; import { AuditService } from 'src/services/audit.service'; import { DatabaseService } from 'src/services/database.service'; @@ -15,6 +13,7 @@ import { StorageTemplateService } from 'src/services/storage-template.service'; import { StorageService } from 'src/services/storage.service'; import { SystemConfigService } from 'src/services/system-config.service'; import { UserService } from 'src/services/user.service'; +import { otelSDK } from 'src/utils/instrumentation'; @Injectable() export class MicroservicesService { diff --git a/server/src/config.ts b/server/src/config.ts index b97f0bb7e..f19546093 100644 --- a/server/src/config.ts +++ b/server/src/config.ts @@ -3,8 +3,8 @@ import { ConfigModuleOptions } from '@nestjs/config'; import { QueueOptions } from 'bullmq'; import { RedisOptions } from 'ioredis'; import Joi from 'joi'; -import { QueueName } from 'src/domain/job/job.constants'; import { LogLevel } from 'src/entities/system-config.entity'; +import { QueueName } from 'src/interfaces/job.repository'; const WHEN_DB_URL_SET = Joi.when('DB_URL', { is: Joi.exist(), diff --git a/server/src/constants.ts b/server/src/constants.ts new file mode 100644 index 000000000..eaacf12d9 --- /dev/null +++ b/server/src/constants.ts @@ -0,0 +1,105 @@ +import { Duration } from 'luxon'; +import { readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { Version } from 'src/utils/version'; + +const { version } = JSON.parse(readFileSync('./package.json', 'utf8')); +export const serverVersion = Version.fromString(version); + +export const AUDIT_LOG_MAX_DURATION = Duration.fromObject({ days: 100 }); +export const ONE_HOUR = Duration.fromObject({ hours: 1 }); + +export const envName = (process.env.NODE_ENV || 'development').toUpperCase(); +export const isDev = process.env.NODE_ENV === 'development'; +export const APP_MEDIA_LOCATION = process.env.IMMICH_MEDIA_LOCATION || './upload'; +export const WEB_ROOT = process.env.IMMICH_WEB_ROOT || '/usr/src/app/www'; + +const GEODATA_ROOT_PATH = process.env.IMMICH_REVERSE_GEOCODING_ROOT || '/usr/src/resources'; + +export const citiesFile = 'cities500.txt'; +export const geodataDatePath = join(GEODATA_ROOT_PATH, 'geodata-date.txt'); +export const geodataAdmin1Path = join(GEODATA_ROOT_PATH, 'admin1CodesASCII.txt'); +export const geodataAdmin2Path = join(GEODATA_ROOT_PATH, 'admin2Codes.txt'); +export const geodataCities500Path = join(GEODATA_ROOT_PATH, citiesFile); + +export const MOBILE_REDIRECT = 'app.immich:/'; +export const LOGIN_URL = '/auth/login?autoLaunch=0'; +export const IMMICH_ACCESS_COOKIE = 'immich_access_token'; +export const IMMICH_IS_AUTHENTICATED = 'immich_is_authenticated'; +export const IMMICH_AUTH_TYPE_COOKIE = 'immich_auth_type'; +export const IMMICH_API_KEY_NAME = 'api_key'; +export const IMMICH_API_KEY_HEADER = 'x-api-key'; +export const IMMICH_SHARED_LINK_ACCESS_COOKIE = 'immich_shared_link_token'; +export enum AuthType { + PASSWORD = 'password', + OAUTH = 'oauth', +} + +export const FACE_THUMBNAIL_SIZE = 250; + +export const supportedYearTokens = ['y', 'yy']; +export const supportedMonthTokens = ['M', 'MM', 'MMM', 'MMMM']; +export const supportedWeekTokens = ['W', 'WW']; +export const supportedDayTokens = ['d', 'dd']; +export const supportedHourTokens = ['h', 'hh', 'H', 'HH']; +export const supportedMinuteTokens = ['m', 'mm']; +export const supportedSecondTokens = ['s', 'ss', 'SSS']; +export const supportedPresetTokens = [ + '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}', + '{{y}}/{{MM}}-{{dd}}/{{filename}}', + '{{y}}/{{MMMM}}-{{dd}}/{{filename}}', + '{{y}}/{{MM}}/{{filename}}', + '{{y}}/{{MMM}}/{{filename}}', + '{{y}}/{{MMMM}}/{{filename}}', + '{{y}}/{{MM}}/{{dd}}/{{filename}}', + '{{y}}/{{MMMM}}/{{dd}}/{{filename}}', + '{{y}}/{{y}}-{{MM}}/{{y}}-{{MM}}-{{dd}}/{{filename}}', + '{{y}}-{{MM}}-{{dd}}/{{filename}}', + '{{y}}-{{MMM}}-{{dd}}/{{filename}}', + '{{y}}-{{MMMM}}-{{dd}}/{{filename}}', + '{{y}}/{{y}}-{{MM}}/{{filename}}', + '{{y}}/{{y}}-{{WW}}/{{filename}}', + '{{y}}/{{y}}-{{MM}}-{{dd}}/{{assetId}}', + '{{y}}/{{y}}-{{MM}}/{{assetId}}', + '{{y}}/{{y}}-{{WW}}/{{assetId}}', + '{{album}}/{{filename}}', +]; + +type ModelInfo = { dimSize: number }; +export const CLIP_MODEL_INFO: Record = { + RN50__openai: { dimSize: 1024 }, + RN50__yfcc15m: { dimSize: 1024 }, + RN50__cc12m: { dimSize: 1024 }, + RN101__openai: { dimSize: 512 }, + RN101__yfcc15m: { dimSize: 512 }, + RN50x4__openai: { dimSize: 640 }, + RN50x16__openai: { dimSize: 768 }, + RN50x64__openai: { dimSize: 1024 }, + 'ViT-B-32__openai': { dimSize: 512 }, + 'ViT-B-32__laion2b_e16': { dimSize: 512 }, + 'ViT-B-32__laion400m_e31': { dimSize: 512 }, + 'ViT-B-32__laion400m_e32': { dimSize: 512 }, + 'ViT-B-32__laion2b-s34b-b79k': { dimSize: 512 }, + 'ViT-B-16__openai': { dimSize: 512 }, + 'ViT-B-16__laion400m_e31': { dimSize: 512 }, + 'ViT-B-16__laion400m_e32': { dimSize: 512 }, + 'ViT-B-16-plus-240__laion400m_e31': { dimSize: 640 }, + 'ViT-B-16-plus-240__laion400m_e32': { dimSize: 640 }, + 'ViT-L-14__openai': { dimSize: 768 }, + 'ViT-L-14__laion400m_e31': { dimSize: 768 }, + 'ViT-L-14__laion400m_e32': { dimSize: 768 }, + 'ViT-L-14__laion2b-s32b-b82k': { dimSize: 768 }, + 'ViT-L-14-336__openai': { dimSize: 768 }, + 'ViT-L-14-quickgelu__dfn2b': { dimSize: 768 }, + 'ViT-H-14__laion2b-s32b-b79k': { dimSize: 1024 }, + 'ViT-H-14-quickgelu__dfn5b': { dimSize: 1024 }, + 'ViT-H-14-378-quickgelu__dfn5b': { dimSize: 1024 }, + 'ViT-g-14__laion2b-s12b-b42k': { dimSize: 1024 }, + 'LABSE-Vit-L-14': { dimSize: 768 }, + 'XLM-Roberta-Large-Vit-B-32': { dimSize: 512 }, + 'XLM-Roberta-Large-Vit-B-16Plus': { dimSize: 640 }, + 'XLM-Roberta-Large-Vit-L-14': { dimSize: 768 }, + 'XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k': { dimSize: 1024 }, + 'nllb-clip-base-siglip__v1': { dimSize: 768 }, + 'nllb-clip-large-siglip__v1': { dimSize: 1152 }, +}; diff --git a/server/src/controllers/auth.controller.ts b/server/src/controllers/auth.controller.ts index cbb649dc0..9b4e7a3bc 100644 --- a/server/src/controllers/auth.controller.ts +++ b/server/src/controllers/auth.controller.ts @@ -1,7 +1,7 @@ import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Req, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; -import { IMMICH_ACCESS_COOKIE, IMMICH_AUTH_TYPE_COOKIE, IMMICH_IS_AUTHENTICATED } from 'src/domain/auth/auth.constant'; +import { IMMICH_ACCESS_COOKIE, IMMICH_AUTH_TYPE_COOKIE, IMMICH_IS_AUTHENTICATED } from 'src/constants'; import { AuthDeviceResponseDto, AuthDto, diff --git a/server/src/controllers/shared-link.controller.ts b/server/src/controllers/shared-link.controller.ts index 61dd6605a..990f4e322 100644 --- a/server/src/controllers/shared-link.controller.ts +++ b/server/src/controllers/shared-link.controller.ts @@ -1,7 +1,7 @@ import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query, Req, Res } from '@nestjs/common'; import { ApiTags } from '@nestjs/swagger'; import { Request, Response } from 'express'; -import { IMMICH_SHARED_LINK_ACCESS_COOKIE } from 'src/domain/auth/auth.constant'; +import { IMMICH_SHARED_LINK_ACCESS_COOKIE } from 'src/constants'; import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto'; import { AssetIdsDto } from 'src/dtos/asset.dto'; import { AuthDto } from 'src/dtos/auth.dto'; diff --git a/server/src/cores/access.core.ts b/server/src/cores/access.core.ts index 1c0b1dabb..78b30e4b1 100644 --- a/server/src/cores/access.core.ts +++ b/server/src/cores/access.core.ts @@ -2,7 +2,7 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { AuthDto } from 'src/dtos/auth.dto'; import { SharedLinkEntity } from 'src/entities/shared-link.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; -import { setDifference, setIsEqual, setUnion } from 'src/utils'; +import { setDifference, setIsEqual, setUnion } from 'src/utils/set'; export enum Permission { ACTIVITY_CREATE = 'activity.create', diff --git a/server/src/cores/storage.core.ts b/server/src/cores/storage.core.ts index 8bf65b248..17f3f0360 100644 --- a/server/src/cores/storage.core.ts +++ b/server/src/cores/storage.core.ts @@ -1,16 +1,16 @@ import { dirname, join, resolve } from 'node:path'; +import { APP_MEDIA_LOCATION } from 'src/constants'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; import { AssetEntity } from 'src/entities/asset.entity'; import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity'; import { PersonEntity } from 'src/entities/person.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { IMoveRepository } from 'src/interfaces/move.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { ImmichLogger } from 'src/utils/logger'; export enum StorageFolder { ENCODED_VIDEO = 'encoded-video', diff --git a/server/src/cores/system-config.core.ts b/server/src/cores/system-config.core.ts index a6692fa18..6554839a5 100644 --- a/server/src/cores/system-config.core.ts +++ b/server/src/cores/system-config.core.ts @@ -5,7 +5,6 @@ import { validate } from 'class-validator'; import { load as loadYaml } from 'js-yaml'; import * as _ from 'lodash'; import { Subject } from 'rxjs'; -import { QueueName } from 'src/domain/job/job.constants'; import { SystemConfigDto } from 'src/dtos/system-config.dto'; import { AudioCodec, @@ -21,8 +20,9 @@ import { TranscodePolicy, VideoCodec, } from 'src/entities/system-config.entity'; -import { ImmichLogger } from 'src/infra/logger'; +import { QueueName } from 'src/interfaces/job.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { ImmichLogger } from 'src/utils/logger'; export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConfig) => void | Promise; diff --git a/server/src/infra/database.config.ts b/server/src/database.config.ts similarity index 86% rename from server/src/infra/database.config.ts rename to server/src/database.config.ts index 572288c59..e4e251ffc 100644 --- a/server/src/infra/database.config.ts +++ b/server/src/database.config.ts @@ -16,9 +16,9 @@ const urlOrParts = url /* eslint unicorn/prefer-module: "off" -- We can fix this when migrating to ESM*/ export const databaseConfig: PostgresConnectionOptions = { type: 'postgres', - entities: [__dirname + '/../entities/*.entity.{js,ts}'], - migrations: [__dirname + '/../migrations/*.{js,ts}'], - subscribers: [__dirname + '/../subscribers/*.{js,ts}'], + entities: [__dirname + '/entities/*.entity.{js,ts}'], + migrations: [__dirname + '/migrations/*.{js,ts}'], + subscribers: [__dirname + '/subscribers/*.{js,ts}'], migrationsRun: false, synchronize: false, connectTimeoutMS: 10_000, // 10 seconds diff --git a/server/src/decorators.ts b/server/src/decorators.ts index 06dc0bfdc..33efdafa3 100644 --- a/server/src/decorators.ts +++ b/server/src/decorators.ts @@ -1,6 +1,6 @@ import { SetMetadata } from '@nestjs/common'; import _ from 'lodash'; -import { setUnion } from 'src/utils'; +import { setUnion } from 'src/utils/set'; // PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the // maximum number of parameters is 65535. Any query that tries to bind more than that (e.g. searching diff --git a/server/src/domain/auth/auth.constant.ts b/server/src/domain/auth/auth.constant.ts deleted file mode 100644 index f29fc9274..000000000 --- a/server/src/domain/auth/auth.constant.ts +++ /dev/null @@ -1,12 +0,0 @@ -export const MOBILE_REDIRECT = 'app.immich:/'; -export const LOGIN_URL = '/auth/login?autoLaunch=0'; -export const IMMICH_ACCESS_COOKIE = 'immich_access_token'; -export const IMMICH_IS_AUTHENTICATED = 'immich_is_authenticated'; -export const IMMICH_AUTH_TYPE_COOKIE = 'immich_auth_type'; -export const IMMICH_API_KEY_NAME = 'api_key'; -export const IMMICH_API_KEY_HEADER = 'x-api-key'; -export const IMMICH_SHARED_LINK_ACCESS_COOKIE = 'immich_shared_link_token'; -export enum AuthType { - PASSWORD = 'password', - OAUTH = 'oauth', -} diff --git a/server/src/domain/job/job.constants.ts b/server/src/domain/job/job.constants.ts deleted file mode 100644 index fe3c81727..000000000 --- a/server/src/domain/job/job.constants.ts +++ /dev/null @@ -1,155 +0,0 @@ -export enum QueueName { - THUMBNAIL_GENERATION = 'thumbnailGeneration', - METADATA_EXTRACTION = 'metadataExtraction', - VIDEO_CONVERSION = 'videoConversion', - FACE_DETECTION = 'faceDetection', - FACIAL_RECOGNITION = 'facialRecognition', - SMART_SEARCH = 'smartSearch', - BACKGROUND_TASK = 'backgroundTask', - STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration', - MIGRATION = 'migration', - SEARCH = 'search', - SIDECAR = 'sidecar', - LIBRARY = 'library', -} - -export type ConcurrentQueueName = Exclude< - QueueName, - QueueName.STORAGE_TEMPLATE_MIGRATION | QueueName.FACIAL_RECOGNITION ->; - -export enum JobCommand { - START = 'start', - PAUSE = 'pause', - RESUME = 'resume', - EMPTY = 'empty', - CLEAR_FAILED = 'clear-failed', -} - -export enum JobName { - // conversion - QUEUE_VIDEO_CONVERSION = 'queue-video-conversion', - VIDEO_CONVERSION = 'video-conversion', - - // thumbnails - QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails', - GENERATE_JPEG_THUMBNAIL = 'generate-jpeg-thumbnail', - GENERATE_WEBP_THUMBNAIL = 'generate-webp-thumbnail', - GENERATE_THUMBHASH_THUMBNAIL = 'generate-thumbhash-thumbnail', - GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail', - - // metadata - QUEUE_METADATA_EXTRACTION = 'queue-metadata-extraction', - METADATA_EXTRACTION = 'metadata-extraction', - LINK_LIVE_PHOTOS = 'link-live-photos', - - // user - USER_DELETION = 'user-deletion', - USER_DELETE_CHECK = 'user-delete-check', - USER_SYNC_USAGE = 'user-sync-usage', - - // asset - ASSET_DELETION = 'asset-deletion', - ASSET_DELETION_CHECK = 'asset-deletion-check', - - // storage template - STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration', - STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single', - - // migration - QUEUE_MIGRATION = 'queue-migration', - MIGRATE_ASSET = 'migrate-asset', - MIGRATE_PERSON = 'migrate-person', - - // facial recognition - PERSON_CLEANUP = 'person-cleanup', - QUEUE_FACE_DETECTION = 'queue-face-detection', - FACE_DETECTION = 'face-detection', - QUEUE_FACIAL_RECOGNITION = 'queue-facial-recognition', - FACIAL_RECOGNITION = 'facial-recognition', - - // library managment - LIBRARY_SCAN = 'library-refresh', - LIBRARY_SCAN_ASSET = 'library-refresh-asset', - LIBRARY_REMOVE_OFFLINE = 'library-remove-offline', - LIBRARY_DELETE = 'library-delete', - LIBRARY_QUEUE_SCAN_ALL = 'library-queue-all-refresh', - LIBRARY_QUEUE_CLEANUP = 'library-queue-cleanup', - - // cleanup - DELETE_FILES = 'delete-files', - CLEAN_OLD_AUDIT_LOGS = 'clean-old-audit-logs', - - // smart search - QUEUE_SMART_SEARCH = 'queue-smart-search', - SMART_SEARCH = 'smart-search', - - // XMP sidecars - QUEUE_SIDECAR = 'queue-sidecar', - SIDECAR_DISCOVERY = 'sidecar-discovery', - SIDECAR_SYNC = 'sidecar-sync', - SIDECAR_WRITE = 'sidecar-write', -} - -export const JOBS_ASSET_PAGINATION_SIZE = 1000; - -export const JOBS_TO_QUEUE: Record = { - // misc - [JobName.ASSET_DELETION]: QueueName.BACKGROUND_TASK, - [JobName.ASSET_DELETION_CHECK]: QueueName.BACKGROUND_TASK, - [JobName.USER_DELETE_CHECK]: QueueName.BACKGROUND_TASK, - [JobName.USER_DELETION]: QueueName.BACKGROUND_TASK, - [JobName.DELETE_FILES]: QueueName.BACKGROUND_TASK, - [JobName.CLEAN_OLD_AUDIT_LOGS]: QueueName.BACKGROUND_TASK, - [JobName.PERSON_CLEANUP]: QueueName.BACKGROUND_TASK, - [JobName.USER_SYNC_USAGE]: QueueName.BACKGROUND_TASK, - - // conversion - [JobName.QUEUE_VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION, - [JobName.VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION, - - // thumbnails - [JobName.QUEUE_GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION, - [JobName.GENERATE_JPEG_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, - [JobName.GENERATE_WEBP_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, - [JobName.GENERATE_THUMBHASH_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, - [JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, - - // metadata - [JobName.QUEUE_METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION, - [JobName.METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION, - [JobName.LINK_LIVE_PHOTOS]: QueueName.METADATA_EXTRACTION, - - // storage template - [JobName.STORAGE_TEMPLATE_MIGRATION]: QueueName.STORAGE_TEMPLATE_MIGRATION, - [JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE]: QueueName.STORAGE_TEMPLATE_MIGRATION, - - // migration - [JobName.QUEUE_MIGRATION]: QueueName.MIGRATION, - [JobName.MIGRATE_ASSET]: QueueName.MIGRATION, - [JobName.MIGRATE_PERSON]: QueueName.MIGRATION, - - // facial recognition - [JobName.QUEUE_FACE_DETECTION]: QueueName.FACE_DETECTION, - [JobName.FACE_DETECTION]: QueueName.FACE_DETECTION, - [JobName.QUEUE_FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION, - [JobName.FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION, - - // smart search - [JobName.QUEUE_SMART_SEARCH]: QueueName.SMART_SEARCH, - [JobName.SMART_SEARCH]: QueueName.SMART_SEARCH, - - // XMP sidecars - [JobName.QUEUE_SIDECAR]: QueueName.SIDECAR, - [JobName.SIDECAR_DISCOVERY]: QueueName.SIDECAR, - [JobName.SIDECAR_SYNC]: QueueName.SIDECAR, - [JobName.SIDECAR_WRITE]: QueueName.SIDECAR, - - // Library management - [JobName.LIBRARY_SCAN_ASSET]: QueueName.LIBRARY, - [JobName.LIBRARY_SCAN]: QueueName.LIBRARY, - [JobName.LIBRARY_DELETE]: QueueName.LIBRARY, - [JobName.LIBRARY_REMOVE_OFFLINE]: QueueName.LIBRARY, - [JobName.LIBRARY_QUEUE_SCAN_ALL]: QueueName.LIBRARY, - [JobName.LIBRARY_QUEUE_CLEANUP]: QueueName.LIBRARY, -}; diff --git a/server/src/domain/job/job.interface.ts b/server/src/domain/job/job.interface.ts deleted file mode 100644 index 8e7420bf9..000000000 --- a/server/src/domain/job/job.interface.ts +++ /dev/null @@ -1,41 +0,0 @@ -export interface IBaseJob { - force?: boolean; -} - -export interface IEntityJob extends IBaseJob { - id: string; - source?: 'upload' | 'sidecar-write'; -} - -export interface IAssetDeletionJob extends IEntityJob { - fromExternal?: boolean; -} - -export interface ILibraryFileJob extends IEntityJob { - ownerId: string; - assetPath: string; -} - -export interface ILibraryRefreshJob extends IEntityJob { - refreshModifiedFiles: boolean; - refreshAllFiles: boolean; -} - -export interface IBulkEntityJob extends IBaseJob { - ids: string[]; -} - -export interface IDeleteFilesJob extends IBaseJob { - files: Array; -} - -export interface ISidecarWriteJob extends IEntityJob { - description?: string; - dateTimeOriginal?: string; - latitude?: number; - longitude?: number; -} - -export interface IDeferrableJob extends IEntityJob { - deferred?: boolean; -} diff --git a/server/src/domain/media/media.constant.ts b/server/src/domain/media/media.constant.ts deleted file mode 100644 index 3a8ee414b..000000000 --- a/server/src/domain/media/media.constant.ts +++ /dev/null @@ -1 +0,0 @@ -export const FACE_THUMBNAIL_SIZE = 250; diff --git a/server/src/domain/smart-info/smart-info.constant.ts b/server/src/domain/smart-info/smart-info.constant.ts deleted file mode 100644 index 66c31b985..000000000 --- a/server/src/domain/smart-info/smart-info.constant.ts +++ /dev/null @@ -1,129 +0,0 @@ -export type ModelInfo = { - dimSize: number; -}; - -export const CLIP_MODEL_INFO: Record = { - RN50__openai: { - dimSize: 1024, - }, - RN50__yfcc15m: { - dimSize: 1024, - }, - RN50__cc12m: { - dimSize: 1024, - }, - RN101__openai: { - dimSize: 512, - }, - RN101__yfcc15m: { - dimSize: 512, - }, - RN50x4__openai: { - dimSize: 640, - }, - RN50x16__openai: { - dimSize: 768, - }, - RN50x64__openai: { - dimSize: 1024, - }, - 'ViT-B-32__openai': { - dimSize: 512, - }, - 'ViT-B-32__laion2b_e16': { - dimSize: 512, - }, - 'ViT-B-32__laion400m_e31': { - dimSize: 512, - }, - 'ViT-B-32__laion400m_e32': { - dimSize: 512, - }, - 'ViT-B-32__laion2b-s34b-b79k': { - dimSize: 512, - }, - 'ViT-B-16__openai': { - dimSize: 512, - }, - 'ViT-B-16__laion400m_e31': { - dimSize: 512, - }, - 'ViT-B-16__laion400m_e32': { - dimSize: 512, - }, - 'ViT-B-16-plus-240__laion400m_e31': { - dimSize: 640, - }, - 'ViT-B-16-plus-240__laion400m_e32': { - dimSize: 640, - }, - 'ViT-L-14__openai': { - dimSize: 768, - }, - 'ViT-L-14__laion400m_e31': { - dimSize: 768, - }, - 'ViT-L-14__laion400m_e32': { - dimSize: 768, - }, - 'ViT-L-14__laion2b-s32b-b82k': { - dimSize: 768, - }, - 'ViT-L-14-336__openai': { - dimSize: 768, - }, - 'ViT-L-14-quickgelu__dfn2b': { - dimSize: 768, - }, - 'ViT-H-14__laion2b-s32b-b79k': { - dimSize: 1024, - }, - 'ViT-H-14-quickgelu__dfn5b': { - dimSize: 1024, - }, - 'ViT-H-14-378-quickgelu__dfn5b': { - dimSize: 1024, - }, - 'ViT-g-14__laion2b-s12b-b42k': { - dimSize: 1024, - }, - 'LABSE-Vit-L-14': { - dimSize: 768, - }, - 'XLM-Roberta-Large-Vit-B-32': { - dimSize: 512, - }, - 'XLM-Roberta-Large-Vit-B-16Plus': { - dimSize: 640, - }, - 'XLM-Roberta-Large-Vit-L-14': { - dimSize: 768, - }, - 'XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k': { - dimSize: 1024, - }, - 'nllb-clip-base-siglip__v1': { - dimSize: 768, - }, - 'nllb-clip-large-siglip__v1': { - dimSize: 1152, - }, -}; - -export function cleanModelName(modelName: string): string { - const token = modelName.split('/').at(-1); - if (!token) { - throw new Error(`Invalid model name: ${modelName}`); - } - - return token.replaceAll(':', '_'); -} - -export function getCLIPModelInfo(modelName: string): ModelInfo { - const modelInfo = CLIP_MODEL_INFO[cleanModelName(modelName)]; - if (!modelInfo) { - throw new Error(`Unknown CLIP model: ${modelName}`); - } - - return modelInfo; -} diff --git a/server/src/domain/system-config/system-config.constants.ts b/server/src/domain/system-config/system-config.constants.ts deleted file mode 100644 index 0290472aa..000000000 --- a/server/src/domain/system-config/system-config.constants.ts +++ /dev/null @@ -1,27 +0,0 @@ -export const supportedYearTokens = ['y', 'yy']; -export const supportedMonthTokens = ['M', 'MM', 'MMM', 'MMMM']; -export const supportedWeekTokens = ['W', 'WW']; -export const supportedDayTokens = ['d', 'dd']; -export const supportedHourTokens = ['h', 'hh', 'H', 'HH']; -export const supportedMinuteTokens = ['m', 'mm']; -export const supportedSecondTokens = ['s', 'ss', 'SSS']; -export const supportedPresetTokens = [ - '{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}', - '{{y}}/{{MM}}-{{dd}}/{{filename}}', - '{{y}}/{{MMMM}}-{{dd}}/{{filename}}', - '{{y}}/{{MM}}/{{filename}}', - '{{y}}/{{MMM}}/{{filename}}', - '{{y}}/{{MMMM}}/{{filename}}', - '{{y}}/{{MM}}/{{dd}}/{{filename}}', - '{{y}}/{{MMMM}}/{{dd}}/{{filename}}', - '{{y}}/{{y}}-{{MM}}/{{y}}-{{MM}}-{{dd}}/{{filename}}', - '{{y}}-{{MM}}-{{dd}}/{{filename}}', - '{{y}}-{{MMM}}-{{dd}}/{{filename}}', - '{{y}}-{{MMMM}}-{{dd}}/{{filename}}', - '{{y}}/{{y}}-{{MM}}/{{filename}}', - '{{y}}/{{y}}-{{WW}}/{{filename}}', - '{{y}}/{{y}}-{{MM}}-{{dd}}/{{assetId}}', - '{{y}}/{{y}}-{{MM}}/{{assetId}}', - '{{y}}/{{y}}-{{WW}}/{{assetId}}', - '{{album}}/{{filename}}', -]; diff --git a/server/src/dtos/job.dto.ts b/server/src/dtos/job.dto.ts index fd463a9b0..ad2ffec11 100644 --- a/server/src/dtos/job.dto.ts +++ b/server/src/dtos/job.dto.ts @@ -1,6 +1,6 @@ import { ApiProperty } from '@nestjs/swagger'; import { IsEnum, IsNotEmpty } from 'class-validator'; -import { JobCommand, QueueName } from 'src/domain/job/job.constants'; +import { JobCommand, QueueName } from 'src/interfaces/job.repository'; import { ValidateBoolean } from 'src/validation'; export class JobIdParamDto { diff --git a/server/src/dtos/server-info.dto.ts b/server/src/dtos/server-info.dto.ts index 33fe83044..cce0de59a 100644 --- a/server/src/dtos/server-info.dto.ts +++ b/server/src/dtos/server-info.dto.ts @@ -1,8 +1,8 @@ import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger'; import type { DateTime } from 'luxon'; import { FeatureFlags } from 'src/cores/system-config.core'; -import { IVersion, VersionType } from 'src/domain/domain.constant'; import { SystemConfigThemeDto } from 'src/dtos/system-config-theme.dto'; +import { IVersion, VersionType } from 'src/utils/version'; export class ServerPingResponse { @ApiResponseProperty({ type: String, example: 'pong' }) diff --git a/server/src/dtos/system-config-job.dto.ts b/server/src/dtos/system-config-job.dto.ts index 2769da327..86f4dad1d 100644 --- a/server/src/dtos/system-config-job.dto.ts +++ b/server/src/dtos/system-config-job.dto.ts @@ -1,7 +1,7 @@ import { ApiProperty } from '@nestjs/swagger'; import { Type } from 'class-transformer'; import { IsInt, IsObject, IsPositive, ValidateNested } from 'class-validator'; -import { ConcurrentQueueName, QueueName } from 'src/domain/job/job.constants'; +import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.repository'; export class JobSettingsDto { @IsInt() diff --git a/server/src/entities/system-config.entity.ts b/server/src/entities/system-config.entity.ts index cf7474417..23eae493b 100644 --- a/server/src/entities/system-config.entity.ts +++ b/server/src/entities/system-config.entity.ts @@ -1,4 +1,4 @@ -import { ConcurrentQueueName } from 'src/domain/job/job.constants'; +import { ConcurrentQueueName } from 'src/interfaces/job.repository'; import { Column, Entity, PrimaryColumn } from 'typeorm'; @Entity('system_config') diff --git a/server/src/immich/api-v1/asset/asset-repository.ts b/server/src/immich/api-v1/asset/asset-repository.ts index e7b870239..af01d4ce0 100644 --- a/server/src/immich/api-v1/asset/asset-repository.ts +++ b/server/src/immich/api-v1/asset/asset-repository.ts @@ -7,7 +7,7 @@ import { CheckExistingAssetsDto } from 'src/immich/api-v1/asset/dto/check-existi import { SearchPropertiesDto } from 'src/immich/api-v1/asset/dto/search-properties.dto'; import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; -import { OptionalBetween } from 'src/infra/infra.utils'; +import { OptionalBetween } from 'src/utils/database'; import { In } from 'typeorm/find-options/operator/In.js'; import { Repository } from 'typeorm/repository/Repository.js'; export interface AssetCheck { diff --git a/server/src/immich/api-v1/asset/asset.service.spec.ts b/server/src/immich/api-v1/asset/asset.service.spec.ts index d10590475..0b465e42c 100644 --- a/server/src/immich/api-v1/asset/asset.service.spec.ts +++ b/server/src/immich/api-v1/asset/asset.service.spec.ts @@ -1,5 +1,4 @@ import { when } from 'jest-when'; -import { JobName } from 'src/domain/job/job.constants'; import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository'; @@ -7,7 +6,7 @@ import { AssetService } from 'src/immich/api-v1/asset/asset.service'; import { CreateAssetDto } from 'src/immich/api-v1/asset/dto/create-asset.dto'; import { AssetRejectReason, AssetUploadAction } from 'src/immich/api-v1/asset/response-dto/asset-check-response.dto'; import { IAssetRepository } from 'src/interfaces/asset.repository'; -import { IJobRepository } from 'src/interfaces/job.repository'; +import { IJobRepository, JobName } from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; diff --git a/server/src/immich/api-v1/asset/asset.service.ts b/server/src/immich/api-v1/asset/asset.service.ts index 023017130..61ad72c56 100644 --- a/server/src/immich/api-v1/asset/asset.service.ts +++ b/server/src/immich/api-v1/asset/asset.service.ts @@ -6,8 +6,6 @@ import { NotFoundException, } from '@nestjs/common'; import { AccessCore, Permission } from 'src/cores/access.core'; -import { mimeTypes } from 'src/domain/domain.constant'; -import { JobName } from 'src/domain/job/job.constants'; import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/entities/asset.entity'; @@ -28,15 +26,16 @@ import { AssetFileUploadResponseDto } from 'src/immich/api-v1/asset/response-dto import { CheckExistingAssetsResponseDto } from 'src/immich/api-v1/asset/response-dto/check-existing-assets-response.dto'; import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto'; import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto'; -import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; -import { IJobRepository } from 'src/interfaces/job.repository'; +import { IJobRepository, JobName } from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; import { UploadFile } from 'src/services/asset.service'; -import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/utils'; +import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/utils/file'; +import { ImmichLogger } from 'src/utils/logger'; +import { mimeTypes } from 'src/utils/mime-types'; import { QueryFailedError } from 'typeorm'; @Injectable() diff --git a/server/src/immich/app.utils.ts b/server/src/immich/app.utils.ts index f0e4ba661..46eeccadb 100644 --- a/server/src/immich/app.utils.ts +++ b/server/src/immich/app.utils.ts @@ -13,12 +13,12 @@ import { writeFileSync } from 'node:fs'; import { access, constants } from 'node:fs/promises'; import path, { isAbsolute } from 'node:path'; import { promisify } from 'node:util'; -import { IMMICH_ACCESS_COOKIE, IMMICH_API_KEY_HEADER, IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; -import { serverVersion } from 'src/domain/domain.constant'; -import { ImmichLogger } from 'src/infra/logger'; +import { IMMICH_ACCESS_COOKIE, IMMICH_API_KEY_HEADER, IMMICH_API_KEY_NAME, serverVersion } from 'src/constants'; import { ImmichReadStream } from 'src/interfaces/storage.repository'; import { Metadata } from 'src/middleware/auth.guard'; -import { CacheControl, ImmichFileResponse, isConnectionAborted } from 'src/utils'; +import { CacheControl, ImmichFileResponse } from 'src/utils/file'; +import { ImmichLogger } from 'src/utils/logger'; +import { isConnectionAborted } from 'src/utils/misc'; type SendFile = Parameters; type SendFileOptions = SendFile[1]; diff --git a/server/src/infra/sql-generator/sql.logger.ts b/server/src/infra/sql-generator/sql.logger.ts deleted file mode 100644 index 6f3c298c0..000000000 --- a/server/src/infra/sql-generator/sql.logger.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { format } from 'sql-formatter'; -import { Logger } from 'typeorm'; - -export class SqlLogger implements Logger { - queries: string[] = []; - errors: Array<{ error: string | Error; query: string }> = []; - - clear() { - this.queries = []; - this.errors = []; - } - - logQuery(query: string) { - this.queries.push(format(query, { language: 'postgresql' })); - } - - logQueryError(error: string | Error, query: string) { - this.errors.push({ error, query }); - } - - logQuerySlow() {} - logSchemaBuild() {} - logMigration() {} - log() {} -} diff --git a/server/src/interfaces/asset.repository.ts b/server/src/interfaces/asset.repository.ts index 9bca4a6df..379357b62 100644 --- a/server/src/interfaces/asset.repository.ts +++ b/server/src/interfaces/asset.repository.ts @@ -4,7 +4,7 @@ import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { ReverseGeocodeResult } from 'src/interfaces/metadata.repository'; import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.repository'; -import { Paginated, PaginationOptions } from 'src/utils'; +import { Paginated, PaginationOptions } from 'src/utils/pagination'; import { FindOptionsRelations, FindOptionsSelect } from 'typeorm'; export type AssetStats = Record; diff --git a/server/src/interfaces/database.repository.ts b/server/src/interfaces/database.repository.ts index e87775c3e..42342eccc 100644 --- a/server/src/interfaces/database.repository.ts +++ b/server/src/interfaces/database.repository.ts @@ -1,4 +1,4 @@ -import { Version } from 'src/domain/domain.constant'; +import { Version } from 'src/utils/version'; export enum DatabaseExtension { CUBE = 'cube', diff --git a/server/src/interfaces/job.repository.ts b/server/src/interfaces/job.repository.ts index 023f6a8e9..6f07fc752 100644 --- a/server/src/interfaces/job.repository.ts +++ b/server/src/interfaces/job.repository.ts @@ -1,14 +1,139 @@ -import { JobName, QueueName } from 'src/domain/job/job.constants'; -import { - IAssetDeletionJob, - IBaseJob, - IDeferrableJob, - IDeleteFilesJob, - IEntityJob, - ILibraryFileJob, - ILibraryRefreshJob, - ISidecarWriteJob, -} from 'src/domain/job/job.interface'; +export enum QueueName { + THUMBNAIL_GENERATION = 'thumbnailGeneration', + METADATA_EXTRACTION = 'metadataExtraction', + VIDEO_CONVERSION = 'videoConversion', + FACE_DETECTION = 'faceDetection', + FACIAL_RECOGNITION = 'facialRecognition', + SMART_SEARCH = 'smartSearch', + BACKGROUND_TASK = 'backgroundTask', + STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration', + MIGRATION = 'migration', + SEARCH = 'search', + SIDECAR = 'sidecar', + LIBRARY = 'library', +} + +export type ConcurrentQueueName = Exclude< + QueueName, + QueueName.STORAGE_TEMPLATE_MIGRATION | QueueName.FACIAL_RECOGNITION +>; + +export enum JobCommand { + START = 'start', + PAUSE = 'pause', + RESUME = 'resume', + EMPTY = 'empty', + CLEAR_FAILED = 'clear-failed', +} + +export enum JobName { + // conversion + QUEUE_VIDEO_CONVERSION = 'queue-video-conversion', + VIDEO_CONVERSION = 'video-conversion', + + // thumbnails + QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails', + GENERATE_JPEG_THUMBNAIL = 'generate-jpeg-thumbnail', + GENERATE_WEBP_THUMBNAIL = 'generate-webp-thumbnail', + GENERATE_THUMBHASH_THUMBNAIL = 'generate-thumbhash-thumbnail', + GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail', + + // metadata + QUEUE_METADATA_EXTRACTION = 'queue-metadata-extraction', + METADATA_EXTRACTION = 'metadata-extraction', + LINK_LIVE_PHOTOS = 'link-live-photos', + + // user + USER_DELETION = 'user-deletion', + USER_DELETE_CHECK = 'user-delete-check', + USER_SYNC_USAGE = 'user-sync-usage', + + // asset + ASSET_DELETION = 'asset-deletion', + ASSET_DELETION_CHECK = 'asset-deletion-check', + + // storage template + STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration', + STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single', + + // migration + QUEUE_MIGRATION = 'queue-migration', + MIGRATE_ASSET = 'migrate-asset', + MIGRATE_PERSON = 'migrate-person', + + // facial recognition + PERSON_CLEANUP = 'person-cleanup', + QUEUE_FACE_DETECTION = 'queue-face-detection', + FACE_DETECTION = 'face-detection', + QUEUE_FACIAL_RECOGNITION = 'queue-facial-recognition', + FACIAL_RECOGNITION = 'facial-recognition', + + // library management + LIBRARY_SCAN = 'library-refresh', + LIBRARY_SCAN_ASSET = 'library-refresh-asset', + LIBRARY_REMOVE_OFFLINE = 'library-remove-offline', + LIBRARY_DELETE = 'library-delete', + LIBRARY_QUEUE_SCAN_ALL = 'library-queue-all-refresh', + LIBRARY_QUEUE_CLEANUP = 'library-queue-cleanup', + + // cleanup + DELETE_FILES = 'delete-files', + CLEAN_OLD_AUDIT_LOGS = 'clean-old-audit-logs', + + // smart search + QUEUE_SMART_SEARCH = 'queue-smart-search', + SMART_SEARCH = 'smart-search', + + // XMP sidecars + QUEUE_SIDECAR = 'queue-sidecar', + SIDECAR_DISCOVERY = 'sidecar-discovery', + SIDECAR_SYNC = 'sidecar-sync', + SIDECAR_WRITE = 'sidecar-write', +} + +export const JOBS_ASSET_PAGINATION_SIZE = 1000; + +export interface IBaseJob { + force?: boolean; +} + +export interface IEntityJob extends IBaseJob { + id: string; + source?: 'upload' | 'sidecar-write'; +} + +export interface IAssetDeletionJob extends IEntityJob { + fromExternal?: boolean; +} + +export interface ILibraryFileJob extends IEntityJob { + ownerId: string; + assetPath: string; +} + +export interface ILibraryRefreshJob extends IEntityJob { + refreshModifiedFiles: boolean; + refreshAllFiles: boolean; +} + +export interface IBulkEntityJob extends IBaseJob { + ids: string[]; +} + +export interface IDeleteFilesJob extends IBaseJob { + files: Array; +} + +export interface ISidecarWriteJob extends IEntityJob { + description?: string; + dateTimeOriginal?: string; + latitude?: number; + longitude?: number; +} + +export interface IDeferrableJob extends IEntityJob { + deferred?: boolean; +} export interface JobCounts { active: number; diff --git a/server/src/interfaces/person.repository.ts b/server/src/interfaces/person.repository.ts index cba11fbb9..382bbda22 100644 --- a/server/src/interfaces/person.repository.ts +++ b/server/src/interfaces/person.repository.ts @@ -1,7 +1,7 @@ import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { PersonEntity } from 'src/entities/person.entity'; -import { Paginated, PaginationOptions } from 'src/utils'; +import { Paginated, PaginationOptions } from 'src/utils/pagination'; import { FindManyOptions, FindOptionsRelations, FindOptionsSelect } from 'typeorm'; export const IPersonRepository = 'IPersonRepository'; diff --git a/server/src/interfaces/search.repository.ts b/server/src/interfaces/search.repository.ts index 29eaa32b7..a4be05549 100644 --- a/server/src/interfaces/search.repository.ts +++ b/server/src/interfaces/search.repository.ts @@ -2,7 +2,7 @@ import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; import { SmartInfoEntity } from 'src/entities/smart-info.entity'; -import { Paginated } from 'src/utils'; +import { Paginated } from 'src/utils/pagination'; export const ISearchRepository = 'ISearchRepository'; diff --git a/server/src/middleware/auth.guard.ts b/server/src/middleware/auth.guard.ts index 48befd9a2..eaa47d013 100644 --- a/server/src/middleware/auth.guard.ts +++ b/server/src/middleware/auth.guard.ts @@ -9,10 +9,10 @@ import { import { Reflector } from '@nestjs/core'; import { ApiBearerAuth, ApiCookieAuth, ApiOkResponse, ApiQuery, ApiSecurity } from '@nestjs/swagger'; import { Request } from 'express'; -import { IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant'; +import { IMMICH_API_KEY_NAME } from 'src/constants'; import { AuthDto } from 'src/dtos/auth.dto'; -import { ImmichLogger } from 'src/infra/logger'; import { AuthService, LoginDetails } from 'src/services/auth.service'; +import { ImmichLogger } from 'src/utils/logger'; import { UAParser } from 'ua-parser-js'; export enum Metadata { diff --git a/server/src/middleware/error.interceptor.ts b/server/src/middleware/error.interceptor.ts index 70c129922..d354c1107 100644 --- a/server/src/middleware/error.interceptor.ts +++ b/server/src/middleware/error.interceptor.ts @@ -8,8 +8,8 @@ import { } from '@nestjs/common'; import { Observable, catchError, throwError } from 'rxjs'; import { routeToErrorMessage } from 'src/immich/app.utils'; -import { ImmichLogger } from 'src/infra/logger'; -import { isConnectionAborted } from 'src/utils'; +import { ImmichLogger } from 'src/utils/logger'; +import { isConnectionAborted } from 'src/utils/misc'; @Injectable() export class ErrorInterceptor implements NestInterceptor { diff --git a/server/src/middleware/file-upload.interceptor.ts b/server/src/middleware/file-upload.interceptor.ts index f1d5c5c34..53acbefa8 100644 --- a/server/src/middleware/file-upload.interceptor.ts +++ b/server/src/middleware/file-upload.interceptor.ts @@ -7,9 +7,9 @@ import multer, { StorageEngine, diskStorage } from 'multer'; import { createHash, randomUUID } from 'node:crypto'; import { Observable } from 'rxjs'; import { UploadFieldName } from 'src/dtos/asset.dto'; -import { ImmichLogger } from 'src/infra/logger'; import { AuthRequest } from 'src/middleware/auth.guard'; import { AssetService, UploadFile } from 'src/services/asset.service'; +import { ImmichLogger } from 'src/utils/logger'; export enum Route { ASSET = 'asset', diff --git a/server/src/infra/websocket.adapter.ts b/server/src/middleware/websocket.adapter.ts similarity index 100% rename from server/src/infra/websocket.adapter.ts rename to server/src/middleware/websocket.adapter.ts diff --git a/server/src/migrations/1700713871511-UsePgVectors.ts b/server/src/migrations/1700713871511-UsePgVectors.ts index 46d5320ce..75c85e3e0 100644 --- a/server/src/migrations/1700713871511-UsePgVectors.ts +++ b/server/src/migrations/1700713871511-UsePgVectors.ts @@ -1,5 +1,5 @@ -import { getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; -import { vectorExt } from 'src/infra/database.config'; +import { vectorExt } from 'src/database.config'; +import { getCLIPModelInfo } from 'src/utils/misc'; import { MigrationInterface, QueryRunner } from 'typeorm'; export class UsePgVectors1700713871511 implements MigrationInterface { diff --git a/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts b/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts index b045ba62b..6ca4952f1 100644 --- a/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts +++ b/server/src/migrations/1700713994428-AddCLIPEmbeddingIndex.ts @@ -1,4 +1,4 @@ -import { vectorExt } from 'src/infra/database.config'; +import { vectorExt } from 'src/database.config'; import { DatabaseExtension } from 'src/interfaces/database.repository'; import { MigrationInterface, QueryRunner } from 'typeorm'; diff --git a/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts b/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts index e77ce3b0b..cc68d689c 100644 --- a/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts +++ b/server/src/migrations/1700714033632-AddFaceEmbeddingIndex.ts @@ -1,4 +1,4 @@ -import { vectorExt } from 'src/infra/database.config'; +import { vectorExt } from 'src/database.config'; import { DatabaseExtension } from 'src/interfaces/database.repository'; import { MigrationInterface, QueryRunner } from 'typeorm'; diff --git a/server/src/infra/sql/access.repository.sql b/server/src/queries/access.repository.sql similarity index 100% rename from server/src/infra/sql/access.repository.sql rename to server/src/queries/access.repository.sql diff --git a/server/src/infra/sql/album.repository.sql b/server/src/queries/album.repository.sql similarity index 100% rename from server/src/infra/sql/album.repository.sql rename to server/src/queries/album.repository.sql diff --git a/server/src/infra/sql/api.key.repository.sql b/server/src/queries/api.key.repository.sql similarity index 100% rename from server/src/infra/sql/api.key.repository.sql rename to server/src/queries/api.key.repository.sql diff --git a/server/src/infra/sql/asset.repository.sql b/server/src/queries/asset.repository.sql similarity index 100% rename from server/src/infra/sql/asset.repository.sql rename to server/src/queries/asset.repository.sql diff --git a/server/src/infra/sql/audit.repository.sql b/server/src/queries/audit.repository.sql similarity index 100% rename from server/src/infra/sql/audit.repository.sql rename to server/src/queries/audit.repository.sql diff --git a/server/src/infra/sql/library.repository.sql b/server/src/queries/library.repository.sql similarity index 100% rename from server/src/infra/sql/library.repository.sql rename to server/src/queries/library.repository.sql diff --git a/server/src/infra/sql/move.repository.sql b/server/src/queries/move.repository.sql similarity index 100% rename from server/src/infra/sql/move.repository.sql rename to server/src/queries/move.repository.sql diff --git a/server/src/infra/sql/partner.repository.sql b/server/src/queries/partner.repository.sql similarity index 100% rename from server/src/infra/sql/partner.repository.sql rename to server/src/queries/partner.repository.sql diff --git a/server/src/infra/sql/person.repository.sql b/server/src/queries/person.repository.sql similarity index 100% rename from server/src/infra/sql/person.repository.sql rename to server/src/queries/person.repository.sql diff --git a/server/src/infra/sql/search.repository.sql b/server/src/queries/search.repository.sql similarity index 100% rename from server/src/infra/sql/search.repository.sql rename to server/src/queries/search.repository.sql diff --git a/server/src/infra/sql/shared.link.repository.sql b/server/src/queries/shared.link.repository.sql similarity index 100% rename from server/src/infra/sql/shared.link.repository.sql rename to server/src/queries/shared.link.repository.sql diff --git a/server/src/infra/sql/system.config.repository.sql b/server/src/queries/system.config.repository.sql similarity index 100% rename from server/src/infra/sql/system.config.repository.sql rename to server/src/queries/system.config.repository.sql diff --git a/server/src/infra/sql/system.metadata.repository.sql b/server/src/queries/system.metadata.repository.sql similarity index 100% rename from server/src/infra/sql/system.metadata.repository.sql rename to server/src/queries/system.metadata.repository.sql diff --git a/server/src/infra/sql/tag.repository.sql b/server/src/queries/tag.repository.sql similarity index 100% rename from server/src/infra/sql/tag.repository.sql rename to server/src/queries/tag.repository.sql diff --git a/server/src/infra/sql/user.repository.sql b/server/src/queries/user.repository.sql similarity index 100% rename from server/src/infra/sql/user.repository.sql rename to server/src/queries/user.repository.sql diff --git a/server/src/infra/sql/user.token.repository.sql b/server/src/queries/user.token.repository.sql similarity index 100% rename from server/src/infra/sql/user.token.repository.sql rename to server/src/queries/user.token.repository.sql diff --git a/server/src/repositories/access.repository.ts b/server/src/repositories/access.repository.ts index 418cf542f..fc067f2c2 100644 --- a/server/src/repositories/access.repository.ts +++ b/server/src/repositories/access.repository.ts @@ -9,8 +9,8 @@ import { PartnerEntity } from 'src/entities/partner.entity'; import { PersonEntity } from 'src/entities/person.entity'; import { SharedLinkEntity } from 'src/entities/shared-link.entity'; import { UserTokenEntity } from 'src/entities/user-token.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { IAccessRepository } from 'src/interfaces/access.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { Brackets, In, Repository } from 'typeorm'; type IActivityAccess = IAccessRepository['activity']; diff --git a/server/src/repositories/activity.repository.ts b/server/src/repositories/activity.repository.ts index bec4a4f17..6d4ef244e 100644 --- a/server/src/repositories/activity.repository.ts +++ b/server/src/repositories/activity.repository.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { ActivityEntity } from 'src/entities/activity.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { IActivityRepository } from 'src/interfaces/activity.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { IsNull, Repository } from 'typeorm'; export interface ActivitySearch { diff --git a/server/src/repositories/album.repository.ts b/server/src/repositories/album.repository.ts index 4646ef3d9..c8ad98325 100644 --- a/server/src/repositories/album.repository.ts +++ b/server/src/repositories/album.repository.ts @@ -1,11 +1,10 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource, InjectRepository } from '@nestjs/typeorm'; import _ from 'lodash'; +import { dataSource } from 'src/database.config'; import { Chunked, ChunkedArray, DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from 'src/decorators'; import { AlbumEntity } from 'src/entities/album.entity'; import { AssetEntity } from 'src/entities/asset.entity'; -import { dataSource } from 'src/infra/database.config'; -import { Instrumentation } from 'src/infra/instrumentation'; import { AlbumAsset, AlbumAssetCount, @@ -13,7 +12,8 @@ import { AlbumInfoOptions, IAlbumRepository, } from 'src/interfaces/album.repository'; -import { setUnion } from 'src/utils'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { setUnion } from 'src/utils/set'; import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/api-key.repository.ts b/server/src/repositories/api-key.repository.ts index 14a7db9c9..4ee79f3b4 100644 --- a/server/src/repositories/api-key.repository.ts +++ b/server/src/repositories/api-key.repository.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { APIKeyEntity } from 'src/entities/api-key.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/asset-stack.repository.ts b/server/src/repositories/asset-stack.repository.ts index 9859c5fad..404908ee0 100644 --- a/server/src/repositories/asset-stack.repository.ts +++ b/server/src/repositories/asset-stack.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { AssetStackEntity } from 'src/entities/asset-stack.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/asset.repository.ts b/server/src/repositories/asset.repository.ts index 71bef17ef..0fb46a120 100644 --- a/server/src/repositories/asset.repository.ts +++ b/server/src/repositories/asset.repository.ts @@ -8,8 +8,6 @@ import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { SmartInfoEntity } from 'src/entities/smart-info.entity'; -import { OptionalBetween, paginate, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; -import { Instrumentation } from 'src/infra/instrumentation'; import { AssetBuilderOptions, AssetCreate, @@ -32,7 +30,9 @@ import { WithoutProperty, } from 'src/interfaces/asset.repository'; import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.repository'; -import { Paginated, PaginationMode, PaginationOptions } from 'src/utils'; +import { OptionalBetween, searchAssetBuilder } from 'src/utils/database'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { Paginated, PaginationMode, PaginationOptions, paginate, paginatedBuilder } from 'src/utils/pagination'; import { Brackets, FindOptionsRelations, diff --git a/server/src/repositories/audit.repository.ts b/server/src/repositories/audit.repository.ts index 1d892dab2..ef8081969 100644 --- a/server/src/repositories/audit.repository.ts +++ b/server/src/repositories/audit.repository.ts @@ -1,7 +1,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { AuditEntity } from 'src/entities/audit.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { AuditSearch, IAuditRepository } from 'src/interfaces/audit.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { LessThan, MoreThan, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/communication.repository.ts b/server/src/repositories/communication.repository.ts index 549975c74..531b63f51 100644 --- a/server/src/repositories/communication.repository.ts +++ b/server/src/repositories/communication.repository.ts @@ -7,8 +7,6 @@ import { WebSocketServer, } from '@nestjs/websockets'; import { Server, Socket } from 'socket.io'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; import { ClientEvent, ICommunicationRepository, @@ -18,6 +16,8 @@ import { ServerEvent, } from 'src/interfaces/communication.repository'; import { AuthService } from 'src/services/auth.service'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; @Instrumentation() @WebSocketGateway({ diff --git a/server/src/repositories/crypto.repository.ts b/server/src/repositories/crypto.repository.ts index 121943af3..f7cfa43ff 100644 --- a/server/src/repositories/crypto.repository.ts +++ b/server/src/repositories/crypto.repository.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { compareSync, hash } from 'bcrypt'; import { createHash, randomBytes, randomUUID } from 'node:crypto'; import { createReadStream } from 'node:fs'; -import { Instrumentation } from 'src/infra/instrumentation'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/repositories/database.repository.ts b/server/src/repositories/database.repository.ts index 60586edc5..4e4632741 100644 --- a/server/src/repositories/database.repository.ts +++ b/server/src/repositories/database.repository.ts @@ -1,10 +1,7 @@ import { Injectable } from '@nestjs/common'; import { InjectDataSource } from '@nestjs/typeorm'; import AsyncLock from 'async-lock'; -import { Version, VersionType } from 'src/domain/domain.constant'; -import { vectorExt } from 'src/infra/database.config'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; +import { vectorExt } from 'src/database.config'; import { DatabaseExtension, DatabaseLock, @@ -14,6 +11,9 @@ import { VectorUpdateResult, extName, } from 'src/interfaces/database.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; +import { Version, VersionType } from 'src/utils/version'; import { isValidInteger } from 'src/validation'; import { DataSource, EntityManager, QueryRunner } from 'typeorm'; diff --git a/server/src/repositories/filesystem.provider.ts b/server/src/repositories/filesystem.provider.ts index 1e65f9664..3722893d8 100644 --- a/server/src/repositories/filesystem.provider.ts +++ b/server/src/repositories/filesystem.provider.ts @@ -4,10 +4,7 @@ import { glob, globStream } from 'fast-glob'; import { constants, createReadStream, existsSync, mkdirSync } from 'node:fs'; import fs from 'node:fs/promises'; import path from 'node:path'; -import { mimeTypes } from 'src/domain/domain.constant'; import { CrawlOptionsDto } from 'src/dtos/library.dto'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; import { DiskUsage, IStorageRepository, @@ -16,6 +13,9 @@ import { StorageEventType, WatchEvents, } from 'src/interfaces/storage.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; +import { mimeTypes } from 'src/utils/mime-types'; @Instrumentation() export class FilesystemProvider implements IStorageRepository { diff --git a/server/src/repositories/job.repository.ts b/server/src/repositories/job.repository.ts index a7637e0e6..2d07d7748 100644 --- a/server/src/repositories/job.repository.ts +++ b/server/src/repositories/job.repository.ts @@ -6,10 +6,78 @@ import { Job, JobsOptions, Processor, Queue, Worker, WorkerOptions } from 'bullm import { CronJob, CronTime } from 'cron'; import { setTimeout } from 'node:timers/promises'; import { bullConfig } from 'src/config'; -import { JOBS_TO_QUEUE, JobName, QueueName } from 'src/domain/job/job.constants'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; -import { IJobRepository, JobCounts, JobItem, QueueCleanType, QueueStatus } from 'src/interfaces/job.repository'; +import { + IJobRepository, + JobCounts, + JobItem, + JobName, + QueueCleanType, + QueueName, + QueueStatus, +} from 'src/interfaces/job.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; + +export const JOBS_TO_QUEUE: Record = { + // misc + [JobName.ASSET_DELETION]: QueueName.BACKGROUND_TASK, + [JobName.ASSET_DELETION_CHECK]: QueueName.BACKGROUND_TASK, + [JobName.USER_DELETE_CHECK]: QueueName.BACKGROUND_TASK, + [JobName.USER_DELETION]: QueueName.BACKGROUND_TASK, + [JobName.DELETE_FILES]: QueueName.BACKGROUND_TASK, + [JobName.CLEAN_OLD_AUDIT_LOGS]: QueueName.BACKGROUND_TASK, + [JobName.PERSON_CLEANUP]: QueueName.BACKGROUND_TASK, + [JobName.USER_SYNC_USAGE]: QueueName.BACKGROUND_TASK, + + // conversion + [JobName.QUEUE_VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION, + [JobName.VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION, + + // thumbnails + [JobName.QUEUE_GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION, + [JobName.GENERATE_JPEG_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, + [JobName.GENERATE_WEBP_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, + [JobName.GENERATE_THUMBHASH_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, + [JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION, + + // metadata + [JobName.QUEUE_METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION, + [JobName.METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION, + [JobName.LINK_LIVE_PHOTOS]: QueueName.METADATA_EXTRACTION, + + // storage template + [JobName.STORAGE_TEMPLATE_MIGRATION]: QueueName.STORAGE_TEMPLATE_MIGRATION, + [JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE]: QueueName.STORAGE_TEMPLATE_MIGRATION, + + // migration + [JobName.QUEUE_MIGRATION]: QueueName.MIGRATION, + [JobName.MIGRATE_ASSET]: QueueName.MIGRATION, + [JobName.MIGRATE_PERSON]: QueueName.MIGRATION, + + // facial recognition + [JobName.QUEUE_FACE_DETECTION]: QueueName.FACE_DETECTION, + [JobName.FACE_DETECTION]: QueueName.FACE_DETECTION, + [JobName.QUEUE_FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION, + [JobName.FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION, + + // smart search + [JobName.QUEUE_SMART_SEARCH]: QueueName.SMART_SEARCH, + [JobName.SMART_SEARCH]: QueueName.SMART_SEARCH, + + // XMP sidecars + [JobName.QUEUE_SIDECAR]: QueueName.SIDECAR, + [JobName.SIDECAR_DISCOVERY]: QueueName.SIDECAR, + [JobName.SIDECAR_SYNC]: QueueName.SIDECAR, + [JobName.SIDECAR_WRITE]: QueueName.SIDECAR, + + // Library management + [JobName.LIBRARY_SCAN_ASSET]: QueueName.LIBRARY, + [JobName.LIBRARY_SCAN]: QueueName.LIBRARY, + [JobName.LIBRARY_DELETE]: QueueName.LIBRARY, + [JobName.LIBRARY_REMOVE_OFFLINE]: QueueName.LIBRARY, + [JobName.LIBRARY_QUEUE_SCAN_ALL]: QueueName.LIBRARY, + [JobName.LIBRARY_QUEUE_CLEANUP]: QueueName.LIBRARY, +}; @Instrumentation() @Injectable() diff --git a/server/src/repositories/library.repository.ts b/server/src/repositories/library.repository.ts index 152f544ce..ddf63f228 100644 --- a/server/src/repositories/library.repository.ts +++ b/server/src/repositories/library.repository.ts @@ -3,8 +3,8 @@ import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { LibraryStatsResponseDto } from 'src/dtos/library.dto'; import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { ILibraryRepository } from 'src/interfaces/library.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { IsNull, Not } from 'typeorm'; import { Repository } from 'typeorm/repository/Repository.js'; diff --git a/server/src/repositories/machine-learning.repository.ts b/server/src/repositories/machine-learning.repository.ts index 34f0cdbfc..75d887943 100644 --- a/server/src/repositories/machine-learning.repository.ts +++ b/server/src/repositories/machine-learning.repository.ts @@ -1,7 +1,6 @@ import { Injectable } from '@nestjs/common'; import { readFile } from 'node:fs/promises'; import { CLIPConfig, ModelConfig, RecognitionConfig } from 'src/dtos/model-config.dto'; -import { Instrumentation } from 'src/infra/instrumentation'; import { CLIPMode, DetectFaceResult, @@ -10,6 +9,7 @@ import { TextModelInput, VisionModelInput, } from 'src/interfaces/machine-learning.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; const errorPrefix = 'Machine learning request'; diff --git a/server/src/repositories/media.repository.ts b/server/src/repositories/media.repository.ts index d0f4332b4..890657e3b 100644 --- a/server/src/repositories/media.repository.ts +++ b/server/src/repositories/media.repository.ts @@ -4,8 +4,6 @@ import { Writable } from 'node:stream'; import { promisify } from 'node:util'; import sharp from 'sharp'; import { Colorspace } from 'src/entities/system-config.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; import { CropOptions, IMediaRepository, @@ -13,7 +11,9 @@ import { TranscodeOptions, VideoInfo, } from 'src/interfaces/media.repository'; -import { handlePromiseError } from 'src/utils'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; +import { handlePromiseError } from 'src/utils/misc'; const probe = promisify(ffmpeg.ffprobe); sharp.concurrency(0); diff --git a/server/src/repositories/metadata.repository.ts b/server/src/repositories/metadata.repository.ts index 5da664f14..1b4dd2b3c 100644 --- a/server/src/repositories/metadata.repository.ts +++ b/server/src/repositories/metadata.repository.ts @@ -6,21 +6,15 @@ import { getName } from 'i18n-iso-countries'; import { createReadStream, existsSync } from 'node:fs'; import { readFile } from 'node:fs/promises'; import readLine from 'node:readline'; +import { citiesFile, geodataAdmin1Path, geodataAdmin2Path, geodataCities500Path, geodataDatePath } from 'src/constants'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { - citiesFile, - geodataAdmin1Path, - geodataAdmin2Path, - geodataCities500Path, - geodataDatePath, -} from 'src/domain/domain.constant'; import { ExifEntity } from 'src/entities/exif.entity'; import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; import { GeoPoint, IMetadataRepository, ImmichTags, ReverseGeocodeResult } from 'src/interfaces/metadata.repository'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; import { DataSource, QueryRunner, Repository } from 'typeorm'; import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js'; diff --git a/server/src/repositories/move.repository.ts b/server/src/repositories/move.repository.ts index e567bcca3..5a17d72a5 100644 --- a/server/src/repositories/move.repository.ts +++ b/server/src/repositories/move.repository.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { MoveEntity, PathType } from 'src/entities/move.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { IMoveRepository, MoveCreate } from 'src/interfaces/move.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/partner.repository.ts b/server/src/repositories/partner.repository.ts index 4c4bbc0ed..a07241b53 100644 --- a/server/src/repositories/partner.repository.ts +++ b/server/src/repositories/partner.repository.ts @@ -1,8 +1,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { PartnerEntity } from 'src/entities/partner.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { IPartnerRepository, PartnerIds } from 'src/interfaces/partner.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { DeepPartial, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/person.repository.ts b/server/src/repositories/person.repository.ts index 6a0008c3d..805c91d92 100644 --- a/server/src/repositories/person.repository.ts +++ b/server/src/repositories/person.repository.ts @@ -4,8 +4,6 @@ import { ChunkedArray, DummyValue, GenerateSql } from 'src/decorators'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity } from 'src/entities/asset.entity'; import { PersonEntity } from 'src/entities/person.entity'; -import { asVector, paginate } from 'src/infra/infra.utils'; -import { Instrumentation } from 'src/infra/instrumentation'; import { AssetFaceId, IPersonRepository, @@ -15,7 +13,9 @@ import { PersonStatistics, UpdateFacesData, } from 'src/interfaces/person.repository'; -import { Paginated, PaginationOptions } from 'src/utils'; +import { asVector } from 'src/utils/database'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { Paginated, PaginationOptions, paginate } from 'src/utils/pagination'; import { FindManyOptions, FindOptionsRelations, FindOptionsSelect, In, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/search.repository.ts b/server/src/repositories/search.repository.ts index aefb3c933..8c48337ce 100644 --- a/server/src/repositories/search.repository.ts +++ b/server/src/repositories/search.repository.ts @@ -1,16 +1,12 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; +import { vectorExt } from 'src/database.config'; import { DummyValue, GenerateSql } from 'src/decorators'; -import { getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; import { SmartInfoEntity } from 'src/entities/smart-info.entity'; import { SmartSearchEntity } from 'src/entities/smart-search.entity'; -import { vectorExt } from 'src/infra/database.config'; -import { asVector, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils'; -import { Instrumentation } from 'src/infra/instrumentation'; -import { ImmichLogger } from 'src/infra/logger'; import { DatabaseExtension } from 'src/interfaces/database.repository'; import { AssetSearchOptions, @@ -21,7 +17,11 @@ import { SearchPaginationOptions, SmartSearchOptions, } from 'src/interfaces/search.repository'; -import { Paginated, PaginationMode, PaginationResult } from 'src/utils'; +import { asVector, searchAssetBuilder } from 'src/utils/database'; +import { Instrumentation } from 'src/utils/instrumentation'; +import { ImmichLogger } from 'src/utils/logger'; +import { getCLIPModelInfo } from 'src/utils/misc'; +import { Paginated, PaginationMode, PaginationResult, paginatedBuilder } from 'src/utils/pagination'; import { isValidInteger } from 'src/validation'; import { Repository, SelectQueryBuilder } from 'typeorm'; diff --git a/server/src/repositories/server-info.repository.ts b/server/src/repositories/server-info.repository.ts index fcef0a396..3c25bc65b 100644 --- a/server/src/repositories/server-info.repository.ts +++ b/server/src/repositories/server-info.repository.ts @@ -1,6 +1,6 @@ import { Injectable } from '@nestjs/common'; -import { Instrumentation } from 'src/infra/instrumentation'; import { GitHubRelease, IServerInfoRepository } from 'src/interfaces/server-info.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; @Instrumentation() @Injectable() diff --git a/server/src/repositories/shared-link.repository.ts b/server/src/repositories/shared-link.repository.ts index 968b6dd73..0e343da5e 100644 --- a/server/src/repositories/shared-link.repository.ts +++ b/server/src/repositories/shared-link.repository.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { SharedLinkEntity } from 'src/entities/shared-link.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/system-config.repository.ts b/server/src/repositories/system-config.repository.ts index af6296ce0..ac300fb5d 100644 --- a/server/src/repositories/system-config.repository.ts +++ b/server/src/repositories/system-config.repository.ts @@ -2,8 +2,8 @@ import { InjectRepository } from '@nestjs/typeorm'; import { readFile } from 'node:fs/promises'; import { Chunked, DummyValue, GenerateSql } from 'src/decorators'; import { SystemConfigEntity } from 'src/entities/system-config.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { In, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/system-metadata.repository.ts b/server/src/repositories/system-metadata.repository.ts index 978dba9bd..60bf47965 100644 --- a/server/src/repositories/system-metadata.repository.ts +++ b/server/src/repositories/system-metadata.repository.ts @@ -1,7 +1,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { SystemMetadata, SystemMetadataEntity } from 'src/entities/system-metadata.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/tag.repository.ts b/server/src/repositories/tag.repository.ts index a2ae74878..5e2b2bb6d 100644 --- a/server/src/repositories/tag.repository.ts +++ b/server/src/repositories/tag.repository.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { AssetEntity } from 'src/entities/asset.entity'; import { TagEntity } from 'src/entities/tag.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { ITagRepository } from 'src/interfaces/tag.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/user-token.repository.ts b/server/src/repositories/user-token.repository.ts index 31d6d2190..074aec332 100644 --- a/server/src/repositories/user-token.repository.ts +++ b/server/src/repositories/user-token.repository.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { UserTokenEntity } from 'src/entities/user-token.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/repositories/user.repository.ts b/server/src/repositories/user.repository.ts index bd94e71a5..aaadc637f 100644 --- a/server/src/repositories/user.repository.ts +++ b/server/src/repositories/user.repository.ts @@ -3,13 +3,13 @@ import { InjectRepository } from '@nestjs/typeorm'; import { DummyValue, GenerateSql } from 'src/decorators'; import { AssetEntity } from 'src/entities/asset.entity'; import { UserEntity } from 'src/entities/user.entity'; -import { Instrumentation } from 'src/infra/instrumentation'; import { IUserRepository, UserFindOptions, UserListFilter, UserStatsQueryResponse, } from 'src/interfaces/user.repository'; +import { Instrumentation } from 'src/utils/instrumentation'; import { IsNull, Not, Repository } from 'typeorm'; @Instrumentation() diff --git a/server/src/services/album.service.ts b/server/src/services/album.service.ts index ea7178bed..3ae5ebd74 100644 --- a/server/src/services/album.service.ts +++ b/server/src/services/album.service.ts @@ -21,7 +21,7 @@ import { IAccessRepository } from 'src/interfaces/access.repository'; import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; -import { setUnion } from 'src/utils'; +import { setUnion } from 'src/utils/set'; @Injectable() export class AlbumService { diff --git a/server/src/services/asset.service.spec.ts b/server/src/services/asset.service.spec.ts index 3a6385c03..c2b6a328e 100644 --- a/server/src/services/asset.service.spec.ts +++ b/server/src/services/asset.service.spec.ts @@ -1,13 +1,12 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { when } from 'jest-when'; -import { JobName } from 'src/domain/job/job.constants'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AssetJobName, AssetStatsResponseDto, UploadFieldName } from 'src/dtos/asset.dto'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; import { AssetStats, IAssetRepository, TimeBucketSize } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; -import { IJobRepository, JobItem } from 'src/interfaces/job.repository'; +import { IJobRepository, JobItem, JobName } from 'src/interfaces/job.repository'; import { IPartnerRepository } from 'src/interfaces/partner.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; diff --git a/server/src/services/asset.service.ts b/server/src/services/asset.service.ts index 51a587a67..b537eda1c 100644 --- a/server/src/services/asset.service.ts +++ b/server/src/services/asset.service.ts @@ -6,9 +6,6 @@ import sanitize from 'sanitize-filename'; import { AccessCore, Permission } from 'src/cores/access.core'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { mimeTypes } from 'src/domain/domain.constant'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; -import { IAssetDeletionJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; import { AssetResponseDto, MemoryLaneResponseDto, @@ -31,17 +28,26 @@ import { UpdateStackParentDto } from 'src/dtos/stack.dto'; import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto'; import { AssetEntity } from 'src/entities/asset.entity'; import { LibraryType } from 'src/entities/library.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository'; import { IAssetRepository, TimeBucketOptions } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; -import { IJobRepository, JobItem, JobStatus } from 'src/interfaces/job.repository'; +import { + IAssetDeletionJob, + IJobRepository, + ISidecarWriteJob, + JOBS_ASSET_PAGINATION_SIZE, + JobItem, + JobName, + JobStatus, +} from 'src/interfaces/job.repository'; import { IPartnerRepository } from 'src/interfaces/partner.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; -import { usePagination } from 'src/utils'; +import { ImmichLogger } from 'src/utils/logger'; +import { mimeTypes } from 'src/utils/mime-types'; +import { usePagination } from 'src/utils/pagination'; export interface UploadRequest { auth: AuthDto | null; diff --git a/server/src/services/audit.service.ts b/server/src/services/audit.service.ts index b84f3824d..c9e4d1663 100644 --- a/server/src/services/audit.service.ts +++ b/server/src/services/audit.service.ts @@ -1,10 +1,9 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; import { resolve } from 'node:path'; +import { AUDIT_LOG_MAX_DURATION } from 'src/constants'; import { AccessCore, Permission } from 'src/cores/access.core'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; -import { AUDIT_LOG_MAX_DURATION } from 'src/domain/domain.constant'; -import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; import { AuditDeletesDto, AuditDeletesResponseDto, @@ -16,16 +15,16 @@ import { import { AuthDto } from 'src/dtos/auth.dto'; import { DatabaseAction } from 'src/entities/audit.entity'; import { AssetPathType, PersonPathType, UserPathType } from 'src/entities/move.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IAuditRepository } from 'src/interfaces/audit.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; -import { JobStatus } from 'src/interfaces/job.repository'; +import { JOBS_ASSET_PAGINATION_SIZE, JobStatus } from 'src/interfaces/job.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; -import { usePagination } from 'src/utils'; +import { ImmichLogger } from 'src/utils/logger'; +import { usePagination } from 'src/utils/pagination'; @Injectable() export class AuditService { diff --git a/server/src/services/auth.service.spec.ts b/server/src/services/auth.service.spec.ts index dc7565e4d..a7d212bac 100644 --- a/server/src/services/auth.service.spec.ts +++ b/server/src/services/auth.service.spec.ts @@ -2,7 +2,7 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common'; import { IncomingHttpHeaders } from 'node:http'; import { Issuer, generators } from 'openid-client'; import { Socket } from 'socket.io'; -import { AuthType } from 'src/domain/auth/auth.constant'; +import { AuthType } from 'src/constants'; import { AuthDto, SignUpDto } from 'src/dtos/auth.dto'; import { UserEntity } from 'src/entities/user.entity'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; diff --git a/server/src/services/auth.service.ts b/server/src/services/auth.service.ts index 9ae41a4fc..0d3d5b118 100644 --- a/server/src/services/auth.service.ts +++ b/server/src/services/auth.service.ts @@ -10,9 +10,6 @@ import cookieParser from 'cookie'; import { DateTime } from 'luxon'; import { IncomingHttpHeaders } from 'node:http'; import { ClientMetadata, Issuer, UserinfoResponse, custom, generators } from 'openid-client'; -import { AccessCore, Permission } from 'src/cores/access.core'; -import { SystemConfigCore } from 'src/cores/system-config.core'; -import { UserCore } from 'src/cores/user.core'; import { AuthType, IMMICH_ACCESS_COOKIE, @@ -21,7 +18,10 @@ import { IMMICH_IS_AUTHENTICATED, LOGIN_URL, MOBILE_REDIRECT, -} from 'src/domain/auth/auth.constant'; +} from 'src/constants'; +import { AccessCore, Permission } from 'src/cores/access.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; +import { UserCore } from 'src/cores/user.core'; import { AuthDeviceResponseDto, AuthDto, @@ -39,7 +39,6 @@ import { import { UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { SystemConfig } from 'src/entities/system-config.entity'; import { UserEntity } from 'src/entities/user.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IKeyRepository } from 'src/interfaces/api-key.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; @@ -48,7 +47,8 @@ import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserTokenRepository } from 'src/interfaces/user-token.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; -import { HumanReadableSize } from 'src/utils'; +import { HumanReadableSize } from 'src/utils/bytes'; +import { ImmichLogger } from 'src/utils/logger'; export interface LoginDetails { isSecure: boolean; diff --git a/server/src/services/database.service.spec.ts b/server/src/services/database.service.spec.ts index dac857a07..57c1c0821 100644 --- a/server/src/services/database.service.spec.ts +++ b/server/src/services/database.service.spec.ts @@ -1,7 +1,7 @@ -import { Version, VersionType } from 'src/domain/domain.constant'; -import { ImmichLogger } from 'src/infra/logger'; import { DatabaseExtension, IDatabaseRepository, VectorIndex } from 'src/interfaces/database.repository'; import { DatabaseService } from 'src/services/database.service'; +import { ImmichLogger } from 'src/utils/logger'; +import { Version, VersionType } from 'src/utils/version'; import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; describe(DatabaseService.name, () => { diff --git a/server/src/services/database.service.ts b/server/src/services/database.service.ts index 7bb16a4e1..9f87228b9 100644 --- a/server/src/services/database.service.ts +++ b/server/src/services/database.service.ts @@ -1,6 +1,4 @@ import { Inject, Injectable } from '@nestjs/common'; -import { Version, VersionType } from 'src/domain/domain.constant'; -import { ImmichLogger } from 'src/infra/logger'; import { DatabaseExtension, DatabaseLock, @@ -9,6 +7,8 @@ import { VectorIndex, extName, } from 'src/interfaces/database.repository'; +import { ImmichLogger } from 'src/utils/logger'; +import { Version, VersionType } from 'src/utils/version'; @Injectable() export class DatabaseService { diff --git a/server/src/services/download.service.spec.ts b/server/src/services/download.service.spec.ts index ab8389955..3c4991cd5 100644 --- a/server/src/services/download.service.spec.ts +++ b/server/src/services/download.service.spec.ts @@ -4,7 +4,7 @@ import { DownloadResponseDto } from 'src/dtos/download.dto'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { DownloadService } from 'src/services/download.service'; -import { CacheControl, ImmichFileResponse } from 'src/utils'; +import { CacheControl, ImmichFileResponse } from 'src/utils/file'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock'; diff --git a/server/src/services/download.service.ts b/server/src/services/download.service.ts index b03951764..3ef7dbc4b 100644 --- a/server/src/services/download.service.ts +++ b/server/src/services/download.service.ts @@ -1,7 +1,6 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { parse } from 'node:path'; import { AccessCore, Permission } from 'src/cores/access.core'; -import { mimeTypes } from 'src/domain/domain.constant'; import { AssetIdsDto } from 'src/dtos/asset.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto'; @@ -9,7 +8,10 @@ import { AssetEntity } from 'src/entities/asset.entity'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { IStorageRepository, ImmichReadStream } from 'src/interfaces/storage.repository'; -import { CacheControl, HumanReadableSize, ImmichFileResponse, usePagination } from 'src/utils'; +import { HumanReadableSize } from 'src/utils/bytes'; +import { CacheControl, ImmichFileResponse } from 'src/utils/file'; +import { mimeTypes } from 'src/utils/mime-types'; +import { usePagination } from 'src/utils/pagination'; @Injectable() export class DownloadService { diff --git a/server/src/services/job.service.spec.ts b/server/src/services/job.service.spec.ts index 4be9786a2..13523a142 100644 --- a/server/src/services/job.service.spec.ts +++ b/server/src/services/job.service.spec.ts @@ -1,10 +1,17 @@ import { BadRequestException } from '@nestjs/common'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; -import { JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; import { SystemConfig, SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ICommunicationRepository } from 'src/interfaces/communication.repository'; -import { IJobRepository, JobHandler, JobItem, JobStatus } from 'src/interfaces/job.repository'; +import { + IJobRepository, + JobCommand, + JobHandler, + JobItem, + JobName, + JobStatus, + QueueName, +} from 'src/interfaces/job.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { JobService } from 'src/services/job.service'; diff --git a/server/src/services/job.service.ts b/server/src/services/job.service.ts index 8650b92d4..e6acd54a3 100644 --- a/server/src/services/job.service.ts +++ b/server/src/services/job.service.ts @@ -1,15 +1,24 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; -import { ConcurrentQueueName, JobCommand, JobName, QueueName } from 'src/domain/job/job.constants'; import { mapAsset } from 'src/dtos/asset-response.dto'; import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/dtos/job.dto'; import { AssetType } from 'src/entities/asset.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; -import { IJobRepository, JobHandler, JobItem, JobStatus, QueueCleanType } from 'src/interfaces/job.repository'; +import { + ConcurrentQueueName, + IJobRepository, + JobCommand, + JobHandler, + JobItem, + JobName, + JobStatus, + QueueCleanType, + QueueName, +} from 'src/interfaces/job.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { ImmichLogger } from 'src/utils/logger'; @Injectable() export class JobService { diff --git a/server/src/services/library.service.spec.ts b/server/src/services/library.service.spec.ts index 2382d83c2..46cbef3af 100644 --- a/server/src/services/library.service.spec.ts +++ b/server/src/services/library.service.spec.ts @@ -3,8 +3,6 @@ import { when } from 'jest-when'; import { R_OK } from 'node:constants'; import { Stats } from 'node:fs'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { JobName } from 'src/domain/job/job.constants'; -import { ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; import { mapLibrary } from 'src/dtos/library.dto'; import { AssetType } from 'src/entities/asset.entity'; import { LibraryType } from 'src/entities/library.entity'; @@ -13,7 +11,7 @@ import { UserEntity } from 'src/entities/user.entity'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { IDatabaseRepository } from 'src/interfaces/database.repository'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IJobRepository, ILibraryFileJob, ILibraryRefreshJob, JobName, JobStatus } from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository, StorageEventType } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; diff --git a/server/src/services/library.service.ts b/server/src/services/library.service.ts index f7b298797..63788d9a7 100644 --- a/server/src/services/library.service.ts +++ b/server/src/services/library.service.ts @@ -8,9 +8,6 @@ import path, { basename, parse } from 'node:path'; import picomatch from 'picomatch'; import { StorageCore } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { mimeTypes } from 'src/domain/domain.constant'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; -import { IBaseJob, IEntityJob, ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface'; import { CreateLibraryDto, LibraryResponseDto, @@ -25,16 +22,27 @@ import { } from 'src/dtos/library.dto'; import { AssetType } from 'src/entities/asset.entity'; import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository, WithProperty } from 'src/interfaces/asset.repository'; import { InternalEvent, InternalEventMap } from 'src/interfaces/communication.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { DatabaseLock, IDatabaseRepository } from 'src/interfaces/database.repository'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { + IBaseJob, + IEntityJob, + IJobRepository, + ILibraryFileJob, + ILibraryRefreshJob, + JOBS_ASSET_PAGINATION_SIZE, + JobName, + JobStatus, +} from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository, StorageEventType } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; -import { handlePromiseError, usePagination } from 'src/utils'; +import { ImmichLogger } from 'src/utils/logger'; +import { mimeTypes } from 'src/utils/mime-types'; +import { handlePromiseError } from 'src/utils/misc'; +import { usePagination } from 'src/utils/pagination'; import { validateCronExpression } from 'src/validation'; const LIBRARY_SCAN_BATCH_SIZE = 5000; diff --git a/server/src/services/media.service.spec.ts b/server/src/services/media.service.spec.ts index eb9407e12..722d2a31c 100644 --- a/server/src/services/media.service.spec.ts +++ b/server/src/services/media.service.spec.ts @@ -1,5 +1,4 @@ import { Stats } from 'node:fs'; -import { JobName } from 'src/domain/job/job.constants'; import { AssetType } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { @@ -13,7 +12,7 @@ import { } from 'src/entities/system-config.entity'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.repository'; import { IMediaRepository } from 'src/interfaces/media.repository'; import { IMoveRepository } from 'src/interfaces/move.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; diff --git a/server/src/services/media.service.ts b/server/src/services/media.service.ts index 5c217f2a8..107ac7c73 100644 --- a/server/src/services/media.service.ts +++ b/server/src/services/media.service.ts @@ -1,18 +1,6 @@ import { Inject, Injectable, UnsupportedMediaTypeException } from '@nestjs/common'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; -import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; -import { - H264Config, - HEVCConfig, - NVENCConfig, - QSVConfig, - RKMPPConfig, - ThumbnailConfig, - VAAPIConfig, - VP9Config, -} from 'src/domain/media/media.util'; import { SystemConfigFFmpegDto } from 'src/dtos/system-config-ffmpeg.dto'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { AssetPathType } from 'src/entities/move.entity'; @@ -24,10 +12,18 @@ import { TranscodeTarget, VideoCodec, } from 'src/entities/system-config.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; -import { IJobRepository, JobItem, JobStatus } from 'src/interfaces/job.repository'; +import { + IBaseJob, + IEntityJob, + IJobRepository, + JOBS_ASSET_PAGINATION_SIZE, + JobItem, + JobName, + JobStatus, + QueueName, +} from 'src/interfaces/job.repository'; import { AudioStreamInfo, IMediaRepository, @@ -38,7 +34,18 @@ import { IMoveRepository } from 'src/interfaces/move.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; -import { usePagination } from 'src/utils'; +import { ImmichLogger } from 'src/utils/logger'; +import { + H264Config, + HEVCConfig, + NVENCConfig, + QSVConfig, + RKMPPConfig, + ThumbnailConfig, + VAAPIConfig, + VP9Config, +} from 'src/utils/media'; +import { usePagination } from 'src/utils/pagination'; @Injectable() export class MediaService { diff --git a/server/src/services/metadata.service.spec.ts b/server/src/services/metadata.service.spec.ts index a235aca04..29347f70c 100644 --- a/server/src/services/metadata.service.spec.ts +++ b/server/src/services/metadata.service.spec.ts @@ -3,7 +3,6 @@ import { when } from 'jest-when'; import { randomBytes } from 'node:crypto'; import { Stats } from 'node:fs'; import { constants } from 'node:fs/promises'; -import { JobName } from 'src/domain/job/job.constants'; import { AssetType } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; import { SystemConfigKey } from 'src/entities/system-config.entity'; @@ -12,7 +11,7 @@ import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.reposito import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { IDatabaseRepository } from 'src/interfaces/database.repository'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.repository'; import { IMediaRepository } from 'src/interfaces/media.repository'; import { IMetadataRepository, ImmichTags } from 'src/interfaces/metadata.repository'; import { IMoveRepository } from 'src/interfaces/move.repository'; diff --git a/server/src/services/metadata.service.ts b/server/src/services/metadata.service.ts index 0e949626c..7f9e389bb 100644 --- a/server/src/services/metadata.service.ts +++ b/server/src/services/metadata.service.ts @@ -8,24 +8,32 @@ import path from 'node:path'; import { Subscription } from 'rxjs'; import { StorageCore } from 'src/cores/storage.core'; import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; -import { IBaseJob, IEntityJob, ISidecarWriteJob } from 'src/domain/job/job.interface'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { ExifEntity } from 'src/entities/exif.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { DatabaseLock, IDatabaseRepository } from 'src/interfaces/database.repository'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { + IBaseJob, + IEntityJob, + IJobRepository, + ISidecarWriteJob, + JOBS_ASSET_PAGINATION_SIZE, + JobName, + JobStatus, + QueueName, +} from 'src/interfaces/job.repository'; import { IMediaRepository } from 'src/interfaces/media.repository'; import { IMetadataRepository, ImmichTags } from 'src/interfaces/metadata.repository'; import { IMoveRepository } from 'src/interfaces/move.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; -import { handlePromiseError, usePagination } from 'src/utils'; +import { ImmichLogger } from 'src/utils/logger'; +import { handlePromiseError } from 'src/utils/misc'; +import { usePagination } from 'src/utils/pagination'; /** look for a date from these tags (in order) */ const EXIF_DATE_TAGS: Array = [ diff --git a/server/src/services/person.service.spec.ts b/server/src/services/person.service.spec.ts index 7abc9f3d9..ae391fa2b 100644 --- a/server/src/services/person.service.spec.ts +++ b/server/src/services/person.service.spec.ts @@ -1,12 +1,11 @@ import { BadRequestException, NotFoundException } from '@nestjs/common'; -import { JobName } from 'src/domain/job/job.constants'; import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto'; import { PersonResponseDto, mapFaces, mapPerson } from 'src/dtos/person.dto'; import { AssetFaceEntity } from 'src/entities/asset-face.entity'; import { Colorspace, SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.repository'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; import { IMediaRepository } from 'src/interfaces/media.repository'; import { IMoveRepository } from 'src/interfaces/move.repository'; @@ -15,7 +14,7 @@ import { FaceSearchResult, ISearchRepository } from 'src/interfaces/search.repos import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { PersonService } from 'src/services/person.service'; -import { CacheControl, ImmichFileResponse } from 'src/utils'; +import { CacheControl, ImmichFileResponse } from 'src/utils/file'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; import { faceStub } from 'test/fixtures/face.stub'; diff --git a/server/src/services/person.service.ts b/server/src/services/person.service.ts index 7da482966..99eae8c06 100644 --- a/server/src/services/person.service.ts +++ b/server/src/services/person.service.ts @@ -1,11 +1,8 @@ import { BadRequestException, Inject, Injectable, NotFoundException } from '@nestjs/common'; +import { FACE_THUMBNAIL_SIZE } from 'src/constants'; import { AccessCore, Permission } from 'src/cores/access.core'; import { StorageCore } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { mimeTypes } from 'src/domain/domain.constant'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; -import { IBaseJob, IDeferrableJob, IEntityJob } from 'src/domain/job/job.interface'; -import { FACE_THUMBNAIL_SIZE } from 'src/domain/media/media.constant'; import { BulkIdErrorReason, BulkIdResponseDto } from 'src/dtos/asset-ids.response.dto'; import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; @@ -26,11 +23,20 @@ import { } from 'src/dtos/person.dto'; import { PersonPathType } from 'src/entities/move.entity'; import { PersonEntity } from 'src/entities/person.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; -import { IJobRepository, JobItem, JobStatus } from 'src/interfaces/job.repository'; +import { + IBaseJob, + IDeferrableJob, + IEntityJob, + IJobRepository, + JOBS_ASSET_PAGINATION_SIZE, + JobItem, + JobName, + JobStatus, + QueueName, +} from 'src/interfaces/job.repository'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; import { CropOptions, IMediaRepository } from 'src/interfaces/media.repository'; import { IMoveRepository } from 'src/interfaces/move.repository'; @@ -38,7 +44,10 @@ import { IPersonRepository, UpdateFacesData } from 'src/interfaces/person.reposi import { ISearchRepository } from 'src/interfaces/search.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; -import { CacheControl, ImmichFileResponse, usePagination } from 'src/utils'; +import { CacheControl, ImmichFileResponse } from 'src/utils/file'; +import { ImmichLogger } from 'src/utils/logger'; +import { mimeTypes } from 'src/utils/mime-types'; +import { usePagination } from 'src/utils/pagination'; import { IsNull } from 'typeorm'; @Injectable() diff --git a/server/src/services/server-info.service.spec.ts b/server/src/services/server-info.service.spec.ts index 0db7597b8..fe678dbef 100644 --- a/server/src/services/server-info.service.spec.ts +++ b/server/src/services/server-info.service.spec.ts @@ -1,4 +1,4 @@ -import { serverVersion } from 'src/domain/domain.constant'; +import { serverVersion } from 'src/constants'; import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; import { ICommunicationRepository } from 'src/interfaces/communication.repository'; import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; diff --git a/server/src/services/server-info.service.ts b/server/src/services/server-info.service.ts index a76ae4022..e0a62bdc7 100644 --- a/server/src/services/server-info.service.ts +++ b/server/src/services/server-info.service.ts @@ -1,8 +1,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { DateTime } from 'luxon'; +import { isDev, serverVersion } from 'src/constants'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { Version, isDev, mimeTypes, serverVersion } from 'src/domain/domain.constant'; import { ServerConfigDto, ServerFeaturesDto, @@ -13,14 +13,16 @@ import { UsageByUserDto, } from 'src/dtos/server-info.dto'; import { SystemMetadataKey } from 'src/entities/system-metadata.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; import { IServerInfoRepository } from 'src/interfaces/server-info.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository'; import { IUserRepository, UserStatsQueryResponse } from 'src/interfaces/user.repository'; -import { asHumanReadable } from 'src/utils'; +import { asHumanReadable } from 'src/utils/bytes'; +import { ImmichLogger } from 'src/utils/logger'; +import { mimeTypes } from 'src/utils/mime-types'; +import { Version } from 'src/utils/version'; @Injectable() export class ServerInfoService { diff --git a/server/src/services/shared-link.service.ts b/server/src/services/shared-link.service.ts index a84a1f120..44b1f91e5 100644 --- a/server/src/services/shared-link.service.ts +++ b/server/src/services/shared-link.service.ts @@ -16,7 +16,7 @@ import { SharedLinkEntity, SharedLinkType } from 'src/entities/shared-link.entit import { IAccessRepository } from 'src/interfaces/access.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository'; -import { OpenGraphTags } from 'src/utils'; +import { OpenGraphTags } from 'src/utils/misc'; @Injectable() export class SharedLinkService { diff --git a/server/src/services/smart-info.service.spec.ts b/server/src/services/smart-info.service.spec.ts index a1b8943f2..b74211da3 100644 --- a/server/src/services/smart-info.service.spec.ts +++ b/server/src/services/smart-info.service.spec.ts @@ -1,14 +1,13 @@ -import { JobName } from 'src/domain/job/job.constants'; -import { cleanModelName, getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant'; import { AssetEntity } from 'src/entities/asset.entity'; import { SystemConfigKey } from 'src/entities/system-config.entity'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { IDatabaseRepository } from 'src/interfaces/database.repository'; -import { IJobRepository } from 'src/interfaces/job.repository'; +import { IJobRepository, JobName } from 'src/interfaces/job.repository'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; import { ISearchRepository } from 'src/interfaces/search.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { SmartInfoService } from 'src/services/smart-info.service'; +import { getCLIPModelInfo } from 'src/utils/misc'; import { assetStub } from 'test/fixtures/asset.stub'; import { newAssetRepositoryMock } from 'test/repositories/asset.repository.mock'; import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock'; @@ -124,16 +123,14 @@ describe(SmartInfoService.name, () => { }); }); - describe('cleanModelName', () => { - it('should clean name', () => { - expect(cleanModelName('ViT-B-32::openai')).toEqual('ViT-B-32__openai'); - expect(cleanModelName('M-CLIP/XLM-Roberta-Large-Vit-L-14')).toEqual('XLM-Roberta-Large-Vit-L-14'); - }); - }); - describe('getCLIPModelInfo', () => { it('should return the model info', () => { expect(getCLIPModelInfo('ViT-B-32__openai')).toEqual({ dimSize: 512 }); + expect(getCLIPModelInfo('M-CLIP/XLM-Roberta-Large-Vit-L-14')).toEqual({ dimSize: 768 }); + }); + + it('should clean the model name', () => { + expect(getCLIPModelInfo('ViT-B-32::openai')).toEqual({ dimSize: 512 }); }); it('should throw an error if the model is not present', () => { diff --git a/server/src/services/smart-info.service.ts b/server/src/services/smart-info.service.ts index a7d470008..d686cd56d 100644 --- a/server/src/services/smart-info.service.ts +++ b/server/src/services/smart-info.service.ts @@ -1,15 +1,21 @@ import { Inject, Injectable } from '@nestjs/common'; import { SystemConfigCore } from 'src/cores/system-config.core'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName, QueueName } from 'src/domain/job/job.constants'; -import { IBaseJob, IEntityJob } from 'src/domain/job/job.interface'; -import { ImmichLogger } from 'src/infra/logger'; import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.repository'; import { DatabaseLock, IDatabaseRepository } from 'src/interfaces/database.repository'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { + IBaseJob, + IEntityJob, + IJobRepository, + JOBS_ASSET_PAGINATION_SIZE, + JobName, + JobStatus, + QueueName, +} from 'src/interfaces/job.repository'; import { IMachineLearningRepository } from 'src/interfaces/machine-learning.repository'; import { ISearchRepository } from 'src/interfaces/search.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; -import { usePagination } from 'src/utils'; +import { ImmichLogger } from 'src/utils/logger'; +import { usePagination } from 'src/utils/pagination'; @Injectable() export class SmartInfoService { diff --git a/server/src/services/storage-template.service.ts b/server/src/services/storage-template.service.ts index b4af03a9f..43c6eb09e 100644 --- a/server/src/services/storage-template.service.ts +++ b/server/src/services/storage-template.service.ts @@ -4,10 +4,6 @@ import handlebar from 'handlebars'; import { DateTime } from 'luxon'; import path from 'node:path'; import sanitize from 'sanitize-filename'; -import { StorageCore, StorageFolder } from 'src/cores/storage.core'; -import { SystemConfigCore } from 'src/cores/system-config.core'; -import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants'; -import { IEntityJob } from 'src/domain/job/job.interface'; import { supportedDayTokens, supportedHourTokens, @@ -16,23 +12,26 @@ import { supportedSecondTokens, supportedWeekTokens, supportedYearTokens, -} from 'src/domain/system-config/system-config.constants'; +} from 'src/constants'; +import { StorageCore, StorageFolder } from 'src/cores/storage.core'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { AssetEntity, AssetType } from 'src/entities/asset.entity'; import { AssetPathType } from 'src/entities/move.entity'; import { SystemConfig } from 'src/entities/system-config.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { InternalEvent, InternalEventMap } from 'src/interfaces/communication.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; import { DatabaseLock, IDatabaseRepository } from 'src/interfaces/database.repository'; -import { JobStatus } from 'src/interfaces/job.repository'; +import { IEntityJob, JOBS_ASSET_PAGINATION_SIZE, JobStatus } from 'src/interfaces/job.repository'; import { IMoveRepository } from 'src/interfaces/move.repository'; import { IPersonRepository } from 'src/interfaces/person.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; -import { getLivePhotoMotionFilename, usePagination } from 'src/utils'; +import { getLivePhotoMotionFilename } from 'src/utils/file'; +import { ImmichLogger } from 'src/utils/logger'; +import { usePagination } from 'src/utils/pagination'; export interface MoveAssetMetadata { storageLabel: string | null; diff --git a/server/src/services/storage.service.ts b/server/src/services/storage.service.ts index 9df3dd778..22cac0040 100644 --- a/server/src/services/storage.service.ts +++ b/server/src/services/storage.service.ts @@ -1,9 +1,8 @@ import { Inject, Injectable } from '@nestjs/common'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; -import { IDeleteFilesJob } from 'src/domain/job/job.interface'; -import { ImmichLogger } from 'src/infra/logger'; -import { JobStatus } from 'src/interfaces/job.repository'; +import { IDeleteFilesJob, JobStatus } from 'src/interfaces/job.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; +import { ImmichLogger } from 'src/utils/logger'; @Injectable() export class StorageService { diff --git a/server/src/services/system-config.service.spec.ts b/server/src/services/system-config.service.spec.ts index b5b5875d7..d7896e87e 100644 --- a/server/src/services/system-config.service.spec.ts +++ b/server/src/services/system-config.service.spec.ts @@ -1,6 +1,5 @@ import { BadRequestException } from '@nestjs/common'; import { defaults } from 'src/cores/system-config.core'; -import { QueueName } from 'src/domain/job/job.constants'; import { AudioCodec, CQMode, @@ -14,11 +13,12 @@ import { TranscodePolicy, VideoCodec, } from 'src/entities/system-config.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { ICommunicationRepository, ServerEvent } from 'src/interfaces/communication.repository'; +import { QueueName } from 'src/interfaces/job.repository'; import { ISearchRepository } from 'src/interfaces/search.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { SystemConfigService } from 'src/services/system-config.service'; +import { ImmichLogger } from 'src/utils/logger'; import { newCommunicationRepositoryMock } from 'test/repositories/communication.repository.mock'; import { newSystemConfigRepositoryMock } from 'test/repositories/system-config.repository.mock'; diff --git a/server/src/services/system-config.service.ts b/server/src/services/system-config.service.ts index c5837dca2..acb8b13fb 100644 --- a/server/src/services/system-config.service.ts +++ b/server/src/services/system-config.service.ts @@ -2,7 +2,6 @@ import { BadRequestException, Inject, Injectable } from '@nestjs/common'; import { OnEvent } from '@nestjs/event-emitter'; import { instanceToPlain } from 'class-transformer'; import _ from 'lodash'; -import { SystemConfigCore } from 'src/cores/system-config.core'; import { supportedDayTokens, supportedHourTokens, @@ -12,11 +11,11 @@ import { supportedSecondTokens, supportedWeekTokens, supportedYearTokens, -} from 'src/domain/system-config/system-config.constants'; +} from 'src/constants'; +import { SystemConfigCore } from 'src/cores/system-config.core'; import { SystemConfigTemplateStorageOptionDto } from 'src/dtos/system-config-storage-template.dto'; import { SystemConfigDto, mapConfig } from 'src/dtos/system-config.dto'; import { LogLevel, SystemConfig } from 'src/entities/system-config.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { ClientEvent, ICommunicationRepository, @@ -26,6 +25,7 @@ import { } from 'src/interfaces/communication.repository'; import { ISearchRepository } from 'src/interfaces/search.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; +import { ImmichLogger } from 'src/utils/logger'; @Injectable() export class SystemConfigService { diff --git a/server/src/services/trash.service.spec.ts b/server/src/services/trash.service.spec.ts index 09f668e6f..03e87a8d0 100644 --- a/server/src/services/trash.service.spec.ts +++ b/server/src/services/trash.service.spec.ts @@ -1,8 +1,7 @@ import { BadRequestException } from '@nestjs/common'; -import { JobName } from 'src/domain/job/job.constants'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; -import { IJobRepository } from 'src/interfaces/job.repository'; +import { IJobRepository, JobName } from 'src/interfaces/job.repository'; import { TrashService } from 'src/services/trash.service'; import { assetStub } from 'test/fixtures/asset.stub'; import { authStub } from 'test/fixtures/auth.stub'; diff --git a/server/src/services/trash.service.ts b/server/src/services/trash.service.ts index 9bece663b..61de73097 100644 --- a/server/src/services/trash.service.ts +++ b/server/src/services/trash.service.ts @@ -1,14 +1,13 @@ import { Inject } from '@nestjs/common'; import { DateTime } from 'luxon'; import { AccessCore, Permission } from 'src/cores/access.core'; -import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants'; import { BulkIdsDto } from 'src/dtos/asset-ids.response.dto'; import { AuthDto } from 'src/dtos/auth.dto'; import { IAccessRepository } from 'src/interfaces/access.repository'; import { IAssetRepository } from 'src/interfaces/asset.repository'; import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository'; -import { IJobRepository } from 'src/interfaces/job.repository'; -import { usePagination } from 'src/utils'; +import { IJobRepository, JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/interfaces/job.repository'; +import { usePagination } from 'src/utils/pagination'; export class TrashService { private access: AccessCore; diff --git a/server/src/services/user.service.spec.ts b/server/src/services/user.service.spec.ts index 51457b201..6a639003d 100644 --- a/server/src/services/user.service.spec.ts +++ b/server/src/services/user.service.spec.ts @@ -5,18 +5,17 @@ import { NotFoundException, } from '@nestjs/common'; import { when } from 'jest-when'; -import { JobName } from 'src/domain/job/job.constants'; import { UpdateUserDto, mapUser } from 'src/dtos/user.dto'; import { UserEntity, UserStatus } from 'src/entities/user.entity'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; -import { IJobRepository } from 'src/interfaces/job.repository'; +import { IJobRepository, JobName } from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserRepository } from 'src/interfaces/user.repository'; import { UserService } from 'src/services/user.service'; -import { CacheControl, ImmichFileResponse } from 'src/utils'; +import { CacheControl, ImmichFileResponse } from 'src/utils/file'; import { authStub } from 'test/fixtures/auth.stub'; import { systemConfigStub } from 'test/fixtures/system-config.stub'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/src/services/user.service.ts b/server/src/services/user.service.ts index ef742123f..e4d8f11c4 100644 --- a/server/src/services/user.service.ts +++ b/server/src/services/user.service.ts @@ -4,21 +4,19 @@ import { randomBytes } from 'node:crypto'; import { StorageCore, StorageFolder } from 'src/cores/storage.core'; import { SystemConfigCore } from 'src/cores/system-config.core'; import { UserCore } from 'src/cores/user.core'; -import { JobName } from 'src/domain/job/job.constants'; -import { IEntityJob } from 'src/domain/job/job.interface'; import { AuthDto } from 'src/dtos/auth.dto'; import { CreateProfileImageResponseDto, mapCreateProfileImageResponse } from 'src/dtos/user-profile.dto'; import { CreateUserDto, DeleteUserDto, UpdateUserDto, UserResponseDto, mapUser } from 'src/dtos/user.dto'; import { UserEntity, UserStatus } from 'src/entities/user.entity'; -import { ImmichLogger } from 'src/infra/logger'; import { IAlbumRepository } from 'src/interfaces/album.repository'; import { ICryptoRepository } from 'src/interfaces/crypto.repository'; -import { IJobRepository, JobStatus } from 'src/interfaces/job.repository'; +import { IEntityJob, IJobRepository, JobName, JobStatus } from 'src/interfaces/job.repository'; import { ILibraryRepository } from 'src/interfaces/library.repository'; import { IStorageRepository } from 'src/interfaces/storage.repository'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { IUserRepository, UserFindOptions } from 'src/interfaces/user.repository'; -import { CacheControl, ImmichFileResponse } from 'src/utils'; +import { CacheControl, ImmichFileResponse } from 'src/utils/file'; +import { ImmichLogger } from 'src/utils/logger'; @Injectable() export class UserService { diff --git a/server/src/utils.spec.ts b/server/src/utils.spec.ts deleted file mode 100644 index c5ae5f6e5..000000000 --- a/server/src/utils.spec.ts +++ /dev/null @@ -1,103 +0,0 @@ -import { isDecimalNumber, isNumberInRange, parseLatitude, parseLongitude, toNumberOrNull } from 'src/utils'; - -describe('checks if a number is a decimal number', () => { - it('returns false for non-decimal numbers', () => { - expect(isDecimalNumber(Number.NaN)).toBe(false); - expect(isDecimalNumber(Number.POSITIVE_INFINITY)).toBe(false); - expect(isDecimalNumber(Number.NEGATIVE_INFINITY)).toBe(false); - }); - - it('returns true for decimal numbers', () => { - expect(isDecimalNumber(0)).toBe(true); - expect(isDecimalNumber(-0)).toBe(true); - expect(isDecimalNumber(10.123_45)).toBe(true); - expect(isDecimalNumber(Number.MAX_VALUE)).toBe(true); - expect(isDecimalNumber(Number.MIN_VALUE)).toBe(true); - }); -}); - -describe('checks if a number is within a range', () => { - it('returns false for numbers outside the range', () => { - expect(isNumberInRange(0, 10, 10)).toBe(false); - expect(isNumberInRange(0.01, 10, 10)).toBe(false); - expect(isNumberInRange(50.1, 0, 50)).toBe(false); - }); - - it('returns true for numbers inside the range', () => { - expect(isNumberInRange(0, 0, 50)).toBe(true); - expect(isNumberInRange(50, 0, 50)).toBe(true); - expect(isNumberInRange(-50.123_45, -50.123_45, 0)).toBe(true); - }); -}); - -describe('converts input to a number or null', () => { - it('returns null for invalid inputs', () => { - expect(toNumberOrNull(null)).toBeNull(); - // eslint-disable-next-line unicorn/no-useless-undefined - expect(toNumberOrNull(undefined)).toBeNull(); - expect(toNumberOrNull('')).toBeNull(); - expect(toNumberOrNull(Number.NaN)).toBeNull(); - }); - - it('returns a number for valid inputs', () => { - expect(toNumberOrNull(0)).toBeCloseTo(0); - expect(toNumberOrNull('0')).toBeCloseTo(0); - expect(toNumberOrNull('-123.45')).toBeCloseTo(-123.45); - }); -}); - -describe('parsing latitude from string input', () => { - it('returns null for invalid inputs', () => { - expect(parseLatitude('')).toBeNull(); - expect(parseLatitude('NaN')).toBeNull(); - expect(parseLatitude('Infinity')).toBeNull(); - expect(parseLatitude('-Infinity')).toBeNull(); - expect(parseLatitude('90.001')).toBeNull(); - expect(parseLatitude(-90.000_001)).toBeNull(); - expect(parseLatitude('1000')).toBeNull(); - expect(parseLatitude(-1000)).toBeNull(); - }); - - it('returns the numeric coordinate for valid inputs', () => { - expect(parseLatitude('90')).toBeCloseTo(90); - expect(parseLatitude('-90')).toBeCloseTo(-90); - expect(parseLatitude(89.999_999)).toBeCloseTo(89.999_999); - expect(parseLatitude('-89.9')).toBeCloseTo(-89.9); - expect(parseLatitude(0)).toBeCloseTo(0); - expect(parseLatitude('-0.0')).toBeCloseTo(-0); - }); -}); - -describe('parsing latitude from null input', () => { - it('returns null for null input', () => { - expect(parseLatitude(null)).toBeNull(); - }); -}); - -describe('parsing longitude from string input', () => { - it('returns null for invalid inputs', () => { - expect(parseLongitude('')).toBeNull(); - expect(parseLongitude('NaN')).toBeNull(); - expect(parseLongitude(Number.POSITIVE_INFINITY)).toBeNull(); - expect(parseLongitude('-Infinity')).toBeNull(); - expect(parseLongitude('180.001')).toBeNull(); - expect(parseLongitude('-180.000001')).toBeNull(); - expect(parseLongitude(1000)).toBeNull(); - expect(parseLongitude('-1000')).toBeNull(); - }); - - it('returns the numeric coordinate for valid inputs', () => { - expect(parseLongitude(180)).toBeCloseTo(180); - expect(parseLongitude('-180')).toBeCloseTo(-180); - expect(parseLongitude('179.999999')).toBeCloseTo(179.999_999); - expect(parseLongitude(-179.9)).toBeCloseTo(-179.9); - expect(parseLongitude('0')).toBeCloseTo(0); - expect(parseLongitude('-0.0')).toBeCloseTo(-0); - }); -}); - -describe('parsing longitude from null input', () => { - it('returns null for null input', () => { - expect(parseLongitude(null)).toBeNull(); - }); -}); diff --git a/server/src/utils.ts b/server/src/utils.ts deleted file mode 100644 index 863dde7ca..000000000 --- a/server/src/utils.ts +++ /dev/null @@ -1,181 +0,0 @@ -import { basename, extname } from 'node:path'; -import { ImmichLogger } from 'src/infra/logger'; - -const KiB = Math.pow(1024, 1); -const MiB = Math.pow(1024, 2); -const GiB = Math.pow(1024, 3); -const TiB = Math.pow(1024, 4); -const PiB = Math.pow(1024, 5); - -export const HumanReadableSize = { KiB, MiB, GiB, TiB, PiB }; - -export function asHumanReadable(bytes: number, precision = 1): string { - const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']; - - let magnitude = 0; - let remainder = bytes; - while (remainder >= 1024) { - if (magnitude + 1 < units.length) { - magnitude++; - remainder /= 1024; - } else { - break; - } - } - - return `${remainder.toFixed(magnitude == 0 ? 0 : precision)} ${units[magnitude]}`; -} - -export const isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED'; - -export function isDecimalNumber(number_: number): boolean { - return !Number.isNaN(number_) && Number.isFinite(number_); -} - -/** - * Check if `num` is a valid number and is between `start` and `end` (inclusive) - */ -export function isNumberInRange(number_: number, start: number, end: number): boolean { - return isDecimalNumber(number_) && number_ >= start && number_ <= end; -} - -export function toNumberOrNull(input: number | string | null | undefined): number | null { - if (input === null || input === undefined) { - return null; - } - - const number_ = typeof input === 'string' ? Number.parseFloat(input) : input; - return isDecimalNumber(number_) ? number_ : null; -} - -export function parseLatitude(input: string | number | null): number | null { - if (input === null) { - return null; - } - const latitude = typeof input === 'string' ? Number.parseFloat(input) : input; - - if (isNumberInRange(latitude, -90, 90)) { - return latitude; - } - return null; -} - -export function parseLongitude(input: string | number | null): number | null { - if (input === null) { - return null; - } - - const longitude = typeof input === 'string' ? Number.parseFloat(input) : input; - - if (isNumberInRange(longitude, -180, 180)) { - return longitude; - } - return null; -} - -// NOTE: The following Set utils have been added here, to easily determine where they are used. -// They should be replaced with native Set operations, when they are added to the language. -// Proposal reference: https://github.com/tc39/proposal-set-methods - -export const setUnion = (...sets: Set[]): Set => { - const union = new Set(sets[0]); - for (const set of sets.slice(1)) { - for (const element of set) { - union.add(element); - } - } - return union; -}; - -export const setDifference = (setA: Set, ...sets: Set[]): Set => { - const difference = new Set(setA); - for (const set of sets) { - for (const element of set) { - difference.delete(element); - } - } - return difference; -}; - -export const setIsSuperset = (set: Set, subset: Set): boolean => { - for (const element of subset) { - if (!set.has(element)) { - return false; - } - } - return true; -}; - -export const setIsEqual = (setA: Set, setB: Set): boolean => { - return setA.size === setB.size && setIsSuperset(setA, setB); -}; - -export const handlePromiseError = (promise: Promise, logger: ImmichLogger): void => { - promise.catch((error: Error | any) => logger.error(`Promise error: ${error}`, error?.stack)); -}; - -export enum CacheControl { - PRIVATE_WITH_CACHE = 'private_with_cache', - PRIVATE_WITHOUT_CACHE = 'private_without_cache', - NONE = 'none', -} - -export class ImmichFileResponse { - public readonly path!: string; - public readonly contentType!: string; - public readonly cacheControl!: CacheControl; - - constructor(response: ImmichFileResponse) { - Object.assign(this, response); - } -} - -export interface OpenGraphTags { - title: string; - description: string; - imageUrl?: string; -} - -export function getFileNameWithoutExtension(path: string): string { - return basename(path, extname(path)); -} - -export function getLivePhotoMotionFilename(stillName: string, motionName: string) { - return getFileNameWithoutExtension(stillName) + extname(motionName); -} - -export interface PaginationOptions { - take: number; - skip?: number; -} - -export enum PaginationMode { - LIMIT_OFFSET = 'limit-offset', - SKIP_TAKE = 'skip-take', -} - -export interface PaginatedBuilderOptions { - take: number; - skip?: number; - mode?: PaginationMode; -} - -export interface PaginationResult { - items: T[]; - hasNextPage: boolean; -} - -export type Paginated = Promise>; - -export async function* usePagination( - pageSize: number, - getNextPage: (pagination: PaginationOptions) => PaginationResult | Paginated, -) { - let hasNextPage = true; - - for (let skip = 0; hasNextPage; skip += pageSize) { - const result = await getNextPage({ take: pageSize, skip }); - hasNextPage = result.hasNextPage; - yield result.items; - } -} diff --git a/server/src/utils/bytes.ts b/server/src/utils/bytes.ts new file mode 100644 index 000000000..e837c81b9 --- /dev/null +++ b/server/src/utils/bytes.ts @@ -0,0 +1,24 @@ +const KiB = Math.pow(1024, 1); +const MiB = Math.pow(1024, 2); +const GiB = Math.pow(1024, 3); +const TiB = Math.pow(1024, 4); +const PiB = Math.pow(1024, 5); + +export const HumanReadableSize = { KiB, MiB, GiB, TiB, PiB }; + +export function asHumanReadable(bytes: number, precision = 1): string { + const units = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB']; + + let magnitude = 0; + let remainder = bytes; + while (remainder >= 1024) { + if (magnitude + 1 < units.length) { + magnitude++; + remainder /= 1024; + } else { + break; + } + } + + return `${remainder.toFixed(magnitude == 0 ? 0 : precision)} ${units[magnitude]}`; +} diff --git a/server/src/infra/infra.utils.ts b/server/src/utils/database.ts similarity index 75% rename from server/src/infra/infra.utils.ts rename to server/src/utils/database.ts index 2b75af379..3a3e4603b 100644 --- a/server/src/infra/infra.utils.ts +++ b/server/src/utils/database.ts @@ -1,18 +1,7 @@ import _ from 'lodash'; import { AssetEntity } from 'src/entities/asset.entity'; import { AssetSearchBuilderOptions } from 'src/interfaces/search.repository'; -import { Paginated, PaginatedBuilderOptions, PaginationMode, PaginationOptions, PaginationResult } from 'src/utils'; -import { - Between, - FindManyOptions, - IsNull, - LessThanOrEqual, - MoreThanOrEqual, - Not, - ObjectLiteral, - Repository, - SelectQueryBuilder, -} from 'typeorm'; +import { Between, IsNull, LessThanOrEqual, MoreThanOrEqual, Not, SelectQueryBuilder } from 'typeorm'; /** * Allows optional values unlike the regular Between and uses MoreThanOrEqual @@ -28,47 +17,6 @@ export function OptionalBetween(from?: T, to?: T) { } } -function paginationHelper(items: Entity[], take: number): PaginationResult { - const hasNextPage = items.length > take; - items.splice(take); - - return { items, hasNextPage }; -} - -export async function paginate( - repository: Repository, - { take, skip }: PaginationOptions, - searchOptions?: FindManyOptions, -): Paginated { - const items = await repository.find( - _.omitBy( - { - ...searchOptions, - // Take one more item to check if there's a next page - take: take + 1, - skip, - }, - _.isUndefined, - ), - ); - - return paginationHelper(items, take); -} - -export async function paginatedBuilder( - qb: SelectQueryBuilder, - { take, skip, mode }: PaginatedBuilderOptions, -): Paginated { - if (mode === PaginationMode.LIMIT_OFFSET) { - qb.limit(take + 1).offset(skip); - } else { - qb.take(take + 1).skip(skip); - } - - const items = await qb.getMany(); - return paginationHelper(items, take); -} - export const asVector = (embedding: number[], quote = false) => quote ? `'[${embedding.join(',')}]'` : `[${embedding.join(',')}]`; diff --git a/server/src/utils/file.ts b/server/src/utils/file.ts new file mode 100644 index 000000000..0a39bdc67 --- /dev/null +++ b/server/src/utils/file.ts @@ -0,0 +1,25 @@ +import { basename, extname } from 'node:path'; + +export function getFileNameWithoutExtension(path: string): string { + return basename(path, extname(path)); +} + +export function getLivePhotoMotionFilename(stillName: string, motionName: string) { + return getFileNameWithoutExtension(stillName) + extname(motionName); +} + +export enum CacheControl { + PRIVATE_WITH_CACHE = 'private_with_cache', + PRIVATE_WITHOUT_CACHE = 'private_without_cache', + NONE = 'none', +} + +export class ImmichFileResponse { + public readonly path!: string; + public readonly contentType!: string; + public readonly cacheControl!: CacheControl; + + constructor(response: ImmichFileResponse) { + Object.assign(this, response); + } +} diff --git a/server/src/infra/instrumentation.ts b/server/src/utils/instrumentation.ts similarity index 98% rename from server/src/infra/instrumentation.ts rename to server/src/utils/instrumentation.ts index a30f0523a..aa39a7728 100644 --- a/server/src/infra/instrumentation.ts +++ b/server/src/utils/instrumentation.ts @@ -14,8 +14,8 @@ import { OpenTelemetryModuleOptions } from 'nestjs-otel/lib/interfaces'; import { copyMetadataFromFunctionToFunction } from 'nestjs-otel/lib/opentelemetry.utils'; import { performance } from 'node:perf_hooks'; import { excludePaths } from 'src/config'; +import { serverVersion } from 'src/constants'; import { DecorateAll } from 'src/decorators'; -import { serverVersion } from 'src/domain/domain.constant'; let metricsEnabled = process.env.IMMICH_METRICS === 'true'; const hostMetrics = diff --git a/server/src/infra/logger.ts b/server/src/utils/logger.ts similarity index 100% rename from server/src/infra/logger.ts rename to server/src/utils/logger.ts diff --git a/server/src/domain/media/media.util.ts b/server/src/utils/media.ts similarity index 100% rename from server/src/domain/media/media.util.ts rename to server/src/utils/media.ts diff --git a/server/src/domain/domain.constant.spec.ts b/server/src/utils/mime-types.spec.ts similarity index 68% rename from server/src/domain/domain.constant.spec.ts rename to server/src/utils/mime-types.spec.ts index e8a1c7b72..96c1921ba 100644 --- a/server/src/domain/domain.constant.spec.ts +++ b/server/src/utils/mime-types.spec.ts @@ -1,4 +1,4 @@ -import { mimeTypes, Version, VersionType } from 'src/domain/domain.constant'; +import { mimeTypes } from 'src/utils/mime-types'; describe('mimeTypes', () => { for (const { mimetype, extension } of [ @@ -196,74 +196,3 @@ describe('mimeTypes', () => { } }); }); - -describe('Version', () => { - const tests = [ - { this: new Version(0, 0, 1), other: new Version(0, 0, 0), compare: 1, type: VersionType.PATCH }, - { this: new Version(0, 1, 0), other: new Version(0, 0, 0), compare: 1, type: VersionType.MINOR }, - { this: new Version(1, 0, 0), other: new Version(0, 0, 0), compare: 1, type: VersionType.MAJOR }, - { this: new Version(0, 0, 0), other: new Version(0, 0, 1), compare: -1, type: VersionType.PATCH }, - { this: new Version(0, 0, 0), other: new Version(0, 1, 0), compare: -1, type: VersionType.MINOR }, - { this: new Version(0, 0, 0), other: new Version(1, 0, 0), compare: -1, type: VersionType.MAJOR }, - { this: new Version(0, 0, 0), other: new Version(0, 0, 0), compare: 0, type: VersionType.EQUAL }, - { this: new Version(0, 0, 1), other: new Version(0, 0, 1), compare: 0, type: VersionType.EQUAL }, - { this: new Version(0, 1, 0), other: new Version(0, 1, 0), compare: 0, type: VersionType.EQUAL }, - { this: new Version(1, 0, 0), other: new Version(1, 0, 0), compare: 0, type: VersionType.EQUAL }, - { this: new Version(1, 0), other: new Version(1, 0, 0), compare: 0, type: VersionType.EQUAL }, - { this: new Version(1, 0), other: new Version(1, 0, 1), compare: -1, type: VersionType.PATCH }, - { this: new Version(1, 1), other: new Version(1, 0, 1), compare: 1, type: VersionType.MINOR }, - { this: new Version(1), other: new Version(1, 0, 0), compare: 0, type: VersionType.EQUAL }, - { this: new Version(1), other: new Version(1, 0, 1), compare: -1, type: VersionType.PATCH }, - ]; - - describe('isOlderThan', () => { - for (const { this: thisVersion, other: otherVersion, compare, type } of tests) { - const expected = compare < 0 ? type : VersionType.EQUAL; - it(`should return '${expected}' when comparing ${thisVersion} to ${otherVersion}`, () => { - expect(thisVersion.isOlderThan(otherVersion)).toEqual(expected); - }); - } - }); - - describe('isEqual', () => { - for (const { this: thisVersion, other: otherVersion, compare } of tests) { - const bool = compare === 0; - it(`should return ${bool} when comparing ${thisVersion} to ${otherVersion}`, () => { - expect(thisVersion.isEqual(otherVersion)).toEqual(bool); - }); - } - }); - - describe('isNewerThan', () => { - for (const { this: thisVersion, other: otherVersion, compare, type } of tests) { - const expected = compare > 0 ? type : VersionType.EQUAL; - it(`should return ${expected} when comparing ${thisVersion} to ${otherVersion}`, () => { - expect(thisVersion.isNewerThan(otherVersion)).toEqual(expected); - }); - } - }); - - describe('fromString', () => { - const tests = [ - { scenario: 'leading v', value: 'v1.72.2', expected: new Version(1, 72, 2) }, - { scenario: 'uppercase v', value: 'V1.72.2', expected: new Version(1, 72, 2) }, - { scenario: 'missing v', value: '1.72.2', expected: new Version(1, 72, 2) }, - { scenario: 'large patch', value: '1.72.123', expected: new Version(1, 72, 123) }, - { scenario: 'large minor', value: '1.123.0', expected: new Version(1, 123, 0) }, - { scenario: 'large major', value: '123.0.0', expected: new Version(123, 0, 0) }, - { scenario: 'major bump', value: 'v2.0.0', expected: new Version(2, 0, 0) }, - { scenario: 'has dash', value: '14.10-1', expected: new Version(14, 10, 1) }, - { scenario: 'missing patch', value: '14.10', expected: new Version(14, 10, 0) }, - { scenario: 'only major', value: '14', expected: new Version(14, 0, 0) }, - ]; - - for (const { scenario, value, expected } of tests) { - it(`should correctly parse ${scenario}`, () => { - const actual = Version.fromString(value); - expect(actual.major).toEqual(expected.major); - expect(actual.minor).toEqual(expected.minor); - expect(actual.patch).toEqual(expected.patch); - }); - } - }); -}); diff --git a/server/src/domain/domain.constant.ts b/server/src/utils/mime-types.ts similarity index 56% rename from server/src/domain/domain.constant.ts rename to server/src/utils/mime-types.ts index 29c4837b6..789fc6a1c 100644 --- a/server/src/domain/domain.constant.ts +++ b/server/src/utils/mime-types.ts @@ -1,97 +1,6 @@ -import { Duration } from 'luxon'; -import { readFileSync } from 'node:fs'; -import { extname, join } from 'node:path'; +import { extname } from 'node:path'; import { AssetType } from 'src/entities/asset.entity'; -export const AUDIT_LOG_MAX_DURATION = Duration.fromObject({ days: 100 }); -export const ONE_HOUR = Duration.fromObject({ hours: 1 }); - -export interface IVersion { - major: number; - minor: number; - patch: number; -} - -export enum VersionType { - EQUAL = 0, - PATCH = 1, - MINOR = 2, - MAJOR = 3, -} - -export class Version implements IVersion { - public readonly types = ['major', 'minor', 'patch'] as const; - - constructor( - public major: number, - public minor: number = 0, - public patch: number = 0, - ) {} - - toString() { - return `${this.major}.${this.minor}.${this.patch}`; - } - - toJSON() { - const { major, minor, patch } = this; - return { major, minor, patch }; - } - - static fromString(version: string): Version { - const regex = /v?(?\d+)(?:\.(?\d+))?(?:[.-](?\d+))?/i; - const matchResult = version.match(regex); - if (matchResult) { - const { major, minor = '0', patch = '0' } = matchResult.groups as { [K in keyof IVersion]: string }; - return new Version(Number(major), Number(minor), Number(patch)); - } else { - throw new Error(`Invalid version format: ${version}`); - } - } - - private compare(version: Version): [number, VersionType] { - for (const [i, key] of this.types.entries()) { - const diff = this[key] - version[key]; - if (diff !== 0) { - return [diff > 0 ? 1 : -1, (VersionType.MAJOR - i) as VersionType]; - } - } - - return [0, VersionType.EQUAL]; - } - - isOlderThan(version: Version): VersionType { - const [bool, type] = this.compare(version); - return bool < 0 ? type : VersionType.EQUAL; - } - - isEqual(version: Version): boolean { - const [bool] = this.compare(version); - return bool === 0; - } - - isNewerThan(version: Version): VersionType { - const [bool, type] = this.compare(version); - return bool > 0 ? type : VersionType.EQUAL; - } -} - -export const envName = (process.env.NODE_ENV || 'development').toUpperCase(); -export const isDev = process.env.NODE_ENV === 'development'; - -const { version } = JSON.parse(readFileSync('./package.json', 'utf8')); -export const serverVersion = Version.fromString(version); - -export const APP_MEDIA_LOCATION = process.env.IMMICH_MEDIA_LOCATION || './upload'; -export const WEB_ROOT = process.env.IMMICH_WEB_ROOT || '/usr/src/app/www'; - -const GEODATA_ROOT_PATH = process.env.IMMICH_REVERSE_GEOCODING_ROOT || '/usr/src/resources'; - -export const citiesFile = 'cities500.txt'; -export const geodataDatePath = join(GEODATA_ROOT_PATH, 'geodata-date.txt'); -export const geodataAdmin1Path = join(GEODATA_ROOT_PATH, 'admin1CodesASCII.txt'); -export const geodataAdmin2Path = join(GEODATA_ROOT_PATH, 'admin2Codes.txt'); -export const geodataCities500Path = join(GEODATA_ROOT_PATH, citiesFile); - const image: Record = { '.3fr': ['image/3fr', 'image/x-hasselblad-3fr'], '.ari': ['image/ari', 'image/x-arriflex-ari'], diff --git a/server/src/utils/misc.ts b/server/src/utils/misc.ts new file mode 100644 index 000000000..d664a904e --- /dev/null +++ b/server/src/utils/misc.ts @@ -0,0 +1,32 @@ +import { CLIP_MODEL_INFO } from 'src/constants'; +import { ImmichLogger } from 'src/utils/logger'; + +export const isConnectionAborted = (error: Error | any) => error.code === 'ECONNABORTED'; + +export const handlePromiseError = (promise: Promise, logger: ImmichLogger): void => { + promise.catch((error: Error | any) => logger.error(`Promise error: ${error}`, error?.stack)); +}; + +export interface OpenGraphTags { + title: string; + description: string; + imageUrl?: string; +} + +function cleanModelName(modelName: string): string { + const token = modelName.split('/').at(-1); + if (!token) { + throw new Error(`Invalid model name: ${modelName}`); + } + + return token.replaceAll(':', '_'); +} + +export function getCLIPModelInfo(modelName: string) { + const modelInfo = CLIP_MODEL_INFO[cleanModelName(modelName)]; + if (!modelInfo) { + throw new Error(`Unknown CLIP model: ${modelName}`); + } + + return modelInfo; +} diff --git a/server/src/utils/pagination.ts b/server/src/utils/pagination.ts new file mode 100644 index 000000000..dec1a9de0 --- /dev/null +++ b/server/src/utils/pagination.ts @@ -0,0 +1,79 @@ +import _ from 'lodash'; +import { FindManyOptions, ObjectLiteral, Repository, SelectQueryBuilder } from 'typeorm'; + +export interface PaginationOptions { + take: number; + skip?: number; +} + +export enum PaginationMode { + LIMIT_OFFSET = 'limit-offset', + SKIP_TAKE = 'skip-take', +} + +export interface PaginatedBuilderOptions { + take: number; + skip?: number; + mode?: PaginationMode; +} + +export interface PaginationResult { + items: T[]; + hasNextPage: boolean; +} + +export type Paginated = Promise>; + +export async function* usePagination( + pageSize: number, + getNextPage: (pagination: PaginationOptions) => PaginationResult | Paginated, +) { + let hasNextPage = true; + + for (let skip = 0; hasNextPage; skip += pageSize) { + const result = await getNextPage({ take: pageSize, skip }); + hasNextPage = result.hasNextPage; + yield result.items; + } +} + +function paginationHelper(items: Entity[], take: number): PaginationResult { + const hasNextPage = items.length > take; + items.splice(take); + + return { items, hasNextPage }; +} + +export async function paginate( + repository: Repository, + { take, skip }: PaginationOptions, + searchOptions?: FindManyOptions, +): Paginated { + const items = await repository.find( + _.omitBy( + { + ...searchOptions, + // Take one more item to check if there's a next page + take: take + 1, + skip, + }, + _.isUndefined, + ), + ); + + return paginationHelper(items, take); +} + +export async function paginatedBuilder( + qb: SelectQueryBuilder, + { take, skip, mode }: PaginatedBuilderOptions, +): Paginated { + if (mode === PaginationMode.LIMIT_OFFSET) { + qb.limit(take + 1).offset(skip); + } else { + qb.take(take + 1).skip(skip); + } + + const items = await qb.getMany(); + return paginationHelper(items, take); +} diff --git a/server/src/utils/set.ts b/server/src/utils/set.ts new file mode 100644 index 000000000..971d3f7e5 --- /dev/null +++ b/server/src/utils/set.ts @@ -0,0 +1,36 @@ +// NOTE: The following Set utils have been added here, to easily determine where they are used. +// They should be replaced with native Set operations, when they are added to the language. +// Proposal reference: https://github.com/tc39/proposal-set-methods + +export const setUnion = (...sets: Set[]): Set => { + const union = new Set(sets[0]); + for (const set of sets.slice(1)) { + for (const element of set) { + union.add(element); + } + } + return union; +}; + +export const setDifference = (setA: Set, ...sets: Set[]): Set => { + const difference = new Set(setA); + for (const set of sets) { + for (const element of set) { + difference.delete(element); + } + } + return difference; +}; + +export const setIsSuperset = (set: Set, subset: Set): boolean => { + for (const element of subset) { + if (!set.has(element)) { + return false; + } + } + return true; +}; + +export const setIsEqual = (setA: Set, setB: Set): boolean => { + return setA.size === setB.size && setIsSuperset(setA, setB); +}; diff --git a/server/src/infra/sql-generator/index.ts b/server/src/utils/sql.ts similarity index 90% rename from server/src/infra/sql-generator/index.ts rename to server/src/utils/sql.ts index 10730fc36..f98273806 100644 --- a/server/src/infra/sql-generator/index.ts +++ b/server/src/utils/sql.ts @@ -5,10 +5,10 @@ import { Test } from '@nestjs/testing'; import { TypeOrmModule } from '@nestjs/typeorm'; import { mkdir, rm, writeFile } from 'node:fs/promises'; import { join } from 'node:path'; +import { format } from 'sql-formatter'; +import { databaseConfig } from 'src/database.config'; import { GENERATE_SQL_KEY, GenerateSqlQueries } from 'src/decorators'; import { databaseEntities } from 'src/entities'; -import { databaseConfig } from 'src/infra/database.config'; -import { SqlLogger } from 'src/infra/sql-generator/sql.logger'; import { ISystemConfigRepository } from 'src/interfaces/system-config.repository'; import { AccessRepository } from 'src/repositories/access.repository'; import { AlbumRepository } from 'src/repositories/album.repository'; @@ -26,6 +26,30 @@ import { SystemMetadataRepository } from 'src/repositories/system-metadata.repos import { TagRepository } from 'src/repositories/tag.repository'; import { UserTokenRepository } from 'src/repositories/user-token.repository'; import { UserRepository } from 'src/repositories/user.repository'; +import { Logger } from 'typeorm'; + +export class SqlLogger implements Logger { + queries: string[] = []; + errors: Array<{ error: string | Error; query: string }> = []; + + clear() { + this.queries = []; + this.errors = []; + } + + logQuery(query: string) { + this.queries.push(format(query, { language: 'postgresql' })); + } + + logQueryError(error: string | Error, query: string) { + this.errors.push({ error, query }); + } + + logQuerySlow() {} + logSchemaBuild() {} + logMigration() {} + log() {} +} const reflector = new Reflector(); const repositories = [ @@ -178,7 +202,7 @@ class SqlGenerator { } } -new SqlGenerator({ targetDir: './src/infra/sql' }) +new SqlGenerator({ targetDir: './src/queries' }) .run() .then(() => { console.log('Done'); diff --git a/server/src/utils/version.spec.ts b/server/src/utils/version.spec.ts new file mode 100644 index 000000000..34c8abb41 --- /dev/null +++ b/server/src/utils/version.spec.ts @@ -0,0 +1,72 @@ +import { Version, VersionType } from 'src/utils/version'; + +describe('Version', () => { + const tests = [ + { this: new Version(0, 0, 1), other: new Version(0, 0, 0), compare: 1, type: VersionType.PATCH }, + { this: new Version(0, 1, 0), other: new Version(0, 0, 0), compare: 1, type: VersionType.MINOR }, + { this: new Version(1, 0, 0), other: new Version(0, 0, 0), compare: 1, type: VersionType.MAJOR }, + { this: new Version(0, 0, 0), other: new Version(0, 0, 1), compare: -1, type: VersionType.PATCH }, + { this: new Version(0, 0, 0), other: new Version(0, 1, 0), compare: -1, type: VersionType.MINOR }, + { this: new Version(0, 0, 0), other: new Version(1, 0, 0), compare: -1, type: VersionType.MAJOR }, + { this: new Version(0, 0, 0), other: new Version(0, 0, 0), compare: 0, type: VersionType.EQUAL }, + { this: new Version(0, 0, 1), other: new Version(0, 0, 1), compare: 0, type: VersionType.EQUAL }, + { this: new Version(0, 1, 0), other: new Version(0, 1, 0), compare: 0, type: VersionType.EQUAL }, + { this: new Version(1, 0, 0), other: new Version(1, 0, 0), compare: 0, type: VersionType.EQUAL }, + { this: new Version(1, 0), other: new Version(1, 0, 0), compare: 0, type: VersionType.EQUAL }, + { this: new Version(1, 0), other: new Version(1, 0, 1), compare: -1, type: VersionType.PATCH }, + { this: new Version(1, 1), other: new Version(1, 0, 1), compare: 1, type: VersionType.MINOR }, + { this: new Version(1), other: new Version(1, 0, 0), compare: 0, type: VersionType.EQUAL }, + { this: new Version(1), other: new Version(1, 0, 1), compare: -1, type: VersionType.PATCH }, + ]; + + describe('isOlderThan', () => { + for (const { this: thisVersion, other: otherVersion, compare, type } of tests) { + const expected = compare < 0 ? type : VersionType.EQUAL; + it(`should return '${expected}' when comparing ${thisVersion} to ${otherVersion}`, () => { + expect(thisVersion.isOlderThan(otherVersion)).toEqual(expected); + }); + } + }); + + describe('isEqual', () => { + for (const { this: thisVersion, other: otherVersion, compare } of tests) { + const bool = compare === 0; + it(`should return ${bool} when comparing ${thisVersion} to ${otherVersion}`, () => { + expect(thisVersion.isEqual(otherVersion)).toEqual(bool); + }); + } + }); + + describe('isNewerThan', () => { + for (const { this: thisVersion, other: otherVersion, compare, type } of tests) { + const expected = compare > 0 ? type : VersionType.EQUAL; + it(`should return ${expected} when comparing ${thisVersion} to ${otherVersion}`, () => { + expect(thisVersion.isNewerThan(otherVersion)).toEqual(expected); + }); + } + }); + + describe('fromString', () => { + const tests = [ + { scenario: 'leading v', value: 'v1.72.2', expected: new Version(1, 72, 2) }, + { scenario: 'uppercase v', value: 'V1.72.2', expected: new Version(1, 72, 2) }, + { scenario: 'missing v', value: '1.72.2', expected: new Version(1, 72, 2) }, + { scenario: 'large patch', value: '1.72.123', expected: new Version(1, 72, 123) }, + { scenario: 'large minor', value: '1.123.0', expected: new Version(1, 123, 0) }, + { scenario: 'large major', value: '123.0.0', expected: new Version(123, 0, 0) }, + { scenario: 'major bump', value: 'v2.0.0', expected: new Version(2, 0, 0) }, + { scenario: 'has dash', value: '14.10-1', expected: new Version(14, 10, 1) }, + { scenario: 'missing patch', value: '14.10', expected: new Version(14, 10, 0) }, + { scenario: 'only major', value: '14', expected: new Version(14, 0, 0) }, + ]; + + for (const { scenario, value, expected } of tests) { + it(`should correctly parse ${scenario}`, () => { + const actual = Version.fromString(value); + expect(actual.major).toEqual(expected.major); + expect(actual.minor).toEqual(expected.minor); + expect(actual.patch).toEqual(expected.patch); + }); + } + }); +}); diff --git a/server/src/utils/version.ts b/server/src/utils/version.ts new file mode 100644 index 000000000..6eca12eb4 --- /dev/null +++ b/server/src/utils/version.ts @@ -0,0 +1,64 @@ +export type IVersion = { major: number; minor: number; patch: number }; + +export enum VersionType { + EQUAL = 0, + PATCH = 1, + MINOR = 2, + MAJOR = 3, +} + +export class Version implements IVersion { + public readonly types = ['major', 'minor', 'patch'] as const; + + constructor( + public major: number, + public minor: number = 0, + public patch: number = 0, + ) {} + + toString() { + return `${this.major}.${this.minor}.${this.patch}`; + } + + toJSON() { + const { major, minor, patch } = this; + return { major, minor, patch }; + } + + static fromString(version: string): Version { + const regex = /v?(?\d+)(?:\.(?\d+))?(?:[.-](?\d+))?/i; + const matchResult = version.match(regex); + if (matchResult) { + const { major, minor = '0', patch = '0' } = matchResult.groups as { [K in keyof IVersion]: string }; + return new Version(Number(major), Number(minor), Number(patch)); + } else { + throw new Error(`Invalid version format: ${version}`); + } + } + + private compare(version: Version): [number, VersionType] { + for (const [i, key] of this.types.entries()) { + const diff = this[key] - version[key]; + if (diff !== 0) { + return [diff > 0 ? 1 : -1, (VersionType.MAJOR - i) as VersionType]; + } + } + + return [0, VersionType.EQUAL]; + } + + isOlderThan(version: Version): VersionType { + const [bool, type] = this.compare(version); + return bool < 0 ? type : VersionType.EQUAL; + } + + isEqual(version: Version): boolean { + const [bool] = this.compare(version); + return bool === 0; + } + + isNewerThan(version: Version): VersionType { + const [bool, type] = this.compare(version); + return bool > 0 ? type : VersionType.EQUAL; + } +} diff --git a/server/test/fixtures/library.stub.ts b/server/test/fixtures/library.stub.ts index b3fa4b7f0..dde250a7a 100644 --- a/server/test/fixtures/library.stub.ts +++ b/server/test/fixtures/library.stub.ts @@ -1,6 +1,6 @@ import { join } from 'node:path'; +import { APP_MEDIA_LOCATION } from 'src/constants'; import { THUMBNAIL_DIR } from 'src/cores/storage.core'; -import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant'; import { LibraryEntity, LibraryType } from 'src/entities/library.entity'; import { userStub } from 'test/fixtures/user.stub'; diff --git a/server/test/repositories/database.repository.mock.ts b/server/test/repositories/database.repository.mock.ts index 82abe16a8..43a2dfb79 100644 --- a/server/test/repositories/database.repository.mock.ts +++ b/server/test/repositories/database.repository.mock.ts @@ -1,5 +1,5 @@ -import { Version } from 'src/domain/domain.constant'; import { IDatabaseRepository } from 'src/interfaces/database.repository'; +import { Version } from 'src/utils/version'; export const newDatabaseRepositoryMock = (): jest.Mocked => { return { diff --git a/server/test/utils.ts b/server/test/utils.ts index f44f6fe17..4feca9946 100644 --- a/server/test/utils.ts +++ b/server/test/utils.ts @@ -10,9 +10,8 @@ import { ApiModule } from 'src/apps/api.module'; import { ApiService } from 'src/apps/api.service'; import { AppModule, AppTestModule } from 'src/apps/app.module'; import { MicroservicesService } from 'src/apps/microservices.service'; -import { QueueName } from 'src/domain/job/job.constants'; -import { dataSource } from 'src/infra/database.config'; -import { IJobRepository, JobItem, JobItemHandler } from 'src/interfaces/job.repository'; +import { dataSource } from 'src/database.config'; +import { IJobRepository, JobItem, JobItemHandler, QueueName } from 'src/interfaces/job.repository'; import { IMediaRepository } from 'src/interfaces/media.repository'; import { StorageEventType } from 'src/interfaces/storage.repository'; import { MediaRepository } from 'src/repositories/media.repository'; From 44ed1f091957f061c837767cc1d5dafc36d592e5 Mon Sep 17 00:00:00 2001 From: Alex Date: Thu, 21 Mar 2024 00:18:38 -0500 Subject: [PATCH 046/152] fix(web): asset-grid padding/margin left fix (#8125) use media query for grid padding/margin size --- web/src/lib/components/photos-page/asset-grid.svelte | 2 +- .../shared-components/navigation-bar/navigation-bar.svelte | 2 +- web/src/routes/(user)/people/[personId]/+page.svelte | 2 +- web/tailwind.config.cjs | 3 +++ 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/web/src/lib/components/photos-page/asset-grid.svelte b/web/src/lib/components/photos-page/asset-grid.svelte index 5892442df..541673764 100644 --- a/web/src/lib/components/photos-page/asset-grid.svelte +++ b/web/src/lib/components/photos-page/asset-grid.svelte @@ -380,7 +380,7 @@
-