mirror of
https://github.com/immich-app/immich.git
synced 2025-04-21 15:36:26 +02:00
refactor: migrate media repository (#15536)
This commit is contained in:
parent
30b8864d2d
commit
66849d0d45
15 changed files with 154 additions and 171 deletions
server
src
config.ts
interfaces
repositories
services
base.service.tsmedia.service.spec.tsmedia.service.tsmetadata.service.spec.tsperson.service.spec.tsperson.service.ts
types.tsutils
test
|
@ -12,7 +12,7 @@ import {
|
|||
VideoContainer,
|
||||
} from 'src/enum';
|
||||
import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.interface';
|
||||
import { ImageOptions } from 'src/interfaces/media.interface';
|
||||
import { ImageOptions } from 'src/types';
|
||||
|
||||
export interface SystemConfig {
|
||||
backup: {
|
||||
|
|
|
@ -1,151 +0,0 @@
|
|||
import { Writable } from 'node:stream';
|
||||
import { ExifOrientation, ImageFormat, TranscodeTarget, VideoCodec } from 'src/enum';
|
||||
|
||||
export const IMediaRepository = 'IMediaRepository';
|
||||
|
||||
export interface CropOptions {
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface ImageOptions {
|
||||
format: ImageFormat;
|
||||
quality: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface RawImageInfo {
|
||||
width: number;
|
||||
height: number;
|
||||
channels: 1 | 2 | 3 | 4;
|
||||
}
|
||||
|
||||
interface DecodeImageOptions {
|
||||
colorspace: string;
|
||||
crop?: CropOptions;
|
||||
processInvalidImages: boolean;
|
||||
raw?: RawImageInfo;
|
||||
}
|
||||
|
||||
export interface DecodeToBufferOptions extends DecodeImageOptions {
|
||||
size: number;
|
||||
orientation?: ExifOrientation;
|
||||
}
|
||||
|
||||
export type GenerateThumbnailOptions = ImageOptions & DecodeImageOptions;
|
||||
|
||||
export type GenerateThumbnailFromBufferOptions = GenerateThumbnailOptions & { raw: RawImageInfo };
|
||||
|
||||
export type GenerateThumbhashOptions = DecodeImageOptions;
|
||||
|
||||
export type GenerateThumbhashFromBufferOptions = GenerateThumbhashOptions & { raw: RawImageInfo };
|
||||
|
||||
export interface GenerateThumbnailsOptions {
|
||||
colorspace: string;
|
||||
crop?: CropOptions;
|
||||
preview?: ImageOptions;
|
||||
processInvalidImages: boolean;
|
||||
thumbhash?: boolean;
|
||||
thumbnail?: ImageOptions;
|
||||
}
|
||||
|
||||
export interface VideoStreamInfo {
|
||||
index: number;
|
||||
height: number;
|
||||
width: number;
|
||||
rotation: number;
|
||||
codecName?: string;
|
||||
frameCount: number;
|
||||
isHDR: boolean;
|
||||
bitrate: number;
|
||||
pixelFormat: string;
|
||||
}
|
||||
|
||||
export interface AudioStreamInfo {
|
||||
index: number;
|
||||
codecName?: string;
|
||||
frameCount: number;
|
||||
}
|
||||
|
||||
export interface VideoFormat {
|
||||
formatName?: string;
|
||||
formatLongName?: string;
|
||||
duration: number;
|
||||
bitrate: number;
|
||||
}
|
||||
|
||||
export interface ImageDimensions {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface InputDimensions extends ImageDimensions {
|
||||
inputPath: string;
|
||||
}
|
||||
|
||||
export interface VideoInfo {
|
||||
format: VideoFormat;
|
||||
videoStreams: VideoStreamInfo[];
|
||||
audioStreams: AudioStreamInfo[];
|
||||
}
|
||||
|
||||
export interface TranscodeCommand {
|
||||
inputOptions: string[];
|
||||
outputOptions: string[];
|
||||
twoPass: boolean;
|
||||
progress: {
|
||||
frameCount: number;
|
||||
percentInterval: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface BitrateDistribution {
|
||||
max: number;
|
||||
target: number;
|
||||
min: number;
|
||||
unit: string;
|
||||
}
|
||||
|
||||
export interface ImageBuffer {
|
||||
data: Buffer;
|
||||
info: RawImageInfo;
|
||||
}
|
||||
|
||||
export interface VideoCodecSWConfig {
|
||||
getCommand(
|
||||
target: TranscodeTarget,
|
||||
videoStream: VideoStreamInfo,
|
||||
audioStream: AudioStreamInfo,
|
||||
format?: VideoFormat,
|
||||
): TranscodeCommand;
|
||||
}
|
||||
|
||||
export interface VideoCodecHWConfig extends VideoCodecSWConfig {
|
||||
getSupportedCodecs(): Array<VideoCodec>;
|
||||
}
|
||||
|
||||
export interface ProbeOptions {
|
||||
countFrames: boolean;
|
||||
}
|
||||
|
||||
export interface VideoInterfaces {
|
||||
dri: string[];
|
||||
mali: boolean;
|
||||
}
|
||||
|
||||
export interface IMediaRepository {
|
||||
// image
|
||||
extract(input: string, output: string): Promise<boolean>;
|
||||
decodeImage(input: string, options: DecodeToBufferOptions): Promise<ImageBuffer>;
|
||||
generateThumbnail(input: string, options: GenerateThumbnailOptions, outputFile: string): Promise<void>;
|
||||
generateThumbnail(input: Buffer, options: GenerateThumbnailFromBufferOptions, outputFile: string): Promise<void>;
|
||||
generateThumbhash(input: string, options: GenerateThumbhashOptions): Promise<Buffer>;
|
||||
generateThumbhash(input: Buffer, options: GenerateThumbhashFromBufferOptions): Promise<Buffer>;
|
||||
getImageDimensions(input: string): Promise<ImageDimensions>;
|
||||
|
||||
// video
|
||||
probe(input: string, options?: ProbeOptions): Promise<VideoInfo>;
|
||||
transcode(input: string, output: string | Writable, command: TranscodeCommand): Promise<void>;
|
||||
}
|
|
@ -10,7 +10,6 @@ import { ILibraryRepository } from 'src/interfaces/library.interface';
|
|||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
||||
import { IMapRepository } from 'src/interfaces/map.interface';
|
||||
import { IMediaRepository } from 'src/interfaces/media.interface';
|
||||
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
|
||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||
import { INotificationRepository } from 'src/interfaces/notification.interface';
|
||||
|
@ -77,6 +76,7 @@ export const repositories = [
|
|||
AuditRepository,
|
||||
ApiKeyRepository,
|
||||
ConfigRepository,
|
||||
MediaRepository,
|
||||
MemoryRepository,
|
||||
ViewRepository,
|
||||
];
|
||||
|
@ -94,7 +94,6 @@ export const providers = [
|
|||
{ provide: ILoggerRepository, useClass: LoggerRepository },
|
||||
{ provide: IMachineLearningRepository, useClass: MachineLearningRepository },
|
||||
{ provide: IMapRepository, useClass: MapRepository },
|
||||
{ provide: IMediaRepository, useClass: MediaRepository },
|
||||
{ provide: IMetadataRepository, useClass: MetadataRepository },
|
||||
{ provide: IMoveRepository, useClass: MoveRepository },
|
||||
{ provide: INotificationRepository, useClass: NotificationRepository },
|
||||
|
|
|
@ -12,12 +12,11 @@ import {
|
|||
DecodeToBufferOptions,
|
||||
GenerateThumbhashOptions,
|
||||
GenerateThumbnailOptions,
|
||||
IMediaRepository,
|
||||
ImageDimensions,
|
||||
ProbeOptions,
|
||||
TranscodeCommand,
|
||||
VideoInfo,
|
||||
} from 'src/interfaces/media.interface';
|
||||
} from 'src/types';
|
||||
import { handlePromiseError } from 'src/utils/misc';
|
||||
|
||||
const probe = (input: string, options: string[]): Promise<FfprobeData> =>
|
||||
|
@ -37,7 +36,7 @@ type ProgressEvent = {
|
|||
};
|
||||
|
||||
@Injectable()
|
||||
export class MediaRepository implements IMediaRepository {
|
||||
export class MediaRepository {
|
||||
constructor(@Inject(ILoggerRepository) private logger: ILoggerRepository) {
|
||||
this.logger.setContext(MediaRepository.name);
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@ import { ILibraryRepository } from 'src/interfaces/library.interface';
|
|||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
||||
import { IMapRepository } from 'src/interfaces/map.interface';
|
||||
import { IMediaRepository } from 'src/interfaces/media.interface';
|
||||
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
|
||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||
import { INotificationRepository } from 'src/interfaces/notification.interface';
|
||||
|
@ -43,6 +42,7 @@ import { ActivityRepository } from 'src/repositories/activity.repository';
|
|||
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
||||
import { AuditRepository } from 'src/repositories/audit.repository';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
import { MediaRepository } from 'src/repositories/media.repository';
|
||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||
import { ViewRepository } from 'src/repositories/view-repository';
|
||||
import { AccessRequest, checkAccess, requireAccess } from 'src/utils/access';
|
||||
|
@ -69,7 +69,7 @@ export class BaseService {
|
|||
@Inject(ILibraryRepository) protected libraryRepository: ILibraryRepository,
|
||||
@Inject(IMachineLearningRepository) protected machineLearningRepository: IMachineLearningRepository,
|
||||
@Inject(IMapRepository) protected mapRepository: IMapRepository,
|
||||
@Inject(IMediaRepository) protected mediaRepository: IMediaRepository,
|
||||
protected mediaRepository: MediaRepository,
|
||||
protected memoryRepository: MemoryRepository,
|
||||
@Inject(IMetadataRepository) protected metadataRepository: IMetadataRepository,
|
||||
@Inject(IMoveRepository) protected moveRepository: IMoveRepository,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { OutputInfo } from 'sharp';
|
||||
import { SystemConfig } from 'src/config';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { ExifEntity } from 'src/entities/exif.entity';
|
||||
|
@ -15,12 +16,12 @@ import {
|
|||
import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interface';
|
||||
import { IJobRepository, JobCounts, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||
import { ILoggerRepository } from 'src/interfaces/logger.interface';
|
||||
import { IMediaRepository, RawImageInfo } from 'src/interfaces/media.interface';
|
||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||
import { MediaService } from 'src/services/media.service';
|
||||
import { IMediaRepository, RawImageInfo } from 'src/types';
|
||||
import { assetStub } from 'test/fixtures/asset.stub';
|
||||
import { faceStub } from 'test/fixtures/face.stub';
|
||||
import { probeStub } from 'test/fixtures/media.stub';
|
||||
|
@ -257,7 +258,7 @@ describe(MediaService.name, () => {
|
|||
beforeEach(() => {
|
||||
rawBuffer = Buffer.from('image data');
|
||||
rawInfo = { width: 100, height: 100, channels: 3 };
|
||||
mediaMock.decodeImage.mockResolvedValue({ data: rawBuffer, info: rawInfo });
|
||||
mediaMock.decodeImage.mockResolvedValue({ data: rawBuffer, info: rawInfo as OutputInfo });
|
||||
});
|
||||
|
||||
it('should skip thumbnail generation if asset not found', async () => {
|
||||
|
|
|
@ -27,8 +27,8 @@ import {
|
|||
JobStatus,
|
||||
QueueName,
|
||||
} from 'src/interfaces/job.interface';
|
||||
import { AudioStreamInfo, VideoFormat, VideoInterfaces, VideoStreamInfo } from 'src/interfaces/media.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { AudioStreamInfo, VideoFormat, VideoInterfaces, VideoStreamInfo } from 'src/types';
|
||||
import { getAssetFiles } from 'src/utils/asset.util';
|
||||
import { BaseConfig, ThumbnailConfig } from 'src/utils/media';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
|
|
|
@ -11,7 +11,6 @@ import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
|||
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||
import { IMapRepository } from 'src/interfaces/map.interface';
|
||||
import { IMediaRepository } from 'src/interfaces/media.interface';
|
||||
import { IMetadataRepository, ImmichTags } from 'src/interfaces/metadata.interface';
|
||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||
|
@ -19,7 +18,7 @@ import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interf
|
|||
import { ITagRepository } from 'src/interfaces/tag.interface';
|
||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||
import { MetadataService } from 'src/services/metadata.service';
|
||||
import { IConfigRepository } from 'src/types';
|
||||
import { IConfigRepository, IMediaRepository } from 'src/types';
|
||||
import { assetStub } from 'test/fixtures/asset.stub';
|
||||
import { fileStub } from 'test/fixtures/file.stub';
|
||||
import { probeStub } from 'test/fixtures/media.stub';
|
||||
|
|
|
@ -7,12 +7,12 @@ import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interfac
|
|||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||
import { DetectedFaces, IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
||||
import { IMediaRepository } from 'src/interfaces/media.interface';
|
||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||
import { FaceSearchResult, ISearchRepository } from 'src/interfaces/search.interface';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||
import { PersonService } from 'src/services/person.service';
|
||||
import { IMediaRepository } from 'src/types';
|
||||
import { ImmichFileResponse } from 'src/utils/file';
|
||||
import { assetStub } from 'test/fixtures/asset.stub';
|
||||
import { authStub } from 'test/fixtures/auth.stub';
|
||||
|
|
|
@ -42,9 +42,9 @@ import {
|
|||
QueueName,
|
||||
} from 'src/interfaces/job.interface';
|
||||
import { BoundingBox } from 'src/interfaces/machine-learning.interface';
|
||||
import { CropOptions, ImageDimensions, InputDimensions } from 'src/interfaces/media.interface';
|
||||
import { UpdateFacesData } from 'src/interfaces/person.interface';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
import { CropOptions, ImageDimensions, InputDimensions } from 'src/types';
|
||||
import { getAssetFiles } from 'src/utils/asset.util';
|
||||
import { ImmichFileResponse } from 'src/utils/file';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
import { UserEntity } from 'src/entities/user.entity';
|
||||
import { Permission } from 'src/enum';
|
||||
import { ExifOrientation, ImageFormat, Permission, TranscodeTarget, VideoCodec } from 'src/enum';
|
||||
import { AccessRepository } from 'src/repositories/access.repository';
|
||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
||||
import { AuditRepository } from 'src/repositories/audit.repository';
|
||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||
import { MediaRepository } from 'src/repositories/media.repository';
|
||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||
import { ViewRepository } from 'src/repositories/view-repository';
|
||||
|
||||
|
@ -24,6 +25,7 @@ export type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInter
|
|||
export type IApiKeyRepository = RepositoryInterface<ApiKeyRepository>;
|
||||
export type IAuditRepository = RepositoryInterface<AuditRepository>;
|
||||
export type IConfigRepository = RepositoryInterface<ConfigRepository>;
|
||||
export type IMediaRepository = RepositoryInterface<MediaRepository>;
|
||||
export type IMemoryRepository = RepositoryInterface<MemoryRepository>;
|
||||
export type IViewRepository = RepositoryInterface<ViewRepository>;
|
||||
|
||||
|
@ -39,3 +41,135 @@ export type ApiKeyItem =
|
|||
export type MemoryItem =
|
||||
| Awaited<ReturnType<IMemoryRepository['create']>>
|
||||
| Awaited<ReturnType<IMemoryRepository['search']>>[0];
|
||||
|
||||
export interface CropOptions {
|
||||
top: number;
|
||||
left: number;
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface ImageOptions {
|
||||
format: ImageFormat;
|
||||
quality: number;
|
||||
size: number;
|
||||
}
|
||||
|
||||
export interface RawImageInfo {
|
||||
width: number;
|
||||
height: number;
|
||||
channels: 1 | 2 | 3 | 4;
|
||||
}
|
||||
|
||||
interface DecodeImageOptions {
|
||||
colorspace: string;
|
||||
crop?: CropOptions;
|
||||
processInvalidImages: boolean;
|
||||
raw?: RawImageInfo;
|
||||
}
|
||||
|
||||
export interface DecodeToBufferOptions extends DecodeImageOptions {
|
||||
size: number;
|
||||
orientation?: ExifOrientation;
|
||||
}
|
||||
|
||||
export type GenerateThumbnailOptions = ImageOptions & DecodeImageOptions;
|
||||
|
||||
export type GenerateThumbnailFromBufferOptions = GenerateThumbnailOptions & { raw: RawImageInfo };
|
||||
|
||||
export type GenerateThumbhashOptions = DecodeImageOptions;
|
||||
|
||||
export type GenerateThumbhashFromBufferOptions = GenerateThumbhashOptions & { raw: RawImageInfo };
|
||||
|
||||
export interface GenerateThumbnailsOptions {
|
||||
colorspace: string;
|
||||
crop?: CropOptions;
|
||||
preview?: ImageOptions;
|
||||
processInvalidImages: boolean;
|
||||
thumbhash?: boolean;
|
||||
thumbnail?: ImageOptions;
|
||||
}
|
||||
|
||||
export interface VideoStreamInfo {
|
||||
index: number;
|
||||
height: number;
|
||||
width: number;
|
||||
rotation: number;
|
||||
codecName?: string;
|
||||
frameCount: number;
|
||||
isHDR: boolean;
|
||||
bitrate: number;
|
||||
pixelFormat: string;
|
||||
}
|
||||
|
||||
export interface AudioStreamInfo {
|
||||
index: number;
|
||||
codecName?: string;
|
||||
frameCount: number;
|
||||
}
|
||||
|
||||
export interface VideoFormat {
|
||||
formatName?: string;
|
||||
formatLongName?: string;
|
||||
duration: number;
|
||||
bitrate: number;
|
||||
}
|
||||
|
||||
export interface ImageDimensions {
|
||||
width: number;
|
||||
height: number;
|
||||
}
|
||||
|
||||
export interface InputDimensions extends ImageDimensions {
|
||||
inputPath: string;
|
||||
}
|
||||
|
||||
export interface VideoInfo {
|
||||
format: VideoFormat;
|
||||
videoStreams: VideoStreamInfo[];
|
||||
audioStreams: AudioStreamInfo[];
|
||||
}
|
||||
|
||||
export interface TranscodeCommand {
|
||||
inputOptions: string[];
|
||||
outputOptions: string[];
|
||||
twoPass: boolean;
|
||||
progress: {
|
||||
frameCount: number;
|
||||
percentInterval: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface BitrateDistribution {
|
||||
max: number;
|
||||
target: number;
|
||||
min: number;
|
||||
unit: string;
|
||||
}
|
||||
|
||||
export interface ImageBuffer {
|
||||
data: Buffer;
|
||||
info: RawImageInfo;
|
||||
}
|
||||
|
||||
export interface VideoCodecSWConfig {
|
||||
getCommand(
|
||||
target: TranscodeTarget,
|
||||
videoStream: VideoStreamInfo,
|
||||
audioStream: AudioStreamInfo,
|
||||
format?: VideoFormat,
|
||||
): TranscodeCommand;
|
||||
}
|
||||
|
||||
export interface VideoCodecHWConfig extends VideoCodecSWConfig {
|
||||
getSupportedCodecs(): Array<VideoCodec>;
|
||||
}
|
||||
|
||||
export interface ProbeOptions {
|
||||
countFrames: boolean;
|
||||
}
|
||||
|
||||
export interface VideoInterfaces {
|
||||
dri: string[];
|
||||
mali: boolean;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ import {
|
|||
VideoFormat,
|
||||
VideoInterfaces,
|
||||
VideoStreamInfo,
|
||||
} from 'src/interfaces/media.interface';
|
||||
} from 'src/types';
|
||||
|
||||
export class BaseConfig implements VideoCodecSWConfig {
|
||||
readonly presets = ['veryslow', 'slower', 'slow', 'medium', 'fast', 'faster', 'veryfast', 'superfast', 'ultrafast'];
|
||||
|
|
2
server/test/fixtures/media.stub.ts
vendored
2
server/test/fixtures/media.stub.ts
vendored
|
@ -1,4 +1,4 @@
|
|||
import { AudioStreamInfo, VideoFormat, VideoInfo, VideoStreamInfo } from 'src/interfaces/media.interface';
|
||||
import { AudioStreamInfo, VideoFormat, VideoInfo, VideoStreamInfo } from 'src/types';
|
||||
|
||||
const probeStubDefaultFormat: VideoFormat = {
|
||||
formatName: 'mov,mp4,m4a,3gp,3g2,mj2',
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { IMediaRepository } from 'src/interfaces/media.interface';
|
||||
import { IMediaRepository } from 'src/types';
|
||||
import { Mocked, vitest } from 'vitest';
|
||||
|
||||
export const newMediaRepositoryMock = (): Mocked<IMediaRepository> => {
|
||||
|
|
|
@ -7,6 +7,7 @@ import { AccessRepository } from 'src/repositories/access.repository';
|
|||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
||||
import { AuditRepository } from 'src/repositories/audit.repository';
|
||||
import { MediaRepository } from 'src/repositories/media.repository';
|
||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||
import { ViewRepository } from 'src/repositories/view-repository';
|
||||
import { BaseService } from 'src/services/base.service';
|
||||
|
@ -15,6 +16,7 @@ import {
|
|||
IActivityRepository,
|
||||
IApiKeyRepository,
|
||||
IAuditRepository,
|
||||
IMediaRepository,
|
||||
IMemoryRepository,
|
||||
IViewRepository,
|
||||
} from 'src/types';
|
||||
|
@ -133,7 +135,7 @@ export const newTestService = <T extends BaseService>(
|
|||
libraryMock,
|
||||
machineLearningMock,
|
||||
mapMock,
|
||||
mediaMock,
|
||||
mediaMock as IMediaRepository as MediaRepository,
|
||||
memoryMock as IMemoryRepository as MemoryRepository,
|
||||
metadataMock,
|
||||
moveMock,
|
||||
|
|
Loading…
Add table
Reference in a new issue