refactor(server)*: tsconfigs (#2689)

* refactor(server): tsconfigs

* chore: dummy commit

* fix: start.sh

* chore: restore original entry scripts
This commit is contained in:
Jason Rasmussen
2023-06-08 11:01:07 -04:00
committed by GitHub
parent a2130aa6c5
commit 8ebac41318
465 changed files with 209 additions and 332 deletions

View File

@@ -0,0 +1,54 @@
import { AssetEntity, AssetType } from '@app/infra/entities';
import { Paginated, PaginationOptions } from '../domain.util';
export interface AssetSearchOptions {
isVisible?: boolean;
type?: AssetType;
}
export interface LivePhotoSearchOptions {
ownerId: string;
livePhotoCID: string;
otherAssetId: string;
type: AssetType;
}
export interface MapMarkerSearchOptions {
isFavorite?: boolean;
fileCreatedBefore?: Date;
fileCreatedAfter?: Date;
}
export interface MapMarker {
id: string;
lat: number;
lon: number;
}
export enum WithoutProperty {
THUMBNAIL = 'thumbnail',
ENCODED_VIDEO = 'encoded-video',
EXIF = 'exif',
CLIP_ENCODING = 'clip-embedding',
OBJECT_TAGS = 'object-tags',
FACES = 'faces',
SIDECAR = 'sidecar',
}
export enum WithProperty {
SIDECAR = 'sidecar',
}
export const IAssetRepository = 'IAssetRepository';
export interface IAssetRepository {
getByIds(ids: string[]): Promise<AssetEntity[]>;
getWithout(pagination: PaginationOptions, property: WithoutProperty): Paginated<AssetEntity>;
getWith(pagination: PaginationOptions, property: WithProperty): Paginated<AssetEntity>;
getFirstAssetForAlbumId(albumId: string): Promise<AssetEntity | null>;
deleteAll(ownerId: string): Promise<void>;
getAll(pagination: PaginationOptions, options?: AssetSearchOptions): Paginated<AssetEntity>;
save(asset: Partial<AssetEntity>): Promise<AssetEntity>;
findLivePhotoMatch(options: LivePhotoSearchOptions): Promise<AssetEntity | null>;
getMapMarkers(ownerId: string, options?: MapMarkerSearchOptions): Promise<MapMarker[]>;
}

View File

@@ -0,0 +1,41 @@
import { assetEntityStub, authStub, newAssetRepositoryMock } from '@test';
import { AssetService, IAssetRepository } from '.';
describe(AssetService.name, () => {
let sut: AssetService;
let assetMock: jest.Mocked<IAssetRepository>;
it('should work', () => {
expect(sut).toBeDefined();
});
beforeEach(async () => {
assetMock = newAssetRepositoryMock();
sut = new AssetService(assetMock);
});
describe('get map markers', () => {
it('should get geo information of assets', async () => {
assetMock.getMapMarkers.mockResolvedValue(
[assetEntityStub.withLocation].map((asset) => ({
id: asset.id,
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
lat: asset.exifInfo!.latitude!,
/* eslint-disable-next-line @typescript-eslint/no-non-null-assertion */
lon: asset.exifInfo!.longitude!,
})),
);
const markers = await sut.getMapMarkers(authStub.user1, {});
expect(markers).toHaveLength(1);
expect(markers[0]).toEqual({
id: assetEntityStub.withLocation.id,
lat: 100,
lon: 100,
});
});
});
});

View File

@@ -0,0 +1,13 @@
import { Inject } from '@nestjs/common';
import { AuthUserDto } from '../auth';
import { IAssetRepository } from './asset.repository';
import { MapMarkerDto } from './dto/map-marker.dto';
import { MapMarkerResponseDto } from './response-dto';
export class AssetService {
constructor(@Inject(IAssetRepository) private assetRepository: IAssetRepository) {}
getMapMarkers(authUser: AuthUserDto, options: MapMarkerDto): Promise<MapMarkerResponseDto[]> {
return this.assetRepository.getMapMarkers(authUser.id, options);
}
}

View File

@@ -0,0 +1,6 @@
import { ValidateUUID } from '@app/immich/decorators/validate-uuid.decorator';
export class AssetIdsDto {
@ValidateUUID({ each: true })
assetIds!: string[];
}

View File

@@ -0,0 +1,2 @@
export * from './asset-ids.dto';
export * from './map-marker.dto';

View File

@@ -0,0 +1,22 @@
import { ApiProperty } from '@nestjs/swagger';
import { Transform, Type } from 'class-transformer';
import { IsBoolean, IsDate, IsOptional } from 'class-validator';
import { toBoolean } from '@app/immich/utils/transform.util';
export class MapMarkerDto {
@ApiProperty()
@IsOptional()
@IsBoolean()
@Transform(toBoolean)
isFavorite?: boolean;
@IsOptional()
@IsDate()
@Type(() => Date)
fileCreatedAfter?: Date;
@IsOptional()
@IsDate()
@Type(() => Date)
fileCreatedBefore?: Date;
}

View File

@@ -0,0 +1,4 @@
export * from './asset.repository';
export * from './asset.service';
export * from './dto';
export * from './response-dto';

View File

@@ -0,0 +1,11 @@
export enum AssetIdErrorReason {
DUPLICATE = 'duplicate',
NO_PERMISSION = 'no_permission',
NOT_FOUND = 'not_found',
}
export class AssetIdsResponseDto {
assetId!: string;
success!: boolean;
error?: AssetIdErrorReason;
}

View File

@@ -0,0 +1,85 @@
import { AssetEntity, AssetType } from '@app/infra/entities';
import { ApiProperty } from '@nestjs/swagger';
import { mapFace, PersonResponseDto } from '../../person';
import { mapTag, TagResponseDto } from '../../tag';
import { ExifResponseDto, mapExif } from './exif-response.dto';
import { mapSmartInfo, SmartInfoResponseDto } from './smart-info-response.dto';
export class AssetResponseDto {
id!: string;
deviceAssetId!: string;
ownerId!: string;
deviceId!: string;
@ApiProperty({ enumName: 'AssetTypeEnum', enum: AssetType })
type!: AssetType;
originalPath!: string;
originalFileName!: string;
resized!: boolean;
fileCreatedAt!: Date;
fileModifiedAt!: Date;
updatedAt!: Date;
isFavorite!: boolean;
isArchived!: boolean;
mimeType!: string | null;
duration!: string;
exifInfo?: ExifResponseDto;
smartInfo?: SmartInfoResponseDto;
livePhotoVideoId?: string | null;
tags?: TagResponseDto[];
people?: PersonResponseDto[];
/**base64 encoded sha1 hash */
checksum!: string;
}
export function mapAsset(entity: AssetEntity): AssetResponseDto {
return {
id: entity.id,
deviceAssetId: entity.deviceAssetId,
ownerId: entity.ownerId,
deviceId: entity.deviceId,
type: entity.type,
originalPath: entity.originalPath,
originalFileName: entity.originalFileName,
resized: !!entity.resizePath,
fileCreatedAt: entity.fileCreatedAt,
fileModifiedAt: entity.fileModifiedAt,
updatedAt: entity.updatedAt,
isFavorite: entity.isFavorite,
isArchived: entity.isArchived,
mimeType: entity.mimeType,
duration: entity.duration ?? '0:00:00.00000',
exifInfo: entity.exifInfo ? mapExif(entity.exifInfo) : undefined,
smartInfo: entity.smartInfo ? mapSmartInfo(entity.smartInfo) : undefined,
livePhotoVideoId: entity.livePhotoVideoId,
tags: entity.tags?.map(mapTag),
people: entity.faces?.map(mapFace),
checksum: entity.checksum.toString('base64'),
};
}
export function mapAssetWithoutExif(entity: AssetEntity): AssetResponseDto {
return {
id: entity.id,
deviceAssetId: entity.deviceAssetId,
ownerId: entity.ownerId,
deviceId: entity.deviceId,
type: entity.type,
originalPath: entity.originalPath,
originalFileName: entity.originalFileName,
resized: !!entity.resizePath,
fileCreatedAt: entity.fileCreatedAt,
fileModifiedAt: entity.fileModifiedAt,
updatedAt: entity.updatedAt,
isFavorite: entity.isFavorite,
isArchived: entity.isArchived,
mimeType: entity.mimeType,
duration: entity.duration ?? '0:00:00.00000',
exifInfo: undefined,
smartInfo: entity.smartInfo ? mapSmartInfo(entity.smartInfo) : undefined,
livePhotoVideoId: entity.livePhotoVideoId,
tags: entity.tags?.map(mapTag),
people: entity.faces?.map(mapFace),
checksum: entity.checksum.toString('base64'),
};
}

View File

@@ -0,0 +1,52 @@
import { ExifEntity } from '@app/infra/entities';
import { ApiProperty } from '@nestjs/swagger';
export class ExifResponseDto {
make?: string | null = null;
model?: string | null = null;
exifImageWidth?: number | null = null;
exifImageHeight?: number | null = null;
@ApiProperty({ type: 'integer', format: 'int64' })
fileSizeInByte?: number | null = null;
orientation?: string | null = null;
dateTimeOriginal?: Date | null = null;
modifyDate?: Date | null = null;
timeZone?: string | null = null;
lensModel?: string | null = null;
fNumber?: number | null = null;
focalLength?: number | null = null;
iso?: number | null = null;
exposureTime?: string | null = null;
latitude?: number | null = null;
longitude?: number | null = null;
city?: string | null = null;
state?: string | null = null;
country?: string | null = null;
description?: string | null = null;
}
export function mapExif(entity: ExifEntity): ExifResponseDto {
return {
make: entity.make,
model: entity.model,
exifImageWidth: entity.exifImageWidth,
exifImageHeight: entity.exifImageHeight,
fileSizeInByte: entity.fileSizeInByte ? parseInt(entity.fileSizeInByte.toString()) : null,
orientation: entity.orientation,
dateTimeOriginal: entity.dateTimeOriginal,
modifyDate: entity.modifyDate,
timeZone: entity.timeZone,
lensModel: entity.lensModel,
fNumber: entity.fNumber,
focalLength: entity.focalLength,
iso: entity.iso,
exposureTime: entity.exposureTime,
latitude: entity.latitude,
longitude: entity.longitude,
city: entity.city,
state: entity.state,
country: entity.country,
description: entity.description,
};
}

View File

@@ -0,0 +1,5 @@
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';

View File

@@ -0,0 +1,12 @@
import { ApiProperty } from '@nestjs/swagger';
export class MapMarkerResponseDto {
@ApiProperty()
id!: string;
@ApiProperty({ format: 'double' })
lat!: number;
@ApiProperty({ format: 'double' })
lon!: number;
}

View File

@@ -0,0 +1,13 @@
import { SmartInfoEntity } from '@app/infra/entities';
export class SmartInfoResponseDto {
tags?: string[] | null;
objects?: string[] | null;
}
export function mapSmartInfo(entity: SmartInfoEntity): SmartInfoResponseDto {
return {
tags: entity.tags,
objects: entity.objects,
};
}