mirror of
https://github.com/immich-app/immich
synced 2025-06-08 06:10:58 +00:00
refactor: database types (#17468)
This commit is contained in:
parent
ac65d46ec6
commit
4794eeca88
@ -1,5 +1,6 @@
|
||||
import { UserMetadataEntity } from 'src/entities/user-metadata.entity';
|
||||
import { AssetStatus, AssetType, Permission, UserStatus } from 'src/enum';
|
||||
import { AssetStatus, AssetType, MemoryType, Permission, UserStatus } from 'src/enum';
|
||||
import { OnThisDayData } from 'src/types';
|
||||
|
||||
export type AuthUser = {
|
||||
id: string;
|
||||
@ -38,6 +39,31 @@ export type ApiKey = {
|
||||
permissions: Permission[];
|
||||
};
|
||||
|
||||
export type Tag = {
|
||||
id: string;
|
||||
value: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
color: string | null;
|
||||
parentId: string | null;
|
||||
};
|
||||
|
||||
export type Memory = {
|
||||
id: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
deletedAt: Date | null;
|
||||
memoryAt: Date;
|
||||
seenAt: Date | null;
|
||||
showAt: Date | null;
|
||||
hideAt: Date | null;
|
||||
type: MemoryType;
|
||||
data: OnThisDayData;
|
||||
ownerId: string;
|
||||
isSaved: boolean;
|
||||
assets: Asset[];
|
||||
};
|
||||
|
||||
export type User = {
|
||||
id: string;
|
||||
name: string;
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsEnum, IsInt, IsObject, IsPositive, ValidateNested } from 'class-validator';
|
||||
import { Memory } from 'src/database';
|
||||
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { MemoryType } from 'src/enum';
|
||||
import { MemoryItem } from 'src/types';
|
||||
import { Optional, ValidateBoolean, ValidateDate, ValidateUUID } from 'src/validation';
|
||||
|
||||
class MemoryBaseDto {
|
||||
@ -89,7 +89,7 @@ export class MemoryResponseDto {
|
||||
assets!: AssetResponseDto[];
|
||||
}
|
||||
|
||||
export const mapMemory = (entity: MemoryItem, auth: AuthDto): MemoryResponseDto => {
|
||||
export const mapMemory = (entity: Memory, auth: AuthDto): MemoryResponseDto => {
|
||||
return {
|
||||
id: entity.id,
|
||||
createdAt: entity.createdAt,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsHexColor, IsNotEmpty, IsString } from 'class-validator';
|
||||
import { TagItem } from 'src/types';
|
||||
import { Tag } from 'src/database';
|
||||
import { Optional, ValidateHexColor, ValidateUUID } from 'src/validation';
|
||||
|
||||
export class TagCreateDto {
|
||||
@ -51,7 +51,7 @@ export class TagResponseDto {
|
||||
color?: string;
|
||||
}
|
||||
|
||||
export function mapTag(entity: TagItem): TagResponseDto {
|
||||
export function mapTag(entity: Tag): TagResponseDto {
|
||||
return {
|
||||
id: entity.id,
|
||||
parentId: entity.parentId ?? undefined,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { DeduplicateJoinsPlugin, ExpressionBuilder, Kysely, SelectQueryBuilder, sql } from 'kysely';
|
||||
import { jsonArrayFrom, jsonObjectFrom } from 'kysely/helpers/postgres';
|
||||
import { Tag } from 'src/database';
|
||||
import { DB } from 'src/db';
|
||||
import { AlbumEntity } from 'src/entities/album.entity';
|
||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||
@ -12,7 +13,6 @@ import { UserEntity } from 'src/entities/user.entity';
|
||||
import { AssetFileType, AssetStatus, AssetType } from 'src/enum';
|
||||
import { TimeBucketSize } from 'src/repositories/asset.repository';
|
||||
import { AssetSearchBuilderOptions } from 'src/repositories/search.repository';
|
||||
import { TagItem } from 'src/types';
|
||||
import { anyUuid, asUuid } from 'src/utils/database';
|
||||
|
||||
export const ASSET_CHECKSUM_CONSTRAINT = 'UQ_assets_owner_checksum';
|
||||
@ -49,7 +49,7 @@ export class AssetEntity {
|
||||
originalFileName!: string;
|
||||
sidecarPath!: string | null;
|
||||
exifInfo?: ExifEntity;
|
||||
tags?: TagItem[];
|
||||
tags?: Tag[];
|
||||
sharedLinks!: SharedLinkEntity[];
|
||||
albums?: AlbumEntity[];
|
||||
faces!: AssetFaceEntity[];
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { BadRequestException, Injectable } from '@nestjs/common';
|
||||
import { ApiKey } from 'src/database';
|
||||
import { APIKeyCreateDto, APIKeyCreateResponseDto, APIKeyResponseDto, APIKeyUpdateDto } from 'src/dtos/api-key.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { Permission } from 'src/enum';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { ApiKeyItem } from 'src/types';
|
||||
import { isGranted } from 'src/utils/access';
|
||||
|
||||
@Injectable()
|
||||
@ -58,7 +58,7 @@ export class ApiKeyService extends BaseService {
|
||||
return keys.map((key) => this.map(key));
|
||||
}
|
||||
|
||||
private map(entity: ApiKeyItem): APIKeyResponseDto {
|
||||
private map(entity: ApiKey): APIKeyResponseDto {
|
||||
return {
|
||||
id: entity.id,
|
||||
name: entity.name,
|
||||
|
@ -14,8 +14,6 @@ import {
|
||||
VideoCodec,
|
||||
} from 'src/enum';
|
||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||
import { SearchRepository } from 'src/repositories/search.repository';
|
||||
import { SessionRepository } from 'src/repositories/session.repository';
|
||||
|
||||
@ -24,8 +22,6 @@ export type DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T
|
||||
export type RepositoryInterface<T extends object> = Pick<T, keyof T>;
|
||||
|
||||
type IActivityRepository = RepositoryInterface<ActivityRepository>;
|
||||
type IApiKeyRepository = RepositoryInterface<ApiKeyRepository>;
|
||||
type IMemoryRepository = RepositoryInterface<MemoryRepository>;
|
||||
type ISearchRepository = RepositoryInterface<SearchRepository>;
|
||||
type ISessionRepository = RepositoryInterface<SessionRepository>;
|
||||
|
||||
@ -35,26 +31,8 @@ export type ActivityItem =
|
||||
|
||||
export type SearchPlacesItem = Awaited<ReturnType<ISearchRepository['searchPlaces']>>[0];
|
||||
|
||||
export type ApiKeyItem =
|
||||
| Awaited<ReturnType<IApiKeyRepository['create']>>
|
||||
| NonNullable<Awaited<ReturnType<IApiKeyRepository['getById']>>>
|
||||
| Awaited<ReturnType<IApiKeyRepository['getByUserId']>>[0];
|
||||
|
||||
export type MemoryItem =
|
||||
| Awaited<ReturnType<IMemoryRepository['create']>>
|
||||
| Awaited<ReturnType<IMemoryRepository['search']>>[0];
|
||||
|
||||
export type SessionItem = Awaited<ReturnType<ISessionRepository['getByUserId']>>[0];
|
||||
|
||||
export type TagItem = {
|
||||
id: string;
|
||||
value: string;
|
||||
createdAt: Date;
|
||||
updatedAt: Date;
|
||||
color: string | null;
|
||||
parentId: string | null;
|
||||
};
|
||||
|
||||
export interface CropOptions {
|
||||
top: number;
|
||||
left: number;
|
||||
|
@ -1,15 +1,15 @@
|
||||
import { Tag } from 'src/database';
|
||||
import { TagRepository } from 'src/repositories/tag.repository';
|
||||
import { TagItem } from 'src/types';
|
||||
|
||||
type UpsertRequest = { userId: string; tags: string[] };
|
||||
export const upsertTags = async (repository: TagRepository, { userId, tags }: UpsertRequest) => {
|
||||
tags = [...new Set(tags)];
|
||||
|
||||
const results: TagItem[] = [];
|
||||
const results: Tag[] = [];
|
||||
|
||||
for (const tag of tags) {
|
||||
const parts = tag.split('/').filter(Boolean);
|
||||
let parent: TagItem | undefined;
|
||||
let parent: Tag | undefined;
|
||||
|
||||
for (const part of parts) {
|
||||
const value = parent ? `${parent.value}/${part}` : part;
|
||||
|
6
server/test/fixtures/tag.stub.ts
vendored
6
server/test/fixtures/tag.stub.ts
vendored
@ -1,7 +1,7 @@
|
||||
import { Tag } from 'src/database';
|
||||
import { TagResponseDto } from 'src/dtos/tag.dto';
|
||||
import { TagItem } from 'src/types';
|
||||
|
||||
const parent = Object.freeze<TagItem>({
|
||||
const parent = Object.freeze<Tag>({
|
||||
id: 'tag-parent',
|
||||
createdAt: new Date('2021-01-01T00:00:00Z'),
|
||||
updatedAt: new Date('2021-01-01T00:00:00Z'),
|
||||
@ -10,7 +10,7 @@ const parent = Object.freeze<TagItem>({
|
||||
parentId: null,
|
||||
});
|
||||
|
||||
const child = Object.freeze<TagItem>({
|
||||
const child = Object.freeze<Tag>({
|
||||
id: 'tag-child',
|
||||
createdAt: new Date('2021-01-01T00:00:00Z'),
|
||||
updatedAt: new Date('2021-01-01T00:00:00Z'),
|
||||
|
@ -5,6 +5,7 @@ import {
|
||||
AuthApiKey,
|
||||
AuthUser,
|
||||
Library,
|
||||
Memory,
|
||||
Partner,
|
||||
SidecarWriteAsset,
|
||||
User,
|
||||
@ -12,7 +13,7 @@ import {
|
||||
} from 'src/database';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { AssetStatus, AssetType, MemoryType, Permission, UserStatus } from 'src/enum';
|
||||
import { ActivityItem, MemoryItem, OnThisDayData } from 'src/types';
|
||||
import { ActivityItem, OnThisDayData } from 'src/types';
|
||||
|
||||
export const newUuid = () => randomUUID() as string;
|
||||
export const newUuids = () =>
|
||||
@ -196,7 +197,7 @@ const libraryFactory = (library: Partial<Library> = {}) => ({
|
||||
...library,
|
||||
});
|
||||
|
||||
const memoryFactory = (memory: Partial<MemoryItem> = {}) => ({
|
||||
const memoryFactory = (memory: Partial<Memory> = {}) => ({
|
||||
id: newUuid(),
|
||||
createdAt: newDate(),
|
||||
updatedAt: newDate(),
|
||||
|
Loading…
x
Reference in New Issue
Block a user