mirror of
https://github.com/immich-app/immich.git
synced 2025-12-21 09:15:44 +03:00
refactor(server): use kysely (#12857)
This commit is contained in:
@@ -1,10 +1,9 @@
|
||||
import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity';
|
||||
import { Insertable, Updateable } from 'kysely';
|
||||
import { AssetFiles, AssetJobStatus, Assets, Exif } from 'src/db';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { ExifEntity } from 'src/entities/exif.entity';
|
||||
import { AssetFileType, AssetOrder, AssetStatus, AssetType } from 'src/enum';
|
||||
import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.interface';
|
||||
import { Paginated, PaginationOptions } from 'src/utils/pagination';
|
||||
import { FindOptionsOrder, FindOptionsRelations, FindOptionsSelect } from 'typeorm';
|
||||
|
||||
export type AssetStats = Record<AssetType, number>;
|
||||
|
||||
@@ -66,43 +65,6 @@ export interface TimeBucketItem {
|
||||
count: number;
|
||||
}
|
||||
|
||||
export type AssetCreate = Pick<
|
||||
AssetEntity,
|
||||
| 'deviceAssetId'
|
||||
| 'ownerId'
|
||||
| 'libraryId'
|
||||
| 'deviceId'
|
||||
| 'type'
|
||||
| 'originalPath'
|
||||
| 'fileCreatedAt'
|
||||
| 'localDateTime'
|
||||
| 'fileModifiedAt'
|
||||
| 'checksum'
|
||||
| 'originalFileName'
|
||||
> &
|
||||
Partial<AssetEntity>;
|
||||
|
||||
export type AssetWithoutRelations = Omit<
|
||||
AssetEntity,
|
||||
| 'livePhotoVideo'
|
||||
| 'stack'
|
||||
| 'albums'
|
||||
| 'faces'
|
||||
| 'owner'
|
||||
| 'library'
|
||||
| 'exifInfo'
|
||||
| 'sharedLinks'
|
||||
| 'smartSearch'
|
||||
| 'tags'
|
||||
>;
|
||||
|
||||
type AssetUpdateWithoutRelations = Pick<AssetWithoutRelations, 'id'> & Partial<AssetWithoutRelations>;
|
||||
type AssetUpdateWithLivePhotoRelation = Pick<AssetWithoutRelations, 'id'> & Pick<AssetEntity, 'livePhotoVideo'>;
|
||||
|
||||
export type AssetUpdateOptions = AssetUpdateWithoutRelations | AssetUpdateWithLivePhotoRelation;
|
||||
|
||||
export type AssetUpdateAllOptions = Omit<Partial<AssetWithoutRelations>, 'id'>;
|
||||
|
||||
export interface MonthDay {
|
||||
day: number;
|
||||
month: number;
|
||||
@@ -113,12 +75,6 @@ export interface AssetExploreFieldOptions {
|
||||
minAssetsPerField: number;
|
||||
}
|
||||
|
||||
export interface AssetExploreOptions extends AssetExploreFieldOptions {
|
||||
relation: keyof AssetEntity;
|
||||
relatedField: string;
|
||||
unnest?: boolean;
|
||||
}
|
||||
|
||||
export interface AssetFullSyncOptions {
|
||||
ownerId: string;
|
||||
lastId?: string;
|
||||
@@ -144,8 +100,30 @@ export interface UpsertFileOptions {
|
||||
path: string;
|
||||
}
|
||||
|
||||
export interface AssetGetByChecksumOptions {
|
||||
ownerId: string;
|
||||
checksum: Buffer;
|
||||
libraryId?: string;
|
||||
}
|
||||
|
||||
export type AssetPathEntity = Pick<AssetEntity, 'id' | 'originalPath' | 'isOffline'>;
|
||||
|
||||
export interface GetByIdsRelations {
|
||||
exifInfo?: boolean;
|
||||
faces?: { person?: boolean };
|
||||
files?: boolean;
|
||||
library?: boolean;
|
||||
owner?: boolean;
|
||||
smartSearch?: boolean;
|
||||
stack?: { assets?: boolean };
|
||||
tags?: boolean;
|
||||
}
|
||||
|
||||
export interface DuplicateGroup {
|
||||
duplicateId: string;
|
||||
assets: AssetEntity[];
|
||||
}
|
||||
|
||||
export interface DayOfYearAssets {
|
||||
yearsAgo: number;
|
||||
assets: AssetEntity[];
|
||||
@@ -154,47 +132,39 @@ export interface DayOfYearAssets {
|
||||
export const IAssetRepository = 'IAssetRepository';
|
||||
|
||||
export interface IAssetRepository {
|
||||
create(asset: AssetCreate): Promise<AssetEntity>;
|
||||
getByIds(
|
||||
ids: string[],
|
||||
relations?: FindOptionsRelations<AssetEntity>,
|
||||
select?: FindOptionsSelect<AssetEntity>,
|
||||
): Promise<AssetEntity[]>;
|
||||
create(asset: Insertable<Assets>): Promise<AssetEntity>;
|
||||
getByIds(ids: string[], relations?: GetByIdsRelations): Promise<AssetEntity[]>;
|
||||
getByIdsWithAllRelations(ids: string[]): Promise<AssetEntity[]>;
|
||||
getByDayOfYear(ownerIds: string[], monthDay: MonthDay): Promise<DayOfYearAssets[]>;
|
||||
getByChecksum(options: { ownerId: string; checksum: Buffer; libraryId?: string }): Promise<AssetEntity | null>;
|
||||
getByChecksum(options: AssetGetByChecksumOptions): Promise<AssetEntity | undefined>;
|
||||
getByChecksums(userId: string, checksums: Buffer[]): Promise<AssetEntity[]>;
|
||||
getUploadAssetIdByChecksum(ownerId: string, checksum: Buffer): Promise<string | undefined>;
|
||||
getByAlbumId(pagination: PaginationOptions, albumId: string): Paginated<AssetEntity>;
|
||||
getByDeviceIds(ownerId: string, deviceId: string, deviceAssetIds: string[]): Promise<string[]>;
|
||||
getByUserId(pagination: PaginationOptions, userId: string, options?: AssetSearchOptions): Paginated<AssetEntity>;
|
||||
getById(
|
||||
id: string,
|
||||
relations?: FindOptionsRelations<AssetEntity>,
|
||||
order?: FindOptionsOrder<AssetEntity>,
|
||||
): Promise<AssetEntity | null>;
|
||||
getById(id: string, relations?: GetByIdsRelations): Promise<AssetEntity | undefined>;
|
||||
getWithout(pagination: PaginationOptions, property: WithoutProperty): Paginated<AssetEntity>;
|
||||
getRandom(userIds: string[], count: number): Promise<AssetEntity[]>;
|
||||
getLastUpdatedAssetForAlbumId(albumId: string): Promise<AssetEntity | null>;
|
||||
getByLibraryIdAndOriginalPath(libraryId: string, originalPath: string): Promise<AssetEntity | null>;
|
||||
getLastUpdatedAssetForAlbumId(albumId: string): Promise<AssetEntity | undefined>;
|
||||
getByLibraryIdAndOriginalPath(libraryId: string, originalPath: string): Promise<AssetEntity | undefined>;
|
||||
deleteAll(ownerId: string): Promise<void>;
|
||||
getAll(pagination: PaginationOptions, options?: AssetSearchOptions): Paginated<AssetEntity>;
|
||||
getAllByDeviceId(userId: string, deviceId: string): Promise<string[]>;
|
||||
getLivePhotoCount(motionId: string): Promise<number>;
|
||||
updateAll(ids: string[], options: Partial<AssetUpdateAllOptions>): Promise<void>;
|
||||
updateAll(ids: string[], options: Updateable<Assets>): Promise<void>;
|
||||
updateDuplicates(options: AssetUpdateDuplicateOptions): Promise<void>;
|
||||
update(asset: AssetUpdateOptions): Promise<void>;
|
||||
update(asset: Updateable<Assets> & { id: string }): Promise<AssetEntity>;
|
||||
remove(asset: AssetEntity): Promise<void>;
|
||||
findLivePhotoMatch(options: LivePhotoSearchOptions): Promise<AssetEntity | null>;
|
||||
findLivePhotoMatch(options: LivePhotoSearchOptions): Promise<AssetEntity | undefined>;
|
||||
getStatistics(ownerId: string, options: AssetStatsOptions): Promise<AssetStats>;
|
||||
getTimeBuckets(options: TimeBucketOptions): Promise<TimeBucketItem[]>;
|
||||
getTimeBucket(timeBucket: string, options: TimeBucketOptions): Promise<AssetEntity[]>;
|
||||
upsertExif(exif: Partial<ExifEntity>): Promise<void>;
|
||||
upsertJobStatus(...jobStatus: Partial<AssetJobStatusEntity>[]): Promise<void>;
|
||||
upsertExif(exif: Insertable<Exif>): Promise<void>;
|
||||
upsertJobStatus(...jobStatus: Insertable<AssetJobStatus>[]): Promise<void>;
|
||||
getAssetIdByCity(userId: string, options: AssetExploreFieldOptions): Promise<SearchExploreItem<string>>;
|
||||
getDuplicates(options: AssetBuilderOptions): Promise<AssetEntity[]>;
|
||||
getDuplicates(userId: string): Promise<DuplicateGroup[]>;
|
||||
getAllForUserFullSync(options: AssetFullSyncOptions): Promise<AssetEntity[]>;
|
||||
getChangedDeltaSync(options: AssetDeltaSyncOptions): Promise<AssetEntity[]>;
|
||||
upsertFile(file: UpsertFileOptions): Promise<void>;
|
||||
upsertFiles(files: UpsertFileOptions[]): Promise<void>;
|
||||
upsertFile(options: Insertable<AssetFiles>): Promise<void>;
|
||||
upsertFiles(options: Insertable<AssetFiles>[]): Promise<void>;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { RegisterQueueOptions } from '@nestjs/bullmq';
|
||||
import { QueueOptions } from 'bullmq';
|
||||
import { RedisOptions } from 'ioredis';
|
||||
import { KyselyConfig } from 'kysely';
|
||||
import { ClsModuleOptions } from 'nestjs-cls';
|
||||
import { OpenTelemetryModuleOptions } from 'nestjs-otel/lib/interfaces';
|
||||
import { ImmichEnvironment, ImmichTelemetry, ImmichWorker, LogLevel } from 'src/enum';
|
||||
@@ -42,7 +43,7 @@ export interface EnvData {
|
||||
};
|
||||
|
||||
database: {
|
||||
config: PostgresConnectionOptions & DatabaseConnectionParams;
|
||||
config: { typeorm: PostgresConnectionOptions & DatabaseConnectionParams; kysely: KyselyConfig };
|
||||
skipMigrations: boolean;
|
||||
vectorExtension: VectorExtension;
|
||||
};
|
||||
|
||||
@@ -59,6 +59,7 @@ export interface VectorUpdateResult {
|
||||
export const IDatabaseRepository = 'IDatabaseRepository';
|
||||
|
||||
export interface IDatabaseRepository {
|
||||
init(): void;
|
||||
reconnect(): Promise<boolean>;
|
||||
getExtensionVersion(extension: DatabaseExtension): Promise<ExtensionVersion>;
|
||||
getExtensionVersionRange(extension: VectorExtension): string;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
||||
import { AssetStatus, AssetType } from 'src/enum';
|
||||
@@ -114,7 +113,7 @@ export interface SearchPeopleOptions {
|
||||
}
|
||||
|
||||
export interface SearchOrderOptions {
|
||||
orderDirection?: 'ASC' | 'DESC';
|
||||
orderDirection?: 'asc' | 'desc';
|
||||
}
|
||||
|
||||
export interface SearchPaginationOptions {
|
||||
@@ -148,20 +147,21 @@ export type SmartSearchOptions = SearchDateOptions &
|
||||
export interface FaceEmbeddingSearch extends SearchEmbeddingOptions {
|
||||
hasPerson?: boolean;
|
||||
numResults: number;
|
||||
maxDistance?: number;
|
||||
maxDistance: number;
|
||||
}
|
||||
|
||||
export interface AssetDuplicateSearch {
|
||||
assetId: string;
|
||||
embedding: number[];
|
||||
maxDistance?: number;
|
||||
maxDistance: number;
|
||||
type: AssetType;
|
||||
userIds: string[];
|
||||
}
|
||||
|
||||
export interface FaceSearchResult {
|
||||
distance: number;
|
||||
face: AssetFaceEntity;
|
||||
id: string;
|
||||
personId: string | null;
|
||||
}
|
||||
|
||||
export interface AssetDuplicateResult {
|
||||
|
||||
Reference in New Issue
Block a user