mirror of
https://github.com/immich-app/immich.git
synced 2024-11-15 09:59:00 -07:00
chore(server): use absolute import paths (#8080)
update server to use absolute import paths
This commit is contained in:
parent
591a641d8d
commit
30f499cf2e
30
.vscode/settings.json
vendored
Normal file
30
.vscode/settings.json
vendored
Normal file
@ -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"
|
||||
],
|
||||
}
|
@ -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.' }] }],
|
||||
},
|
||||
};
|
||||
|
@ -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 = {
|
||||
|
@ -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) => {
|
||||
|
@ -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,
|
||||
|
@ -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 = {
|
||||
|
@ -16,9 +16,7 @@
|
||||
],
|
||||
"coverageDirectory": "./coverage",
|
||||
"moduleNameMapper": {
|
||||
"^@test(|/.*)$": "<rootDir>/test/$1",
|
||||
"^@app/immich(|/.*)$": "<rootDir>/src/immich/$1",
|
||||
"^@app/infra(|/.*)$": "<rootDir>/src/infra/$1",
|
||||
"^@app/domain(|/.*)$": "<rootDir>/src/domain/$1"
|
||||
"^test(|/.*)$": "<rootDir>/test/$1",
|
||||
"^src(|/.*)$": "<rootDir>/src/$1"
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -155,16 +155,14 @@
|
||||
"./src/domain/": {
|
||||
"branches": 75,
|
||||
"functions": 80,
|
||||
"lines": 90,
|
||||
"statements": 90
|
||||
"lines": 85,
|
||||
"statements": 85
|
||||
}
|
||||
},
|
||||
"testEnvironment": "node",
|
||||
"moduleNameMapper": {
|
||||
"^@test(|/.*)$": "<rootDir>/test/$1",
|
||||
"^@app/immich(|/.*)$": "<rootDir>/src/immich/$1",
|
||||
"^@app/infra(|/.*)$": "<rootDir>/src/infra/$1",
|
||||
"^@app/domain(|/.*)$": "<rootDir>/src/domain/$1"
|
||||
"^test(|/.*)$": "<rootDir>/test/$1",
|
||||
"^src(|/.*)$": "<rootDir>/src/$1"
|
||||
},
|
||||
"globalSetup": "<rootDir>/test/global-setup.js"
|
||||
},
|
||||
|
@ -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',
|
||||
|
@ -1 +0,0 @@
|
||||
export * from './access.core';
|
@ -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',
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './activity.dto';
|
||||
export * from './activity.service';
|
@ -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', () => {
|
||||
|
@ -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;
|
||||
|
@ -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<IAlbumRepository>;
|
||||
let assetMock: jest.Mocked<IAssetRepository>;
|
||||
let jobMock: jest.Mocked<IJobRepository>;
|
||||
let userMock: jest.Mocked<IUserRepository>;
|
||||
|
||||
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', () => {
|
||||
|
@ -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);
|
||||
|
@ -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 })
|
||||
|
@ -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()
|
||||
|
@ -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()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ValidateBoolean } from '../../domain.util';
|
||||
import { ValidateBoolean } from 'src/domain/domain.util';
|
||||
|
||||
export class AlbumInfoDto {
|
||||
@ValidateBoolean({ optional: true })
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ValidateBoolean, ValidateUUID } from '../../domain.util';
|
||||
import { ValidateBoolean, ValidateUUID } from 'src/domain/domain.util';
|
||||
|
||||
export class GetAlbumsDto {
|
||||
@ValidateBoolean({ optional: true })
|
||||
|
@ -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';
|
@ -1,3 +0,0 @@
|
||||
export * from './album-response.dto';
|
||||
export * from './album.service';
|
||||
export * from './dto';
|
@ -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()
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './api-key.dto';
|
||||
export * from './api-key.service';
|
@ -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,
|
||||
|
@ -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',
|
||||
|
@ -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 })
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ValidateUUID } from '../../domain.util';
|
||||
import { ValidateUUID } from 'src/domain/domain.util';
|
||||
|
||||
export class UpdateStackParentDto {
|
||||
@ValidateUUID()
|
||||
|
@ -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 })
|
||||
|
@ -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()
|
||||
|
@ -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';
|
@ -1,4 +1,4 @@
|
||||
import { ValidateBoolean, ValidateDate } from '../../domain.util';
|
||||
import { ValidateBoolean, ValidateDate } from 'src/domain/domain.util';
|
||||
|
||||
export class MapMarkerDto {
|
||||
@ValidateBoolean({ optional: true })
|
||||
|
@ -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()
|
||||
|
@ -1,3 +0,0 @@
|
||||
export * from './asset.service';
|
||||
export * from './dto';
|
||||
export * from './response-dto';
|
@ -1,4 +1,4 @@
|
||||
import { ValidateUUID } from '../../domain.util';
|
||||
import { ValidateUUID } from 'src/domain/domain.util';
|
||||
|
||||
/** @deprecated Use `BulkIdResponseDto` instead */
|
||||
export enum AssetIdErrorReason {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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';
|
@ -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;
|
||||
|
@ -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 });
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './audit.dto';
|
||||
export * from './audit.service';
|
@ -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;
|
||||
|
@ -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');
|
||||
|
||||
|
@ -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;
|
||||
|
@ -1,3 +0,0 @@
|
||||
export * from './auth.constant';
|
||||
export * from './auth.dto';
|
||||
export * from './auth.service';
|
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -1 +0,0 @@
|
||||
export * from './database.service';
|
@ -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(),
|
||||
|
@ -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 [
|
||||
|
@ -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 });
|
||||
|
@ -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,
|
||||
|
@ -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',
|
||||
|
@ -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 })
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './download.dto';
|
||||
export * from './download.service';
|
@ -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';
|
@ -1,4 +0,0 @@
|
||||
export * from './job.constants';
|
||||
export * from './job.dto';
|
||||
export * from './job.interface';
|
||||
export * from './job.service';
|
@ -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()
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './library.dto';
|
||||
export * from './library.service';
|
@ -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)
|
||||
|
@ -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<IAssetRepository>;
|
||||
let configMock: jest.Mocked<ISystemConfigRepository>;
|
||||
let cryptoMock: jest.Mocked<ICryptoRepository>;
|
||||
@ -49,7 +43,6 @@ describe(LibraryService.name, () => {
|
||||
let databaseMock: jest.Mocked<IDatabaseRepository>;
|
||||
|
||||
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);
|
||||
});
|
||||
|
@ -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<string, () => Promise<void>> = {};
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './media.constant';
|
||||
export * from './media.service';
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -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) {}
|
||||
|
@ -1 +0,0 @@
|
||||
export * from './metadata.service';
|
@ -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<IAlbumRepository>;
|
||||
|
@ -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<keyof Tags> = [
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './partner.dto';
|
||||
export * from './partner.service';
|
@ -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()
|
||||
|
@ -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: <PartnerResponseDto>{
|
||||
|
@ -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 {
|
||||
|
@ -1,2 +0,0 @@
|
||||
export * from './person.dto';
|
||||
export * from './person.service';
|
@ -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 {
|
||||
/**
|
||||
|
@ -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',
|
||||
|
@ -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);
|
||||
|
@ -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';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { AlbumEntity } from '@app/infra/entities';
|
||||
import { AlbumEntity } from 'src/infra/entities/album.entity';
|
||||
|
||||
export const IAlbumRepository = 'IAlbumRepository';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { APIKeyEntity } from '@app/infra/entities';
|
||||
import { APIKeyEntity } from 'src/infra/entities/api-key.entity';
|
||||
|
||||
export const IKeyRepository = 'IKeyRepository';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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<AssetType, number>;
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Version } from '../domain.constant';
|
||||
import { Version } from 'src/domain/domain.constant';
|
||||
|
||||
export enum DatabaseExtension {
|
||||
CUBE = 'cube',
|
||||
|
@ -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';
|
@ -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;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user