mirror of
https://github.com/immich-app/immich.git
synced 2025-06-03 13:44:16 -04:00
refactor: repositories (#15561)
* refactor: version history repository * refactor: oauth repository * refactor: trash repository * refactor: telemetry repository * refactor: metadata repository * refactor: cron repository * refactor: map repository * refactor: server-info repository * refactor: album user repository * refactor: notification repository
This commit is contained in:
parent
995314446b
commit
1869b1b41a
@ -13,7 +13,6 @@ import { entities } from 'src/entities';
|
|||||||
import { ImmichWorker } from 'src/enum';
|
import { ImmichWorker } from 'src/enum';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository } from 'src/interfaces/job.interface';
|
import { IJobRepository } from 'src/interfaces/job.interface';
|
||||||
import { ITelemetryRepository } from 'src/interfaces/telemetry.interface';
|
|
||||||
import { AuthGuard } from 'src/middleware/auth.guard';
|
import { AuthGuard } from 'src/middleware/auth.guard';
|
||||||
import { ErrorInterceptor } from 'src/middleware/error.interceptor';
|
import { ErrorInterceptor } from 'src/middleware/error.interceptor';
|
||||||
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
|
import { FileUploadInterceptor } from 'src/middleware/file-upload.interceptor';
|
||||||
@ -22,7 +21,7 @@ import { LoggingInterceptor } from 'src/middleware/logging.interceptor';
|
|||||||
import { providers, repositories } from 'src/repositories';
|
import { providers, repositories } from 'src/repositories';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { teardownTelemetry } from 'src/repositories/telemetry.repository';
|
import { teardownTelemetry, TelemetryRepository } from 'src/repositories/telemetry.repository';
|
||||||
import { services } from 'src/services';
|
import { services } from 'src/services';
|
||||||
import { CliService } from 'src/services/cli.service';
|
import { CliService } from 'src/services/cli.service';
|
||||||
import { DatabaseService } from 'src/services/database.service';
|
import { DatabaseService } from 'src/services/database.service';
|
||||||
@ -67,7 +66,7 @@ class BaseModule implements OnModuleInit, OnModuleDestroy {
|
|||||||
logger: LoggingRepository,
|
logger: LoggingRepository,
|
||||||
@Inject(IEventRepository) private eventRepository: IEventRepository,
|
@Inject(IEventRepository) private eventRepository: IEventRepository,
|
||||||
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
@Inject(IJobRepository) private jobRepository: IJobRepository,
|
||||||
@Inject(ITelemetryRepository) private telemetryRepository: ITelemetryRepository,
|
private telemetryRepository: TelemetryRepository,
|
||||||
) {
|
) {
|
||||||
logger.setAppName(this.worker);
|
logger.setAppName(this.worker);
|
||||||
}
|
}
|
||||||
|
@ -3,8 +3,8 @@ import { ApiTags } from '@nestjs/swagger';
|
|||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
import { TemplateDto, TemplateResponseDto, TestEmailResponseDto } from 'src/dtos/notification.dto';
|
import { TemplateDto, TemplateResponseDto, TestEmailResponseDto } from 'src/dtos/notification.dto';
|
||||||
import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto';
|
import { SystemConfigSmtpDto } from 'src/dtos/system-config.dto';
|
||||||
import { EmailTemplate } from 'src/interfaces/notification.interface';
|
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
|
import { EmailTemplate } from 'src/repositories/notification.repository';
|
||||||
import { NotificationService } from 'src/services/notification.service';
|
import { NotificationService } from 'src/services/notification.service';
|
||||||
|
|
||||||
@ApiTags('Notifications')
|
@ApiTags('Notifications')
|
||||||
|
@ -2,7 +2,7 @@ import { Img, Link, Section, Text } from '@react-email/components';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ImmichButton } from 'src/emails/components/button.component';
|
import { ImmichButton } from 'src/emails/components/button.component';
|
||||||
import ImmichLayout from 'src/emails/components/immich.layout';
|
import ImmichLayout from 'src/emails/components/immich.layout';
|
||||||
import { AlbumInviteEmailProps } from 'src/interfaces/notification.interface';
|
import { AlbumInviteEmailProps } from 'src/repositories/notification.repository';
|
||||||
import { replaceTemplateTags } from 'src/utils/replace-template-tags';
|
import { replaceTemplateTags } from 'src/utils/replace-template-tags';
|
||||||
|
|
||||||
export const AlbumInviteEmail = ({
|
export const AlbumInviteEmail = ({
|
||||||
|
@ -2,7 +2,7 @@ import { Img, Link, Section, Text } from '@react-email/components';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ImmichButton } from 'src/emails/components/button.component';
|
import { ImmichButton } from 'src/emails/components/button.component';
|
||||||
import ImmichLayout from 'src/emails/components/immich.layout';
|
import ImmichLayout from 'src/emails/components/immich.layout';
|
||||||
import { AlbumUpdateEmailProps } from 'src/interfaces/notification.interface';
|
import { AlbumUpdateEmailProps } from 'src/repositories/notification.repository';
|
||||||
import { replaceTemplateTags } from 'src/utils/replace-template-tags';
|
import { replaceTemplateTags } from 'src/utils/replace-template-tags';
|
||||||
|
|
||||||
export const AlbumUpdateEmail = ({
|
export const AlbumUpdateEmail = ({
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { Link, Row, Text } from '@react-email/components';
|
import { Link, Row, Text } from '@react-email/components';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import ImmichLayout from 'src/emails/components/immich.layout';
|
import ImmichLayout from 'src/emails/components/immich.layout';
|
||||||
import { TestEmailProps } from 'src/interfaces/notification.interface';
|
import { TestEmailProps } from 'src/repositories/notification.repository';
|
||||||
|
|
||||||
export const TestEmail = ({ baseUrl, displayName }: TestEmailProps) => (
|
export const TestEmail = ({ baseUrl, displayName }: TestEmailProps) => (
|
||||||
<ImmichLayout preview="This is a test email from Immich.">
|
<ImmichLayout preview="This is a test email from Immich.">
|
||||||
|
@ -2,7 +2,7 @@ import { Link, Section, Text } from '@react-email/components';
|
|||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { ImmichButton } from 'src/emails/components/button.component';
|
import { ImmichButton } from 'src/emails/components/button.component';
|
||||||
import ImmichLayout from 'src/emails/components/immich.layout';
|
import ImmichLayout from 'src/emails/components/immich.layout';
|
||||||
import { WelcomeEmailProps } from 'src/interfaces/notification.interface';
|
import { WelcomeEmailProps } from 'src/repositories/notification.repository';
|
||||||
import { replaceTemplateTags } from 'src/utils/replace-template-tags';
|
import { replaceTemplateTags } from 'src/utils/replace-template-tags';
|
||||||
|
|
||||||
export const WelcomeEmail = ({ baseUrl, displayName, username, password, customTemplate }: WelcomeEmailProps) => {
|
export const WelcomeEmail = ({ baseUrl, displayName, username, password, customTemplate }: WelcomeEmailProps) => {
|
||||||
|
@ -1,18 +0,0 @@
|
|||||||
import { Insertable, Selectable, Updateable } from 'kysely';
|
|
||||||
import { AlbumsSharedUsersUsers } from 'src/db';
|
|
||||||
|
|
||||||
export const IAlbumUserRepository = 'IAlbumUserRepository';
|
|
||||||
|
|
||||||
export type AlbumPermissionId = {
|
|
||||||
albumsId: string;
|
|
||||||
usersId: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface IAlbumUserRepository {
|
|
||||||
create(albumUser: Insertable<AlbumsSharedUsersUsers>): Promise<Selectable<AlbumsSharedUsersUsers>>;
|
|
||||||
update(
|
|
||||||
id: AlbumPermissionId,
|
|
||||||
albumPermission: Updateable<AlbumsSharedUsersUsers>,
|
|
||||||
): Promise<Selectable<AlbumsSharedUsersUsers>>;
|
|
||||||
delete(id: AlbumPermissionId): Promise<void>;
|
|
||||||
}
|
|
@ -1,20 +0,0 @@
|
|||||||
export const ICronRepository = 'ICronRepository';
|
|
||||||
|
|
||||||
type CronBase = {
|
|
||||||
name: string;
|
|
||||||
start?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CronCreate = CronBase & {
|
|
||||||
expression: string;
|
|
||||||
onTick: () => void;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type CronUpdate = CronBase & {
|
|
||||||
expression?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface ICronRepository {
|
|
||||||
create(cron: CronCreate): void;
|
|
||||||
update(cron: CronUpdate): void;
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
import { ClassConstructor } from 'class-transformer';
|
import { ClassConstructor } from 'class-transformer';
|
||||||
import { EmailImageAttachment } from 'src/interfaces/notification.interface';
|
import { EmailImageAttachment } from 'src/repositories/notification.repository';
|
||||||
|
|
||||||
export enum QueueName {
|
export enum QueueName {
|
||||||
THUMBNAIL_GENERATION = 'thumbnailGeneration',
|
THUMBNAIL_GENERATION = 'thumbnailGeneration',
|
||||||
|
@ -1,31 +0,0 @@
|
|||||||
export const IMapRepository = 'IMapRepository';
|
|
||||||
|
|
||||||
export interface MapMarkerSearchOptions {
|
|
||||||
isArchived?: boolean;
|
|
||||||
isFavorite?: boolean;
|
|
||||||
fileCreatedBefore?: Date;
|
|
||||||
fileCreatedAfter?: Date;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface GeoPoint {
|
|
||||||
latitude: number;
|
|
||||||
longitude: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ReverseGeocodeResult {
|
|
||||||
country: string | null;
|
|
||||||
state: string | null;
|
|
||||||
city: string | null;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface MapMarker extends ReverseGeocodeResult {
|
|
||||||
id: string;
|
|
||||||
lat: number;
|
|
||||||
lon: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IMapRepository {
|
|
||||||
init(): Promise<void>;
|
|
||||||
reverseGeocode(point: GeoPoint): Promise<ReverseGeocodeResult>;
|
|
||||||
getMapMarkers(ownerIds: string[], albumIds: string[], options?: MapMarkerSearchOptions): Promise<MapMarker[]>;
|
|
||||||
}
|
|
@ -1,71 +0,0 @@
|
|||||||
import { BinaryField, Tags } from 'exiftool-vendored';
|
|
||||||
|
|
||||||
export const IMetadataRepository = 'IMetadataRepository';
|
|
||||||
|
|
||||||
export interface ExifDuration {
|
|
||||||
Value: number;
|
|
||||||
Scale?: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
type StringOrNumber = string | number;
|
|
||||||
|
|
||||||
type TagsWithWrongTypes =
|
|
||||||
| 'FocalLength'
|
|
||||||
| 'Duration'
|
|
||||||
| 'Description'
|
|
||||||
| 'ImageDescription'
|
|
||||||
| 'RegionInfo'
|
|
||||||
| 'TagsList'
|
|
||||||
| 'Keywords'
|
|
||||||
| 'HierarchicalSubject'
|
|
||||||
| 'ISO';
|
|
||||||
export interface ImmichTags extends Omit<Tags, TagsWithWrongTypes> {
|
|
||||||
ContentIdentifier?: string;
|
|
||||||
MotionPhoto?: number;
|
|
||||||
MotionPhotoVersion?: number;
|
|
||||||
MotionPhotoPresentationTimestampUs?: number;
|
|
||||||
MediaGroupUUID?: string;
|
|
||||||
ImagePixelDepth?: string;
|
|
||||||
FocalLength?: number;
|
|
||||||
Duration?: number | string | ExifDuration;
|
|
||||||
EmbeddedVideoType?: string;
|
|
||||||
EmbeddedVideoFile?: BinaryField;
|
|
||||||
MotionPhotoVideo?: BinaryField;
|
|
||||||
TagsList?: StringOrNumber[];
|
|
||||||
HierarchicalSubject?: StringOrNumber[];
|
|
||||||
Keywords?: StringOrNumber | StringOrNumber[];
|
|
||||||
ISO?: number | number[];
|
|
||||||
|
|
||||||
// Type is wrong, can also be number.
|
|
||||||
Description?: StringOrNumber;
|
|
||||||
ImageDescription?: StringOrNumber;
|
|
||||||
|
|
||||||
// Extended properties for image regions, such as faces
|
|
||||||
RegionInfo?: {
|
|
||||||
AppliedToDimensions: {
|
|
||||||
W: number;
|
|
||||||
H: number;
|
|
||||||
Unit: string;
|
|
||||||
};
|
|
||||||
RegionList: {
|
|
||||||
Area: {
|
|
||||||
// (X,Y) // center of the rectangle
|
|
||||||
X: number;
|
|
||||||
Y: number;
|
|
||||||
W: number;
|
|
||||||
H: number;
|
|
||||||
Unit: string;
|
|
||||||
};
|
|
||||||
Rotation?: number;
|
|
||||||
Type?: string;
|
|
||||||
Name?: string;
|
|
||||||
}[];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IMetadataRepository {
|
|
||||||
teardown(): Promise<void>;
|
|
||||||
readTags(path: string): Promise<ImmichTags>;
|
|
||||||
writeTags(path: string, tags: Partial<Tags>): Promise<void>;
|
|
||||||
extractBinaryTag(tagName: string, path: string): Promise<Buffer>;
|
|
||||||
}
|
|
@ -1,101 +0,0 @@
|
|||||||
export const INotificationRepository = 'INotificationRepository';
|
|
||||||
|
|
||||||
export type EmailImageAttachment = {
|
|
||||||
filename: string;
|
|
||||||
path: string;
|
|
||||||
cid: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SendEmailOptions = {
|
|
||||||
from: string;
|
|
||||||
to: string;
|
|
||||||
replyTo?: string;
|
|
||||||
subject: string;
|
|
||||||
html: string;
|
|
||||||
text: string;
|
|
||||||
imageAttachments?: EmailImageAttachment[];
|
|
||||||
smtp: SmtpOptions;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SmtpOptions = {
|
|
||||||
host: string;
|
|
||||||
port?: number;
|
|
||||||
username?: string;
|
|
||||||
password?: string;
|
|
||||||
ignoreCert?: boolean;
|
|
||||||
};
|
|
||||||
|
|
||||||
export enum EmailTemplate {
|
|
||||||
TEST_EMAIL = 'test',
|
|
||||||
|
|
||||||
// AUTH
|
|
||||||
WELCOME = 'welcome',
|
|
||||||
RESET_PASSWORD = 'reset-password',
|
|
||||||
|
|
||||||
// ALBUM
|
|
||||||
ALBUM_INVITE = 'album-invite',
|
|
||||||
ALBUM_UPDATE = 'album-update',
|
|
||||||
}
|
|
||||||
|
|
||||||
interface BaseEmailProps {
|
|
||||||
baseUrl: string;
|
|
||||||
customTemplate?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface TestEmailProps extends BaseEmailProps {
|
|
||||||
displayName: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface WelcomeEmailProps extends BaseEmailProps {
|
|
||||||
displayName: string;
|
|
||||||
username: string;
|
|
||||||
password?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlbumInviteEmailProps extends BaseEmailProps {
|
|
||||||
albumName: string;
|
|
||||||
albumId: string;
|
|
||||||
senderName: string;
|
|
||||||
recipientName: string;
|
|
||||||
cid?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface AlbumUpdateEmailProps extends BaseEmailProps {
|
|
||||||
albumName: string;
|
|
||||||
albumId: string;
|
|
||||||
recipientName: string;
|
|
||||||
cid?: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type EmailRenderRequest =
|
|
||||||
| {
|
|
||||||
template: EmailTemplate.TEST_EMAIL;
|
|
||||||
data: TestEmailProps;
|
|
||||||
customTemplate: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
template: EmailTemplate.WELCOME;
|
|
||||||
data: WelcomeEmailProps;
|
|
||||||
customTemplate: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
template: EmailTemplate.ALBUM_INVITE;
|
|
||||||
data: AlbumInviteEmailProps;
|
|
||||||
customTemplate: string;
|
|
||||||
}
|
|
||||||
| {
|
|
||||||
template: EmailTemplate.ALBUM_UPDATE;
|
|
||||||
data: AlbumUpdateEmailProps;
|
|
||||||
customTemplate: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
export type SendEmailResponse = {
|
|
||||||
messageId: string;
|
|
||||||
response: any;
|
|
||||||
};
|
|
||||||
|
|
||||||
export interface INotificationRepository {
|
|
||||||
renderEmail(request: EmailRenderRequest): Promise<{ html: string; text: string }>;
|
|
||||||
sendEmail(options: SendEmailOptions): Promise<SendEmailResponse>;
|
|
||||||
verifySmtp(options: SmtpOptions): Promise<true>;
|
|
||||||
}
|
|
@ -1,22 +0,0 @@
|
|||||||
import { UserinfoResponse } from 'openid-client';
|
|
||||||
|
|
||||||
export const IOAuthRepository = 'IOAuthRepository';
|
|
||||||
|
|
||||||
export type OAuthConfig = {
|
|
||||||
clientId: string;
|
|
||||||
clientSecret: string;
|
|
||||||
issuerUrl: string;
|
|
||||||
mobileOverrideEnabled: boolean;
|
|
||||||
mobileRedirectUri: string;
|
|
||||||
profileSigningAlgorithm: string;
|
|
||||||
scope: string;
|
|
||||||
signingAlgorithm: string;
|
|
||||||
};
|
|
||||||
export type OAuthProfile = UserinfoResponse;
|
|
||||||
|
|
||||||
export interface IOAuthRepository {
|
|
||||||
init(): void;
|
|
||||||
authorize(config: OAuthConfig, redirectUrl: string): Promise<string>;
|
|
||||||
getLogoutEndpoint(config: OAuthConfig): Promise<string | undefined>;
|
|
||||||
getProfile(config: OAuthConfig, url: string, redirectUrl: string): Promise<OAuthProfile>;
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
export interface GitHubRelease {
|
|
||||||
id: number;
|
|
||||||
url: string;
|
|
||||||
tag_name: string;
|
|
||||||
name: string;
|
|
||||||
created_at: string;
|
|
||||||
published_at: string;
|
|
||||||
body: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ServerBuildVersions {
|
|
||||||
nodejs: string;
|
|
||||||
ffmpeg: string;
|
|
||||||
libvips: string;
|
|
||||||
exiftool: string;
|
|
||||||
imagemagick: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
export const IServerInfoRepository = 'IServerInfoRepository';
|
|
||||||
|
|
||||||
export interface IServerInfoRepository {
|
|
||||||
getGitHubRelease(): Promise<GitHubRelease>;
|
|
||||||
getBuildVersions(): Promise<ServerBuildVersions>;
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
import { MetricOptions } from '@opentelemetry/api';
|
|
||||||
import { ClassConstructor } from 'class-transformer';
|
|
||||||
|
|
||||||
export const ITelemetryRepository = 'ITelemetryRepository';
|
|
||||||
|
|
||||||
export interface MetricGroupOptions {
|
|
||||||
enabled: boolean;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IMetricGroupRepository {
|
|
||||||
addToCounter(name: string, value: number, options?: MetricOptions): void;
|
|
||||||
addToGauge(name: string, value: number, options?: MetricOptions): void;
|
|
||||||
addToHistogram(name: string, value: number, options?: MetricOptions): void;
|
|
||||||
configure(options: MetricGroupOptions): this;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ITelemetryRepository {
|
|
||||||
setup(options: { repositories: ClassConstructor<unknown>[] }): void;
|
|
||||||
api: IMetricGroupRepository;
|
|
||||||
host: IMetricGroupRepository;
|
|
||||||
jobs: IMetricGroupRepository;
|
|
||||||
repo: IMetricGroupRepository;
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
export const ITrashRepository = 'ITrashRepository';
|
|
||||||
|
|
||||||
export interface ITrashRepository {
|
|
||||||
empty(userId: string): Promise<number>;
|
|
||||||
restore(userId: string): Promise<number>;
|
|
||||||
restoreAll(assetIds: string[]): Promise<number>;
|
|
||||||
getDeletedIds(): AsyncIterableIterator<{ id: string }>;
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
import { VersionHistoryEntity } from 'src/entities/version-history.entity';
|
|
||||||
|
|
||||||
export const IVersionHistoryRepository = 'IVersionHistoryRepository';
|
|
||||||
|
|
||||||
export interface IVersionHistoryRepository {
|
|
||||||
create(version: Omit<VersionHistoryEntity, 'id' | 'createdAt'>): Promise<VersionHistoryEntity>;
|
|
||||||
getAll(): Promise<VersionHistoryEntity[]>;
|
|
||||||
getLatest(): Promise<VersionHistoryEntity | undefined>;
|
|
||||||
}
|
|
@ -4,10 +4,14 @@ import { InjectKysely } from 'nestjs-kysely';
|
|||||||
import { AlbumsSharedUsersUsers, DB } from 'src/db';
|
import { AlbumsSharedUsersUsers, DB } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { AlbumUserRole } from 'src/enum';
|
import { AlbumUserRole } from 'src/enum';
|
||||||
import { AlbumPermissionId, IAlbumUserRepository } from 'src/interfaces/album-user.interface';
|
|
||||||
|
export type AlbumPermissionId = {
|
||||||
|
albumsId: string;
|
||||||
|
usersId: string;
|
||||||
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class AlbumUserRepository implements IAlbumUserRepository {
|
export class AlbumUserRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }] })
|
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }] })
|
||||||
@ -16,10 +20,7 @@ export class AlbumUserRepository implements IAlbumUserRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }, { role: AlbumUserRole.VIEWER }] })
|
@GenerateSql({ params: [{ usersId: DummyValue.UUID, albumsId: DummyValue.UUID }, { role: AlbumUserRole.VIEWER }] })
|
||||||
update(
|
update({ usersId, albumsId }: AlbumPermissionId, dto: Updateable<AlbumsSharedUsersUsers>) {
|
||||||
{ usersId, albumsId }: AlbumPermissionId,
|
|
||||||
dto: Updateable<AlbumsSharedUsersUsers>,
|
|
||||||
): Promise<Selectable<AlbumsSharedUsersUsers>> {
|
|
||||||
return this.db
|
return this.db
|
||||||
.updateTable('albums_shared_users_users')
|
.updateTable('albums_shared_users_users')
|
||||||
.set(dto)
|
.set(dto)
|
||||||
|
@ -43,8 +43,8 @@ import {
|
|||||||
WithProperty,
|
WithProperty,
|
||||||
WithoutProperty,
|
WithoutProperty,
|
||||||
} from 'src/interfaces/asset.interface';
|
} from 'src/interfaces/asset.interface';
|
||||||
import { MapMarker, MapMarkerSearchOptions } from 'src/interfaces/map.interface';
|
|
||||||
import { AssetSearchOptions, SearchExploreItem, SearchExploreItemSet } from 'src/interfaces/search.interface';
|
import { AssetSearchOptions, SearchExploreItem, SearchExploreItemSet } from 'src/interfaces/search.interface';
|
||||||
|
import { MapMarker, MapMarkerSearchOptions } from 'src/repositories/map.repository';
|
||||||
import { anyUuid, asUuid, mapUpsertColumns } from 'src/utils/database';
|
import { anyUuid, asUuid, mapUpsertColumns } from 'src/utils/database';
|
||||||
import { Paginated, PaginationOptions, paginationHelper } from 'src/utils/pagination';
|
import { Paginated, PaginationOptions, paginationHelper } from 'src/utils/pagination';
|
||||||
|
|
||||||
|
@ -1,11 +1,24 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { SchedulerRegistry } from '@nestjs/schedule';
|
import { SchedulerRegistry } from '@nestjs/schedule';
|
||||||
import { CronJob, CronTime } from 'cron';
|
import { CronJob, CronTime } from 'cron';
|
||||||
import { CronCreate, CronUpdate, ICronRepository } from 'src/interfaces/cron.interface';
|
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
|
type CronBase = {
|
||||||
|
name: string;
|
||||||
|
start?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CronCreate = CronBase & {
|
||||||
|
expression: string;
|
||||||
|
onTick: () => void;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type CronUpdate = CronBase & {
|
||||||
|
expression?: string;
|
||||||
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class CronRepository implements ICronRepository {
|
export class CronRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private schedulerRegistry: SchedulerRegistry,
|
private schedulerRegistry: SchedulerRegistry,
|
||||||
private logger: LoggingRepository,
|
private logger: LoggingRepository,
|
||||||
|
@ -1,33 +1,23 @@
|
|||||||
import { IAlbumUserRepository } from 'src/interfaces/album-user.interface';
|
|
||||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { ICronRepository } from 'src/interfaces/cron.interface';
|
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||||
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository } from 'src/interfaces/job.interface';
|
import { IJobRepository } from 'src/interfaces/job.interface';
|
||||||
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
||||||
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
||||||
import { IMapRepository } from 'src/interfaces/map.interface';
|
|
||||||
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
|
|
||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
import { INotificationRepository } from 'src/interfaces/notification.interface';
|
|
||||||
import { IOAuthRepository } from 'src/interfaces/oauth.interface';
|
|
||||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
import { IProcessRepository } from 'src/interfaces/process.interface';
|
import { IProcessRepository } from 'src/interfaces/process.interface';
|
||||||
import { ISearchRepository } from 'src/interfaces/search.interface';
|
import { ISearchRepository } from 'src/interfaces/search.interface';
|
||||||
import { IServerInfoRepository } from 'src/interfaces/server-info.interface';
|
|
||||||
import { ISessionRepository } from 'src/interfaces/session.interface';
|
import { ISessionRepository } from 'src/interfaces/session.interface';
|
||||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
||||||
import { IStackRepository } from 'src/interfaces/stack.interface';
|
import { IStackRepository } from 'src/interfaces/stack.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { ITagRepository } from 'src/interfaces/tag.interface';
|
import { ITagRepository } from 'src/interfaces/tag.interface';
|
||||||
import { ITelemetryRepository } from 'src/interfaces/telemetry.interface';
|
|
||||||
import { ITrashRepository } from 'src/interfaces/trash.interface';
|
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { IVersionHistoryRepository } from 'src/interfaces/version-history.interface';
|
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||||
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||||
@ -71,44 +61,44 @@ import { ViewRepository } from 'src/repositories/view-repository';
|
|||||||
export const repositories = [
|
export const repositories = [
|
||||||
AccessRepository,
|
AccessRepository,
|
||||||
ActivityRepository,
|
ActivityRepository,
|
||||||
|
AlbumUserRepository,
|
||||||
AuditRepository,
|
AuditRepository,
|
||||||
ApiKeyRepository,
|
ApiKeyRepository,
|
||||||
ConfigRepository,
|
ConfigRepository,
|
||||||
|
CronRepository,
|
||||||
LoggingRepository,
|
LoggingRepository,
|
||||||
|
MapRepository,
|
||||||
MediaRepository,
|
MediaRepository,
|
||||||
MemoryRepository,
|
MemoryRepository,
|
||||||
|
MetadataRepository,
|
||||||
|
NotificationRepository,
|
||||||
|
OAuthRepository,
|
||||||
|
ServerInfoRepository,
|
||||||
|
TelemetryRepository,
|
||||||
|
TrashRepository,
|
||||||
ViewRepository,
|
ViewRepository,
|
||||||
|
VersionHistoryRepository,
|
||||||
];
|
];
|
||||||
|
|
||||||
export const providers = [
|
export const providers = [
|
||||||
{ provide: IAlbumRepository, useClass: AlbumRepository },
|
{ provide: IAlbumRepository, useClass: AlbumRepository },
|
||||||
{ provide: IAlbumUserRepository, useClass: AlbumUserRepository },
|
|
||||||
{ provide: IAssetRepository, useClass: AssetRepository },
|
{ provide: IAssetRepository, useClass: AssetRepository },
|
||||||
{ provide: ICronRepository, useClass: CronRepository },
|
|
||||||
{ provide: ICryptoRepository, useClass: CryptoRepository },
|
{ provide: ICryptoRepository, useClass: CryptoRepository },
|
||||||
{ provide: IDatabaseRepository, useClass: DatabaseRepository },
|
{ provide: IDatabaseRepository, useClass: DatabaseRepository },
|
||||||
{ provide: IEventRepository, useClass: EventRepository },
|
{ provide: IEventRepository, useClass: EventRepository },
|
||||||
{ provide: IJobRepository, useClass: JobRepository },
|
{ provide: IJobRepository, useClass: JobRepository },
|
||||||
{ provide: ILibraryRepository, useClass: LibraryRepository },
|
{ provide: ILibraryRepository, useClass: LibraryRepository },
|
||||||
{ provide: IMachineLearningRepository, useClass: MachineLearningRepository },
|
{ provide: IMachineLearningRepository, useClass: MachineLearningRepository },
|
||||||
{ provide: IMapRepository, useClass: MapRepository },
|
|
||||||
{ provide: IMetadataRepository, useClass: MetadataRepository },
|
|
||||||
{ provide: IMoveRepository, useClass: MoveRepository },
|
{ provide: IMoveRepository, useClass: MoveRepository },
|
||||||
{ provide: INotificationRepository, useClass: NotificationRepository },
|
|
||||||
{ provide: IOAuthRepository, useClass: OAuthRepository },
|
|
||||||
{ provide: IPartnerRepository, useClass: PartnerRepository },
|
{ provide: IPartnerRepository, useClass: PartnerRepository },
|
||||||
{ provide: IPersonRepository, useClass: PersonRepository },
|
{ provide: IPersonRepository, useClass: PersonRepository },
|
||||||
{ provide: IProcessRepository, useClass: ProcessRepository },
|
{ provide: IProcessRepository, useClass: ProcessRepository },
|
||||||
{ provide: ISearchRepository, useClass: SearchRepository },
|
{ provide: ISearchRepository, useClass: SearchRepository },
|
||||||
{ provide: IServerInfoRepository, useClass: ServerInfoRepository },
|
|
||||||
{ provide: ISessionRepository, useClass: SessionRepository },
|
{ provide: ISessionRepository, useClass: SessionRepository },
|
||||||
{ provide: ISharedLinkRepository, useClass: SharedLinkRepository },
|
{ provide: ISharedLinkRepository, useClass: SharedLinkRepository },
|
||||||
{ provide: IStackRepository, useClass: StackRepository },
|
{ provide: IStackRepository, useClass: StackRepository },
|
||||||
{ provide: IStorageRepository, useClass: StorageRepository },
|
{ provide: IStorageRepository, useClass: StorageRepository },
|
||||||
{ provide: ISystemMetadataRepository, useClass: SystemMetadataRepository },
|
{ provide: ISystemMetadataRepository, useClass: SystemMetadataRepository },
|
||||||
{ provide: ITagRepository, useClass: TagRepository },
|
{ provide: ITagRepository, useClass: TagRepository },
|
||||||
{ provide: ITelemetryRepository, useClass: TelemetryRepository },
|
|
||||||
{ provide: ITrashRepository, useClass: TrashRepository },
|
|
||||||
{ provide: IUserRepository, useClass: UserRepository },
|
{ provide: IUserRepository, useClass: UserRepository },
|
||||||
{ provide: IVersionHistoryRepository, useClass: VersionHistoryRepository },
|
|
||||||
];
|
];
|
||||||
|
@ -11,24 +11,41 @@ import { DB, GeodataPlaces, NaturalearthCountries } from 'src/db';
|
|||||||
import { AssetEntity, withExif } from 'src/entities/asset.entity';
|
import { AssetEntity, withExif } from 'src/entities/asset.entity';
|
||||||
import { NaturalEarthCountriesTempEntity } from 'src/entities/natural-earth-countries.entity';
|
import { NaturalEarthCountriesTempEntity } from 'src/entities/natural-earth-countries.entity';
|
||||||
import { LogLevel, SystemMetadataKey } from 'src/enum';
|
import { LogLevel, SystemMetadataKey } from 'src/enum';
|
||||||
import {
|
|
||||||
GeoPoint,
|
|
||||||
IMapRepository,
|
|
||||||
MapMarker,
|
|
||||||
MapMarkerSearchOptions,
|
|
||||||
ReverseGeocodeResult,
|
|
||||||
} from 'src/interfaces/map.interface';
|
|
||||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
|
export interface MapMarkerSearchOptions {
|
||||||
|
isArchived?: boolean;
|
||||||
|
isFavorite?: boolean;
|
||||||
|
fileCreatedBefore?: Date;
|
||||||
|
fileCreatedAfter?: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GeoPoint {
|
||||||
|
latitude: number;
|
||||||
|
longitude: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ReverseGeocodeResult {
|
||||||
|
country: string | null;
|
||||||
|
state: string | null;
|
||||||
|
city: string | null;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface MapMarker extends ReverseGeocodeResult {
|
||||||
|
id: string;
|
||||||
|
lat: number;
|
||||||
|
lon: number;
|
||||||
|
}
|
||||||
|
|
||||||
interface MapDB extends DB {
|
interface MapDB extends DB {
|
||||||
geodata_places_tmp: GeodataPlaces;
|
geodata_places_tmp: GeodataPlaces;
|
||||||
naturalearth_countries_tmp: NaturalearthCountries;
|
naturalearth_countries_tmp: NaturalearthCountries;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MapRepository implements IMapRepository {
|
export class MapRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private configRepository: ConfigRepository,
|
private configRepository: ConfigRepository,
|
||||||
@Inject(ISystemMetadataRepository) private metadataRepository: ISystemMetadataRepository,
|
@Inject(ISystemMetadataRepository) private metadataRepository: ISystemMetadataRepository,
|
||||||
|
@ -1,11 +1,72 @@
|
|||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { DefaultReadTaskOptions, ExifTool, Tags } from 'exiftool-vendored';
|
import { BinaryField, DefaultReadTaskOptions, ExifTool, Tags } from 'exiftool-vendored';
|
||||||
import geotz from 'geo-tz';
|
import geotz from 'geo-tz';
|
||||||
import { IMetadataRepository, ImmichTags } from 'src/interfaces/metadata.interface';
|
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
|
interface ExifDuration {
|
||||||
|
Value: number;
|
||||||
|
Scale?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
type StringOrNumber = string | number;
|
||||||
|
|
||||||
|
type TagsWithWrongTypes =
|
||||||
|
| 'FocalLength'
|
||||||
|
| 'Duration'
|
||||||
|
| 'Description'
|
||||||
|
| 'ImageDescription'
|
||||||
|
| 'RegionInfo'
|
||||||
|
| 'TagsList'
|
||||||
|
| 'Keywords'
|
||||||
|
| 'HierarchicalSubject'
|
||||||
|
| 'ISO';
|
||||||
|
|
||||||
|
export interface ImmichTags extends Omit<Tags, TagsWithWrongTypes> {
|
||||||
|
ContentIdentifier?: string;
|
||||||
|
MotionPhoto?: number;
|
||||||
|
MotionPhotoVersion?: number;
|
||||||
|
MotionPhotoPresentationTimestampUs?: number;
|
||||||
|
MediaGroupUUID?: string;
|
||||||
|
ImagePixelDepth?: string;
|
||||||
|
FocalLength?: number;
|
||||||
|
Duration?: number | string | ExifDuration;
|
||||||
|
EmbeddedVideoType?: string;
|
||||||
|
EmbeddedVideoFile?: BinaryField;
|
||||||
|
MotionPhotoVideo?: BinaryField;
|
||||||
|
TagsList?: StringOrNumber[];
|
||||||
|
HierarchicalSubject?: StringOrNumber[];
|
||||||
|
Keywords?: StringOrNumber | StringOrNumber[];
|
||||||
|
ISO?: number | number[];
|
||||||
|
|
||||||
|
// Type is wrong, can also be number.
|
||||||
|
Description?: StringOrNumber;
|
||||||
|
ImageDescription?: StringOrNumber;
|
||||||
|
|
||||||
|
// Extended properties for image regions, such as faces
|
||||||
|
RegionInfo?: {
|
||||||
|
AppliedToDimensions: {
|
||||||
|
W: number;
|
||||||
|
H: number;
|
||||||
|
Unit: string;
|
||||||
|
};
|
||||||
|
RegionList: {
|
||||||
|
Area: {
|
||||||
|
// (X,Y) // center of the rectangle
|
||||||
|
X: number;
|
||||||
|
Y: number;
|
||||||
|
W: number;
|
||||||
|
H: number;
|
||||||
|
Unit: string;
|
||||||
|
};
|
||||||
|
Rotation?: number;
|
||||||
|
Type?: string;
|
||||||
|
Name?: string;
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class MetadataRepository implements IMetadataRepository {
|
export class MetadataRepository {
|
||||||
private exiftool = new ExifTool({
|
private exiftool = new ExifTool({
|
||||||
defaultVideosToUTC: true,
|
defaultVideosToUTC: true,
|
||||||
backfillTimezones: true,
|
backfillTimezones: true,
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { EmailRenderRequest, EmailTemplate } from 'src/interfaces/notification.interface';
|
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
import { NotificationRepository } from 'src/repositories/notification.repository';
|
import { EmailRenderRequest, EmailTemplate, NotificationRepository } from 'src/repositories/notification.repository';
|
||||||
import { ILoggingRepository } from 'src/types';
|
import { ILoggingRepository } from 'src/types';
|
||||||
import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock';
|
import { newLoggingRepositoryMock } from 'test/repositories/logger.repository.mock';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
@ -6,18 +6,104 @@ import { AlbumInviteEmail } from 'src/emails/album-invite.email';
|
|||||||
import { AlbumUpdateEmail } from 'src/emails/album-update.email';
|
import { AlbumUpdateEmail } from 'src/emails/album-update.email';
|
||||||
import { TestEmail } from 'src/emails/test.email';
|
import { TestEmail } from 'src/emails/test.email';
|
||||||
import { WelcomeEmail } from 'src/emails/welcome.email';
|
import { WelcomeEmail } from 'src/emails/welcome.email';
|
||||||
import {
|
|
||||||
EmailRenderRequest,
|
|
||||||
EmailTemplate,
|
|
||||||
INotificationRepository,
|
|
||||||
SendEmailOptions,
|
|
||||||
SendEmailResponse,
|
|
||||||
SmtpOptions,
|
|
||||||
} from 'src/interfaces/notification.interface';
|
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
|
export type EmailImageAttachment = {
|
||||||
|
filename: string;
|
||||||
|
path: string;
|
||||||
|
cid: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SendEmailOptions = {
|
||||||
|
from: string;
|
||||||
|
to: string;
|
||||||
|
replyTo?: string;
|
||||||
|
subject: string;
|
||||||
|
html: string;
|
||||||
|
text: string;
|
||||||
|
imageAttachments?: EmailImageAttachment[];
|
||||||
|
smtp: SmtpOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SmtpOptions = {
|
||||||
|
host: string;
|
||||||
|
port?: number;
|
||||||
|
username?: string;
|
||||||
|
password?: string;
|
||||||
|
ignoreCert?: boolean;
|
||||||
|
};
|
||||||
|
|
||||||
|
export enum EmailTemplate {
|
||||||
|
TEST_EMAIL = 'test',
|
||||||
|
|
||||||
|
// AUTH
|
||||||
|
WELCOME = 'welcome',
|
||||||
|
RESET_PASSWORD = 'reset-password',
|
||||||
|
|
||||||
|
// ALBUM
|
||||||
|
ALBUM_INVITE = 'album-invite',
|
||||||
|
ALBUM_UPDATE = 'album-update',
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BaseEmailProps {
|
||||||
|
baseUrl: string;
|
||||||
|
customTemplate?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface TestEmailProps extends BaseEmailProps {
|
||||||
|
displayName: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface WelcomeEmailProps extends BaseEmailProps {
|
||||||
|
displayName: string;
|
||||||
|
username: string;
|
||||||
|
password?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlbumInviteEmailProps extends BaseEmailProps {
|
||||||
|
albumName: string;
|
||||||
|
albumId: string;
|
||||||
|
senderName: string;
|
||||||
|
recipientName: string;
|
||||||
|
cid?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface AlbumUpdateEmailProps extends BaseEmailProps {
|
||||||
|
albumName: string;
|
||||||
|
albumId: string;
|
||||||
|
recipientName: string;
|
||||||
|
cid?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type EmailRenderRequest =
|
||||||
|
| {
|
||||||
|
template: EmailTemplate.TEST_EMAIL;
|
||||||
|
data: TestEmailProps;
|
||||||
|
customTemplate: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
template: EmailTemplate.WELCOME;
|
||||||
|
data: WelcomeEmailProps;
|
||||||
|
customTemplate: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
template: EmailTemplate.ALBUM_INVITE;
|
||||||
|
data: AlbumInviteEmailProps;
|
||||||
|
customTemplate: string;
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
template: EmailTemplate.ALBUM_UPDATE;
|
||||||
|
data: AlbumUpdateEmailProps;
|
||||||
|
customTemplate: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type SendEmailResponse = {
|
||||||
|
messageId: string;
|
||||||
|
response: any;
|
||||||
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class NotificationRepository implements INotificationRepository {
|
export class NotificationRepository {
|
||||||
constructor(private logger: LoggingRepository) {
|
constructor(private logger: LoggingRepository) {
|
||||||
this.logger.setContext(NotificationRepository.name);
|
this.logger.setContext(NotificationRepository.name);
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,21 @@
|
|||||||
import { Injectable, InternalServerErrorException } from '@nestjs/common';
|
import { Injectable, InternalServerErrorException } from '@nestjs/common';
|
||||||
import { custom, generators, Issuer } from 'openid-client';
|
import { custom, generators, Issuer, UserinfoResponse } from 'openid-client';
|
||||||
import { IOAuthRepository, OAuthConfig, OAuthProfile } from 'src/interfaces/oauth.interface';
|
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
|
export type OAuthConfig = {
|
||||||
|
clientId: string;
|
||||||
|
clientSecret: string;
|
||||||
|
issuerUrl: string;
|
||||||
|
mobileOverrideEnabled: boolean;
|
||||||
|
mobileRedirectUri: string;
|
||||||
|
profileSigningAlgorithm: string;
|
||||||
|
scope: string;
|
||||||
|
signingAlgorithm: string;
|
||||||
|
};
|
||||||
|
export type OAuthProfile = UserinfoResponse;
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class OAuthRepository implements IOAuthRepository {
|
export class OAuthRepository {
|
||||||
constructor(private logger: LoggingRepository) {
|
constructor(private logger: LoggingRepository) {
|
||||||
this.logger.setContext(OAuthRepository.name);
|
this.logger.setContext(OAuthRepository.name);
|
||||||
}
|
}
|
||||||
|
@ -4,10 +4,27 @@ import { exec as execCallback } from 'node:child_process';
|
|||||||
import { readFile } from 'node:fs/promises';
|
import { readFile } from 'node:fs/promises';
|
||||||
import { promisify } from 'node:util';
|
import { promisify } from 'node:util';
|
||||||
import sharp from 'sharp';
|
import sharp from 'sharp';
|
||||||
import { GitHubRelease, IServerInfoRepository, ServerBuildVersions } from 'src/interfaces/server-info.interface';
|
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
|
export interface GitHubRelease {
|
||||||
|
id: number;
|
||||||
|
url: string;
|
||||||
|
tag_name: string;
|
||||||
|
name: string;
|
||||||
|
created_at: string;
|
||||||
|
published_at: string;
|
||||||
|
body: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ServerBuildVersions {
|
||||||
|
nodejs: string;
|
||||||
|
ffmpeg: string;
|
||||||
|
libvips: string;
|
||||||
|
exiftool: string;
|
||||||
|
imagemagick: string;
|
||||||
|
}
|
||||||
|
|
||||||
const exec = promisify(execCallback);
|
const exec = promisify(execCallback);
|
||||||
const maybeFirstLine = async (command: string): Promise<string> => {
|
const maybeFirstLine = async (command: string): Promise<string> => {
|
||||||
try {
|
try {
|
||||||
@ -34,7 +51,7 @@ const getLockfileVersion = (name: string, lockfile?: BuildLockfile) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class ServerInfoRepository implements IServerInfoRepository {
|
export class ServerInfoRepository {
|
||||||
constructor(
|
constructor(
|
||||||
private configRepository: ConfigRepository,
|
private configRepository: ConfigRepository,
|
||||||
private logger: LoggingRepository,
|
private logger: LoggingRepository,
|
||||||
|
@ -15,11 +15,12 @@ import { MetricService } from 'nestjs-otel';
|
|||||||
import { copyMetadataFromFunctionToFunction } from 'nestjs-otel/lib/opentelemetry.utils';
|
import { copyMetadataFromFunctionToFunction } from 'nestjs-otel/lib/opentelemetry.utils';
|
||||||
import { serverVersion } from 'src/constants';
|
import { serverVersion } from 'src/constants';
|
||||||
import { ImmichTelemetry, MetadataKey } from 'src/enum';
|
import { ImmichTelemetry, MetadataKey } from 'src/enum';
|
||||||
import { IMetricGroupRepository, ITelemetryRepository, MetricGroupOptions } from 'src/interfaces/telemetry.interface';
|
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
|
||||||
class MetricGroupRepository implements IMetricGroupRepository {
|
type MetricGroupOptions = { enabled: boolean };
|
||||||
|
|
||||||
|
export class MetricGroupRepository {
|
||||||
private enabled = false;
|
private enabled = false;
|
||||||
|
|
||||||
constructor(private metricService: MetricService) {}
|
constructor(private metricService: MetricService) {}
|
||||||
@ -86,7 +87,7 @@ export const teardownTelemetry = async () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class TelemetryRepository implements ITelemetryRepository {
|
export class TelemetryRepository {
|
||||||
api: MetricGroupRepository;
|
api: MetricGroupRepository;
|
||||||
host: MetricGroupRepository;
|
host: MetricGroupRepository;
|
||||||
jobs: MetricGroupRepository;
|
jobs: MetricGroupRepository;
|
||||||
|
@ -3,9 +3,8 @@ import { InjectKysely } from 'nestjs-kysely';
|
|||||||
import { DB } from 'src/db';
|
import { DB } from 'src/db';
|
||||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||||
import { AssetStatus } from 'src/enum';
|
import { AssetStatus } from 'src/enum';
|
||||||
import { ITrashRepository } from 'src/interfaces/trash.interface';
|
|
||||||
|
|
||||||
export class TrashRepository implements ITrashRepository {
|
export class TrashRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
getDeletedIds(): AsyncIterableIterator<{ id: string }> {
|
getDeletedIds(): AsyncIterableIterator<{ id: string }> {
|
||||||
|
@ -3,25 +3,23 @@ import { Insertable, Kysely } from 'kysely';
|
|||||||
import { InjectKysely } from 'nestjs-kysely';
|
import { InjectKysely } from 'nestjs-kysely';
|
||||||
import { DB, VersionHistory } from 'src/db';
|
import { DB, VersionHistory } from 'src/db';
|
||||||
import { GenerateSql } from 'src/decorators';
|
import { GenerateSql } from 'src/decorators';
|
||||||
import { VersionHistoryEntity } from 'src/entities/version-history.entity';
|
|
||||||
import { IVersionHistoryRepository } from 'src/interfaces/version-history.interface';
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class VersionHistoryRepository implements IVersionHistoryRepository {
|
export class VersionHistoryRepository {
|
||||||
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
constructor(@InjectKysely() private db: Kysely<DB>) {}
|
||||||
|
|
||||||
@GenerateSql()
|
@GenerateSql()
|
||||||
getAll(): Promise<VersionHistoryEntity[]> {
|
getAll() {
|
||||||
return this.db.selectFrom('version_history').selectAll().orderBy('createdAt', 'desc').execute();
|
return this.db.selectFrom('version_history').selectAll().orderBy('createdAt', 'desc').execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql()
|
@GenerateSql()
|
||||||
getLatest(): Promise<VersionHistoryEntity | undefined> {
|
getLatest() {
|
||||||
return this.db.selectFrom('version_history').selectAll().orderBy('createdAt', 'desc').executeTakeFirst();
|
return this.db.selectFrom('version_history').selectAll().orderBy('createdAt', 'desc').executeTakeFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [{ version: 'v1.123.0' }] })
|
@GenerateSql({ params: [{ version: 'v1.123.0' }] })
|
||||||
create(version: Insertable<VersionHistory>): Promise<VersionHistoryEntity> {
|
create(version: Insertable<VersionHistory>) {
|
||||||
return this.db.insertInto('version_history').values(version).returningAll().executeTakeFirstOrThrow();
|
return this.db.insertInto('version_history').values(version).returningAll().executeTakeFirstOrThrow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,11 @@ import { BadRequestException } from '@nestjs/common';
|
|||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdErrorReason } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AlbumUserRole } from 'src/enum';
|
import { AlbumUserRole } from 'src/enum';
|
||||||
import { IAlbumUserRepository } from 'src/interfaces/album-user.interface';
|
|
||||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { AlbumService } from 'src/services/album.service';
|
import { AlbumService } from 'src/services/album.service';
|
||||||
|
import { IAlbumUserRepository } from 'src/types';
|
||||||
import { albumStub } from 'test/fixtures/album.stub';
|
import { albumStub } from 'test/fixtures/album.stub';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { userStub } from 'test/fixtures/user.stub';
|
import { userStub } from 'test/fixtures/user.stub';
|
||||||
|
@ -5,13 +5,12 @@ import { UserEntity } from 'src/entities/user.entity';
|
|||||||
import { AuthType, Permission } from 'src/enum';
|
import { AuthType, Permission } from 'src/enum';
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IOAuthRepository } from 'src/interfaces/oauth.interface';
|
|
||||||
import { ISessionRepository } from 'src/interfaces/session.interface';
|
import { ISessionRepository } from 'src/interfaces/session.interface';
|
||||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
||||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { AuthService } from 'src/services/auth.service';
|
import { AuthService } from 'src/services/auth.service';
|
||||||
import { IApiKeyRepository } from 'src/types';
|
import { IApiKeyRepository, IOAuthRepository } from 'src/types';
|
||||||
import { keyStub } from 'test/fixtures/api-key.stub';
|
import { keyStub } from 'test/fixtures/api-key.stub';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { sessionStub } from 'test/fixtures/session.stub';
|
import { sessionStub } from 'test/fixtures/session.stub';
|
||||||
|
@ -19,7 +19,7 @@ import {
|
|||||||
import { UserAdminResponseDto, mapUserAdmin } from 'src/dtos/user.dto';
|
import { UserAdminResponseDto, mapUserAdmin } from 'src/dtos/user.dto';
|
||||||
import { UserEntity } from 'src/entities/user.entity';
|
import { UserEntity } from 'src/entities/user.entity';
|
||||||
import { AuthType, ImmichCookie, ImmichHeader, ImmichQuery, Permission } from 'src/enum';
|
import { AuthType, ImmichCookie, ImmichHeader, ImmichQuery, Permission } from 'src/enum';
|
||||||
import { OAuthProfile } from 'src/interfaces/oauth.interface';
|
import { OAuthProfile } from 'src/repositories/oauth.repository';
|
||||||
import { BaseService } from 'src/services/base.service';
|
import { BaseService } from 'src/services/base.service';
|
||||||
import { AuthApiKey } from 'src/types';
|
import { AuthApiKey } from 'src/types';
|
||||||
import { isGranted } from 'src/utils/access';
|
import { isGranted } from 'src/utils/access';
|
||||||
|
@ -2,14 +2,13 @@ import { PassThrough } from 'node:stream';
|
|||||||
import { defaults, SystemConfig } from 'src/config';
|
import { defaults, SystemConfig } from 'src/config';
|
||||||
import { StorageCore } from 'src/cores/storage.core';
|
import { StorageCore } from 'src/cores/storage.core';
|
||||||
import { ImmichWorker, StorageFolder } from 'src/enum';
|
import { ImmichWorker, StorageFolder } from 'src/enum';
|
||||||
import { ICronRepository } from 'src/interfaces/cron.interface';
|
|
||||||
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
||||||
import { JobStatus } from 'src/interfaces/job.interface';
|
import { JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { IProcessRepository } from 'src/interfaces/process.interface';
|
import { IProcessRepository } from 'src/interfaces/process.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { BackupService } from 'src/services/backup.service';
|
import { BackupService } from 'src/services/backup.service';
|
||||||
import { IConfigRepository } from 'src/types';
|
import { IConfigRepository, ICronRepository } from 'src/types';
|
||||||
import { systemConfigStub } from 'test/fixtures/system-config.stub';
|
import { systemConfigStub } from 'test/fixtures/system-config.stub';
|
||||||
import { mockSpawn, newTestService } from 'test/utils';
|
import { mockSpawn, newTestService } from 'test/utils';
|
||||||
import { describe, Mocked } from 'vitest';
|
import { describe, Mocked } from 'vitest';
|
||||||
|
@ -6,44 +6,44 @@ import { SALT_ROUNDS } from 'src/constants';
|
|||||||
import { StorageCore } from 'src/cores/storage.core';
|
import { StorageCore } from 'src/cores/storage.core';
|
||||||
import { Users } from 'src/db';
|
import { Users } from 'src/db';
|
||||||
import { UserEntity } from 'src/entities/user.entity';
|
import { UserEntity } from 'src/entities/user.entity';
|
||||||
import { IAlbumUserRepository } from 'src/interfaces/album-user.interface';
|
|
||||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { ICronRepository } from 'src/interfaces/cron.interface';
|
|
||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||||
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository } from 'src/interfaces/job.interface';
|
import { IJobRepository } from 'src/interfaces/job.interface';
|
||||||
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
||||||
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
import { IMachineLearningRepository } from 'src/interfaces/machine-learning.interface';
|
||||||
import { IMapRepository } from 'src/interfaces/map.interface';
|
|
||||||
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
|
|
||||||
import { IMoveRepository } from 'src/interfaces/move.interface';
|
import { IMoveRepository } from 'src/interfaces/move.interface';
|
||||||
import { INotificationRepository } from 'src/interfaces/notification.interface';
|
|
||||||
import { IOAuthRepository } from 'src/interfaces/oauth.interface';
|
|
||||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
import { IProcessRepository } from 'src/interfaces/process.interface';
|
import { IProcessRepository } from 'src/interfaces/process.interface';
|
||||||
import { ISearchRepository } from 'src/interfaces/search.interface';
|
import { ISearchRepository } from 'src/interfaces/search.interface';
|
||||||
import { IServerInfoRepository } from 'src/interfaces/server-info.interface';
|
|
||||||
import { ISessionRepository } from 'src/interfaces/session.interface';
|
import { ISessionRepository } from 'src/interfaces/session.interface';
|
||||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
import { ISharedLinkRepository } from 'src/interfaces/shared-link.interface';
|
||||||
import { IStackRepository } from 'src/interfaces/stack.interface';
|
import { IStackRepository } from 'src/interfaces/stack.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { ITagRepository } from 'src/interfaces/tag.interface';
|
import { ITagRepository } from 'src/interfaces/tag.interface';
|
||||||
import { ITelemetryRepository } from 'src/interfaces/telemetry.interface';
|
|
||||||
import { ITrashRepository } from 'src/interfaces/trash.interface';
|
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
import { IVersionHistoryRepository } from 'src/interfaces/version-history.interface';
|
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||||
|
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||||
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
||||||
import { AuditRepository } from 'src/repositories/audit.repository';
|
import { AuditRepository } from 'src/repositories/audit.repository';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
|
import { CronRepository } from 'src/repositories/cron.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
import { MapRepository } from 'src/repositories/map.repository';
|
||||||
import { MediaRepository } from 'src/repositories/media.repository';
|
import { MediaRepository } from 'src/repositories/media.repository';
|
||||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||||
|
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
||||||
|
import { NotificationRepository } from 'src/repositories/notification.repository';
|
||||||
|
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
||||||
|
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
||||||
|
import { TelemetryRepository } from 'src/repositories/telemetry.repository';
|
||||||
|
import { TrashRepository } from 'src/repositories/trash.repository';
|
||||||
|
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||||
import { ViewRepository } from 'src/repositories/view-repository';
|
import { ViewRepository } from 'src/repositories/view-repository';
|
||||||
import { AccessRequest, checkAccess, requireAccess } from 'src/utils/access';
|
import { AccessRequest, checkAccess, requireAccess } from 'src/utils/access';
|
||||||
import { getConfig, updateConfig } from 'src/utils/config';
|
import { getConfig, updateConfig } from 'src/utils/config';
|
||||||
@ -57,10 +57,10 @@ export class BaseService {
|
|||||||
protected activityRepository: ActivityRepository,
|
protected activityRepository: ActivityRepository,
|
||||||
protected auditRepository: AuditRepository,
|
protected auditRepository: AuditRepository,
|
||||||
@Inject(IAlbumRepository) protected albumRepository: IAlbumRepository,
|
@Inject(IAlbumRepository) protected albumRepository: IAlbumRepository,
|
||||||
@Inject(IAlbumUserRepository) protected albumUserRepository: IAlbumUserRepository,
|
protected albumUserRepository: AlbumUserRepository,
|
||||||
@Inject(IAssetRepository) protected assetRepository: IAssetRepository,
|
@Inject(IAssetRepository) protected assetRepository: IAssetRepository,
|
||||||
protected configRepository: ConfigRepository,
|
protected configRepository: ConfigRepository,
|
||||||
@Inject(ICronRepository) protected cronRepository: ICronRepository,
|
protected cronRepository: CronRepository,
|
||||||
@Inject(ICryptoRepository) protected cryptoRepository: ICryptoRepository,
|
@Inject(ICryptoRepository) protected cryptoRepository: ICryptoRepository,
|
||||||
@Inject(IDatabaseRepository) protected databaseRepository: IDatabaseRepository,
|
@Inject(IDatabaseRepository) protected databaseRepository: IDatabaseRepository,
|
||||||
@Inject(IEventRepository) protected eventRepository: IEventRepository,
|
@Inject(IEventRepository) protected eventRepository: IEventRepository,
|
||||||
@ -68,28 +68,28 @@ export class BaseService {
|
|||||||
protected keyRepository: ApiKeyRepository,
|
protected keyRepository: ApiKeyRepository,
|
||||||
@Inject(ILibraryRepository) protected libraryRepository: ILibraryRepository,
|
@Inject(ILibraryRepository) protected libraryRepository: ILibraryRepository,
|
||||||
@Inject(IMachineLearningRepository) protected machineLearningRepository: IMachineLearningRepository,
|
@Inject(IMachineLearningRepository) protected machineLearningRepository: IMachineLearningRepository,
|
||||||
@Inject(IMapRepository) protected mapRepository: IMapRepository,
|
protected mapRepository: MapRepository,
|
||||||
protected mediaRepository: MediaRepository,
|
protected mediaRepository: MediaRepository,
|
||||||
protected memoryRepository: MemoryRepository,
|
protected memoryRepository: MemoryRepository,
|
||||||
@Inject(IMetadataRepository) protected metadataRepository: IMetadataRepository,
|
protected metadataRepository: MetadataRepository,
|
||||||
@Inject(IMoveRepository) protected moveRepository: IMoveRepository,
|
@Inject(IMoveRepository) protected moveRepository: IMoveRepository,
|
||||||
@Inject(INotificationRepository) protected notificationRepository: INotificationRepository,
|
protected notificationRepository: NotificationRepository,
|
||||||
@Inject(IOAuthRepository) protected oauthRepository: IOAuthRepository,
|
protected oauthRepository: OAuthRepository,
|
||||||
@Inject(IPartnerRepository) protected partnerRepository: IPartnerRepository,
|
@Inject(IPartnerRepository) protected partnerRepository: IPartnerRepository,
|
||||||
@Inject(IPersonRepository) protected personRepository: IPersonRepository,
|
@Inject(IPersonRepository) protected personRepository: IPersonRepository,
|
||||||
@Inject(IProcessRepository) protected processRepository: IProcessRepository,
|
@Inject(IProcessRepository) protected processRepository: IProcessRepository,
|
||||||
@Inject(ISearchRepository) protected searchRepository: ISearchRepository,
|
@Inject(ISearchRepository) protected searchRepository: ISearchRepository,
|
||||||
@Inject(IServerInfoRepository) protected serverInfoRepository: IServerInfoRepository,
|
protected serverInfoRepository: ServerInfoRepository,
|
||||||
@Inject(ISessionRepository) protected sessionRepository: ISessionRepository,
|
@Inject(ISessionRepository) protected sessionRepository: ISessionRepository,
|
||||||
@Inject(ISharedLinkRepository) protected sharedLinkRepository: ISharedLinkRepository,
|
@Inject(ISharedLinkRepository) protected sharedLinkRepository: ISharedLinkRepository,
|
||||||
@Inject(IStackRepository) protected stackRepository: IStackRepository,
|
@Inject(IStackRepository) protected stackRepository: IStackRepository,
|
||||||
@Inject(IStorageRepository) protected storageRepository: IStorageRepository,
|
@Inject(IStorageRepository) protected storageRepository: IStorageRepository,
|
||||||
@Inject(ISystemMetadataRepository) protected systemMetadataRepository: ISystemMetadataRepository,
|
@Inject(ISystemMetadataRepository) protected systemMetadataRepository: ISystemMetadataRepository,
|
||||||
@Inject(ITagRepository) protected tagRepository: ITagRepository,
|
@Inject(ITagRepository) protected tagRepository: ITagRepository,
|
||||||
@Inject(ITelemetryRepository) protected telemetryRepository: ITelemetryRepository,
|
protected telemetryRepository: TelemetryRepository,
|
||||||
@Inject(ITrashRepository) protected trashRepository: ITrashRepository,
|
protected trashRepository: TrashRepository,
|
||||||
@Inject(IUserRepository) protected userRepository: IUserRepository,
|
@Inject(IUserRepository) protected userRepository: IUserRepository,
|
||||||
@Inject(IVersionHistoryRepository) protected versionRepository: IVersionHistoryRepository,
|
protected versionRepository: VersionHistoryRepository,
|
||||||
protected viewRepository: ViewRepository,
|
protected viewRepository: ViewRepository,
|
||||||
) {
|
) {
|
||||||
this.logger.setContext(this.constructor.name);
|
this.logger.setContext(this.constructor.name);
|
||||||
|
@ -3,10 +3,10 @@ import { defaults, SystemConfig } from 'src/config';
|
|||||||
import { ImmichWorker } from 'src/enum';
|
import { ImmichWorker } from 'src/enum';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { IJobRepository, JobCommand, JobItem, JobName, JobStatus, QueueName } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobCommand, JobItem, JobName, JobStatus, QueueName } from 'src/interfaces/job.interface';
|
||||||
import { ITelemetryRepository } from 'src/interfaces/telemetry.interface';
|
|
||||||
import { JobService } from 'src/services/job.service';
|
import { JobService } from 'src/services/job.service';
|
||||||
import { IConfigRepository, ILoggingRepository } from 'src/types';
|
import { IConfigRepository, ILoggingRepository } from 'src/types';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
|
import { ITelemetryRepositoryMock } from 'test/repositories/telemetry.repository.mock';
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
@ -16,7 +16,7 @@ describe(JobService.name, () => {
|
|||||||
let configMock: Mocked<IConfigRepository>;
|
let configMock: Mocked<IConfigRepository>;
|
||||||
let jobMock: Mocked<IJobRepository>;
|
let jobMock: Mocked<IJobRepository>;
|
||||||
let loggerMock: Mocked<ILoggingRepository>;
|
let loggerMock: Mocked<ILoggingRepository>;
|
||||||
let telemetryMock: Mocked<ITelemetryRepository>;
|
let telemetryMock: ITelemetryRepositoryMock;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
({ sut, assetMock, configMock, jobMock, loggerMock, telemetryMock } = newTestService(JobService, {}));
|
({ sut, assetMock, configMock, jobMock, loggerMock, telemetryMock } = newTestService(JobService, {}));
|
||||||
|
@ -5,7 +5,6 @@ import { mapLibrary } from 'src/dtos/library.dto';
|
|||||||
import { UserEntity } from 'src/entities/user.entity';
|
import { UserEntity } from 'src/entities/user.entity';
|
||||||
import { AssetType, ImmichWorker } from 'src/enum';
|
import { AssetType, ImmichWorker } from 'src/enum';
|
||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { ICronRepository } from 'src/interfaces/cron.interface';
|
|
||||||
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
import { IDatabaseRepository } from 'src/interfaces/database.interface';
|
||||||
import {
|
import {
|
||||||
IJobRepository,
|
IJobRepository,
|
||||||
@ -18,7 +17,7 @@ import {
|
|||||||
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
import { ILibraryRepository } from 'src/interfaces/library.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
import { LibraryService } from 'src/services/library.service';
|
import { LibraryService } from 'src/services/library.service';
|
||||||
import { IConfigRepository } from 'src/types';
|
import { IConfigRepository, ICronRepository } from 'src/types';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { libraryStub } from 'test/fixtures/library.stub';
|
import { libraryStub } from 'test/fixtures/library.stub';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
import { IAlbumRepository } from 'src/interfaces/album.interface';
|
||||||
import { IMapRepository } from 'src/interfaces/map.interface';
|
|
||||||
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
import { IPartnerRepository } from 'src/interfaces/partner.interface';
|
||||||
import { MapService } from 'src/services/map.service';
|
import { MapService } from 'src/services/map.service';
|
||||||
|
import { IMapRepository } from 'src/types';
|
||||||
import { albumStub } from 'test/fixtures/album.stub';
|
import { albumStub } from 'test/fixtures/album.stub';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
|
@ -10,15 +10,14 @@ import { IAssetRepository, WithoutProperty } from 'src/interfaces/asset.interfac
|
|||||||
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
import { ICryptoRepository } from 'src/interfaces/crypto.interface';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { IMapRepository } from 'src/interfaces/map.interface';
|
|
||||||
import { IMetadataRepository, ImmichTags } from 'src/interfaces/metadata.interface';
|
|
||||||
import { IPersonRepository } from 'src/interfaces/person.interface';
|
import { IPersonRepository } from 'src/interfaces/person.interface';
|
||||||
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
import { IStorageRepository } from 'src/interfaces/storage.interface';
|
||||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { ITagRepository } from 'src/interfaces/tag.interface';
|
import { ITagRepository } from 'src/interfaces/tag.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
|
import { ImmichTags } from 'src/repositories/metadata.repository';
|
||||||
import { MetadataService } from 'src/services/metadata.service';
|
import { MetadataService } from 'src/services/metadata.service';
|
||||||
import { IConfigRepository, IMediaRepository } from 'src/types';
|
import { IConfigRepository, IMapRepository, IMediaRepository, IMetadataRepository } from 'src/types';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { fileStub } from 'test/fixtures/file.stub';
|
import { fileStub } from 'test/fixtures/file.stub';
|
||||||
import { probeStub } from 'test/fixtures/media.stub';
|
import { probeStub } from 'test/fixtures/media.stub';
|
||||||
|
@ -18,8 +18,8 @@ import { WithoutProperty } from 'src/interfaces/asset.interface';
|
|||||||
import { DatabaseLock } from 'src/interfaces/database.interface';
|
import { DatabaseLock } from 'src/interfaces/database.interface';
|
||||||
import { ArgOf } from 'src/interfaces/event.interface';
|
import { ArgOf } from 'src/interfaces/event.interface';
|
||||||
import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface';
|
import { JobName, JobOf, JOBS_ASSET_PAGINATION_SIZE, JobStatus, QueueName } from 'src/interfaces/job.interface';
|
||||||
import { ReverseGeocodeResult } from 'src/interfaces/map.interface';
|
import { ReverseGeocodeResult } from 'src/repositories/map.repository';
|
||||||
import { ImmichTags } from 'src/interfaces/metadata.interface';
|
import { ImmichTags } from 'src/repositories/metadata.repository';
|
||||||
import { BaseService } from 'src/services/base.service';
|
import { BaseService } from 'src/services/base.service';
|
||||||
import { isFaceImportEnabled } from 'src/utils/misc';
|
import { isFaceImportEnabled } from 'src/utils/misc';
|
||||||
import { usePagination } from 'src/utils/pagination';
|
import { usePagination } from 'src/utils/pagination';
|
||||||
|
@ -8,10 +8,11 @@ import { IAlbumRepository } from 'src/interfaces/album.interface';
|
|||||||
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
import { IAssetRepository } from 'src/interfaces/asset.interface';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository, INotifyAlbumUpdateJob, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, INotifyAlbumUpdateJob, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { EmailTemplate, INotificationRepository } from 'src/interfaces/notification.interface';
|
|
||||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IUserRepository } from 'src/interfaces/user.interface';
|
import { IUserRepository } from 'src/interfaces/user.interface';
|
||||||
|
import { EmailTemplate } from 'src/repositories/notification.repository';
|
||||||
import { NotificationService } from 'src/services/notification.service';
|
import { NotificationService } from 'src/services/notification.service';
|
||||||
|
import { INotificationRepository } from 'src/types';
|
||||||
import { albumStub } from 'test/fixtures/album.stub';
|
import { albumStub } from 'test/fixtures/album.stub';
|
||||||
import { assetStub } from 'test/fixtures/asset.stub';
|
import { assetStub } from 'test/fixtures/asset.stub';
|
||||||
import { userStub } from 'test/fixtures/user.stub';
|
import { userStub } from 'test/fixtures/user.stub';
|
||||||
|
@ -12,7 +12,7 @@ import {
|
|||||||
JobStatus,
|
JobStatus,
|
||||||
QueueName,
|
QueueName,
|
||||||
} from 'src/interfaces/job.interface';
|
} from 'src/interfaces/job.interface';
|
||||||
import { EmailImageAttachment, EmailTemplate } from 'src/interfaces/notification.interface';
|
import { EmailImageAttachment, EmailTemplate } from 'src/repositories/notification.repository';
|
||||||
import { BaseService } from 'src/services/base.service';
|
import { BaseService } from 'src/services/base.service';
|
||||||
import { getAssetFiles } from 'src/utils/asset.util';
|
import { getAssetFiles } from 'src/utils/asset.util';
|
||||||
import { getFilenameExtension } from 'src/utils/file';
|
import { getFilenameExtension } from 'src/utils/file';
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { BadRequestException } from '@nestjs/common';
|
import { BadRequestException } from '@nestjs/common';
|
||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { ITrashRepository } from 'src/interfaces/trash.interface';
|
|
||||||
import { TrashService } from 'src/services/trash.service';
|
import { TrashService } from 'src/services/trash.service';
|
||||||
|
import { ITrashRepository } from 'src/types';
|
||||||
import { authStub } from 'test/fixtures/auth.stub';
|
import { authStub } from 'test/fixtures/auth.stub';
|
||||||
import { IAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
import { IAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
|
@ -4,11 +4,9 @@ import { serverVersion } from 'src/constants';
|
|||||||
import { ImmichEnvironment, SystemMetadataKey } from 'src/enum';
|
import { ImmichEnvironment, SystemMetadataKey } from 'src/enum';
|
||||||
import { IEventRepository } from 'src/interfaces/event.interface';
|
import { IEventRepository } from 'src/interfaces/event.interface';
|
||||||
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
import { IJobRepository, JobName, JobStatus } from 'src/interfaces/job.interface';
|
||||||
import { IServerInfoRepository } from 'src/interfaces/server-info.interface';
|
|
||||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.interface';
|
||||||
import { IVersionHistoryRepository } from 'src/interfaces/version-history.interface';
|
|
||||||
import { VersionService } from 'src/services/version.service';
|
import { VersionService } from 'src/services/version.service';
|
||||||
import { IConfigRepository, ILoggingRepository } from 'src/types';
|
import { IConfigRepository, ILoggingRepository, IServerInfoRepository, IVersionHistoryRepository } from 'src/types';
|
||||||
import { mockEnvData } from 'test/repositories/config.repository.mock';
|
import { mockEnvData } from 'test/repositories/config.repository.mock';
|
||||||
import { newTestService } from 'test/utils';
|
import { newTestService } from 'test/utils';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
@ -2,12 +2,22 @@ import { UserEntity } from 'src/entities/user.entity';
|
|||||||
import { ExifOrientation, ImageFormat, Permission, TranscodeTarget, VideoCodec } from 'src/enum';
|
import { ExifOrientation, ImageFormat, Permission, TranscodeTarget, VideoCodec } from 'src/enum';
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||||
|
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||||
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
||||||
import { AuditRepository } from 'src/repositories/audit.repository';
|
import { AuditRepository } from 'src/repositories/audit.repository';
|
||||||
import { ConfigRepository } from 'src/repositories/config.repository';
|
import { ConfigRepository } from 'src/repositories/config.repository';
|
||||||
|
import { CronRepository } from 'src/repositories/cron.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
import { MapRepository } from 'src/repositories/map.repository';
|
||||||
import { MediaRepository } from 'src/repositories/media.repository';
|
import { MediaRepository } from 'src/repositories/media.repository';
|
||||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||||
|
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
||||||
|
import { NotificationRepository } from 'src/repositories/notification.repository';
|
||||||
|
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
||||||
|
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
||||||
|
import { MetricGroupRepository, TelemetryRepository } from 'src/repositories/telemetry.repository';
|
||||||
|
import { TrashRepository } from 'src/repositories/trash.repository';
|
||||||
|
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||||
import { ViewRepository } from 'src/repositories/view-repository';
|
import { ViewRepository } from 'src/repositories/view-repository';
|
||||||
|
|
||||||
export type DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T;
|
export type DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T;
|
||||||
@ -23,9 +33,11 @@ export type RepositoryInterface<T extends object> = Pick<T, keyof T>;
|
|||||||
|
|
||||||
export type IActivityRepository = RepositoryInterface<ActivityRepository>;
|
export type IActivityRepository = RepositoryInterface<ActivityRepository>;
|
||||||
export type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInterface<AccessRepository[K]> };
|
export type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInterface<AccessRepository[K]> };
|
||||||
|
export type IAlbumUserRepository = RepositoryInterface<AlbumUserRepository>;
|
||||||
export type IApiKeyRepository = RepositoryInterface<ApiKeyRepository>;
|
export type IApiKeyRepository = RepositoryInterface<ApiKeyRepository>;
|
||||||
export type IAuditRepository = RepositoryInterface<AuditRepository>;
|
export type IAuditRepository = RepositoryInterface<AuditRepository>;
|
||||||
export type IConfigRepository = RepositoryInterface<ConfigRepository>;
|
export type IConfigRepository = RepositoryInterface<ConfigRepository>;
|
||||||
|
export type ICronRepository = RepositoryInterface<CronRepository>;
|
||||||
export type ILoggingRepository = Pick<
|
export type ILoggingRepository = Pick<
|
||||||
LoggingRepository,
|
LoggingRepository,
|
||||||
| 'verbose'
|
| 'verbose'
|
||||||
@ -39,9 +51,18 @@ export type ILoggingRepository = Pick<
|
|||||||
| 'setContext'
|
| 'setContext'
|
||||||
| 'setAppName'
|
| 'setAppName'
|
||||||
>;
|
>;
|
||||||
|
export type IMapRepository = RepositoryInterface<MapRepository>;
|
||||||
export type IMediaRepository = RepositoryInterface<MediaRepository>;
|
export type IMediaRepository = RepositoryInterface<MediaRepository>;
|
||||||
export type IMemoryRepository = RepositoryInterface<MemoryRepository>;
|
export type IMemoryRepository = RepositoryInterface<MemoryRepository>;
|
||||||
|
export type IMetadataRepository = RepositoryInterface<MetadataRepository>;
|
||||||
|
export type IMetricGroupRepository = RepositoryInterface<MetricGroupRepository>;
|
||||||
|
export type INotificationRepository = RepositoryInterface<NotificationRepository>;
|
||||||
|
export type IOAuthRepository = RepositoryInterface<OAuthRepository>;
|
||||||
|
export type IServerInfoRepository = RepositoryInterface<ServerInfoRepository>;
|
||||||
|
export type ITelemetryRepository = RepositoryInterface<TelemetryRepository>;
|
||||||
|
export type ITrashRepository = RepositoryInterface<TrashRepository>;
|
||||||
export type IViewRepository = RepositoryInterface<ViewRepository>;
|
export type IViewRepository = RepositoryInterface<ViewRepository>;
|
||||||
|
export type IVersionHistoryRepository = RepositoryInterface<VersionHistoryRepository>;
|
||||||
|
|
||||||
export type ActivityItem =
|
export type ActivityItem =
|
||||||
| Awaited<ReturnType<IActivityRepository['create']>>
|
| Awaited<ReturnType<IActivityRepository['create']>>
|
||||||
|
2
server/test/fixtures/metadata.stub.ts
vendored
2
server/test/fixtures/metadata.stub.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
import { ImmichTags } from 'src/interfaces/metadata.interface';
|
import { ImmichTags } from 'src/repositories/metadata.repository';
|
||||||
import { personStub } from 'test/fixtures/person.stub';
|
import { personStub } from 'test/fixtures/person.stub';
|
||||||
|
|
||||||
export const metadataStub = {
|
export const metadataStub = {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IAlbumUserRepository } from 'src/interfaces/album-user.interface';
|
import { IAlbumUserRepository } from 'src/types';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
export const newAlbumUserRepositoryMock = (): Mocked<IAlbumUserRepository> => {
|
export const newAlbumUserRepositoryMock = (): Mocked<IAlbumUserRepository> => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ICronRepository } from 'src/interfaces/cron.interface';
|
import { ICronRepository } from 'src/types';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
export const newCronRepositoryMock = (): Mocked<ICronRepository> => {
|
export const newCronRepositoryMock = (): Mocked<ICronRepository> => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IMapRepository } from 'src/interfaces/map.interface';
|
import { IMapRepository } from 'src/types';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
export const newMapRepositoryMock = (): Mocked<IMapRepository> => {
|
export const newMapRepositoryMock = (): Mocked<IMapRepository> => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
|
import { IMetadataRepository } from 'src/types';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
export const newMetadataRepositoryMock = (): Mocked<IMetadataRepository> => {
|
export const newMetadataRepositoryMock = (): Mocked<IMetadataRepository> => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { INotificationRepository } from 'src/interfaces/notification.interface';
|
import { INotificationRepository } from 'src/types';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
export const newNotificationRepositoryMock = (): Mocked<INotificationRepository> => {
|
export const newNotificationRepositoryMock = (): Mocked<INotificationRepository> => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IOAuthRepository } from 'src/interfaces/oauth.interface';
|
import { IOAuthRepository } from 'src/types';
|
||||||
import { Mocked } from 'vitest';
|
import { Mocked } from 'vitest';
|
||||||
|
|
||||||
export const newOAuthRepositoryMock = (): Mocked<IOAuthRepository> => {
|
export const newOAuthRepositoryMock = (): Mocked<IOAuthRepository> => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IServerInfoRepository } from 'src/interfaces/server-info.interface';
|
import { IServerInfoRepository } from 'src/types';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
export const newServerInfoRepositoryMock = (): Mocked<IServerInfoRepository> => {
|
export const newServerInfoRepositoryMock = (): Mocked<IServerInfoRepository> => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ITelemetryRepository } from 'src/interfaces/telemetry.interface';
|
import { ITelemetryRepository, RepositoryInterface } from 'src/types';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
const newMetricGroupMock = () => {
|
const newMetricGroupMock = () => {
|
||||||
@ -10,7 +10,11 @@ const newMetricGroupMock = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const newTelemetryRepositoryMock = (): Mocked<ITelemetryRepository> => {
|
export type ITelemetryRepositoryMock = {
|
||||||
|
[K in keyof ITelemetryRepository]: Mocked<RepositoryInterface<ITelemetryRepository[K]>>;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const newTelemetryRepositoryMock = (): ITelemetryRepositoryMock => {
|
||||||
return {
|
return {
|
||||||
setup: vitest.fn(),
|
setup: vitest.fn(),
|
||||||
api: newMetricGroupMock(),
|
api: newMetricGroupMock(),
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { ITrashRepository } from 'src/interfaces/trash.interface';
|
import { ITrashRepository } from 'src/types';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
export const newTrashRepositoryMock = (): Mocked<ITrashRepository> => {
|
export const newTrashRepositoryMock = (): Mocked<ITrashRepository> => {
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { IVersionHistoryRepository } from 'src/interfaces/version-history.interface';
|
import { IVersionHistoryRepository } from 'src/types';
|
||||||
import { Mocked, vitest } from 'vitest';
|
import { Mocked, vitest } from 'vitest';
|
||||||
|
|
||||||
export const newVersionHistoryRepositoryMock = (): Mocked<IVersionHistoryRepository> => {
|
export const newVersionHistoryRepositoryMock = (): Mocked<IVersionHistoryRepository> => {
|
||||||
|
@ -2,24 +2,42 @@ import { ChildProcessWithoutNullStreams } from 'node:child_process';
|
|||||||
import { Writable } from 'node:stream';
|
import { Writable } from 'node:stream';
|
||||||
import { PNG } from 'pngjs';
|
import { PNG } from 'pngjs';
|
||||||
import { ImmichWorker } from 'src/enum';
|
import { ImmichWorker } from 'src/enum';
|
||||||
import { IMetadataRepository } from 'src/interfaces/metadata.interface';
|
|
||||||
import { AccessRepository } from 'src/repositories/access.repository';
|
import { AccessRepository } from 'src/repositories/access.repository';
|
||||||
import { ActivityRepository } from 'src/repositories/activity.repository';
|
import { ActivityRepository } from 'src/repositories/activity.repository';
|
||||||
|
import { AlbumUserRepository } from 'src/repositories/album-user.repository';
|
||||||
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
import { ApiKeyRepository } from 'src/repositories/api-key.repository';
|
||||||
import { AuditRepository } from 'src/repositories/audit.repository';
|
import { AuditRepository } from 'src/repositories/audit.repository';
|
||||||
|
import { CronRepository } from 'src/repositories/cron.repository';
|
||||||
import { LoggingRepository } from 'src/repositories/logging.repository';
|
import { LoggingRepository } from 'src/repositories/logging.repository';
|
||||||
|
import { MapRepository } from 'src/repositories/map.repository';
|
||||||
import { MediaRepository } from 'src/repositories/media.repository';
|
import { MediaRepository } from 'src/repositories/media.repository';
|
||||||
import { MemoryRepository } from 'src/repositories/memory.repository';
|
import { MemoryRepository } from 'src/repositories/memory.repository';
|
||||||
|
import { MetadataRepository } from 'src/repositories/metadata.repository';
|
||||||
|
import { NotificationRepository } from 'src/repositories/notification.repository';
|
||||||
|
import { OAuthRepository } from 'src/repositories/oauth.repository';
|
||||||
|
import { ServerInfoRepository } from 'src/repositories/server-info.repository';
|
||||||
|
import { TelemetryRepository } from 'src/repositories/telemetry.repository';
|
||||||
|
import { TrashRepository } from 'src/repositories/trash.repository';
|
||||||
|
import { VersionHistoryRepository } from 'src/repositories/version-history.repository';
|
||||||
import { ViewRepository } from 'src/repositories/view-repository';
|
import { ViewRepository } from 'src/repositories/view-repository';
|
||||||
import { BaseService } from 'src/services/base.service';
|
import { BaseService } from 'src/services/base.service';
|
||||||
import {
|
import {
|
||||||
IAccessRepository,
|
IAccessRepository,
|
||||||
IActivityRepository,
|
IActivityRepository,
|
||||||
|
IAlbumUserRepository,
|
||||||
IApiKeyRepository,
|
IApiKeyRepository,
|
||||||
IAuditRepository,
|
IAuditRepository,
|
||||||
|
ICronRepository,
|
||||||
ILoggingRepository,
|
ILoggingRepository,
|
||||||
|
IMapRepository,
|
||||||
IMediaRepository,
|
IMediaRepository,
|
||||||
IMemoryRepository,
|
IMemoryRepository,
|
||||||
|
IMetadataRepository,
|
||||||
|
INotificationRepository,
|
||||||
|
IOAuthRepository,
|
||||||
|
IServerInfoRepository,
|
||||||
|
ITrashRepository,
|
||||||
|
IVersionHistoryRepository,
|
||||||
IViewRepository,
|
IViewRepository,
|
||||||
} from 'src/types';
|
} from 'src/types';
|
||||||
import { newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
import { newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
||||||
@ -66,7 +84,7 @@ import { Mocked, vitest } from 'vitest';
|
|||||||
|
|
||||||
type Overrides = {
|
type Overrides = {
|
||||||
worker?: ImmichWorker;
|
worker?: ImmichWorker;
|
||||||
metadataRepository?: IMetadataRepository;
|
metadataRepository?: MetadataRepository;
|
||||||
};
|
};
|
||||||
type BaseServiceArgs = ConstructorParameters<typeof BaseService>;
|
type BaseServiceArgs = ConstructorParameters<typeof BaseService>;
|
||||||
type Constructor<Type, Args extends Array<any>> = {
|
type Constructor<Type, Args extends Array<any>> = {
|
||||||
@ -125,10 +143,10 @@ export const newTestService = <T extends BaseService>(
|
|||||||
activityMock as IActivityRepository as ActivityRepository,
|
activityMock as IActivityRepository as ActivityRepository,
|
||||||
auditMock as IAuditRepository as AuditRepository,
|
auditMock as IAuditRepository as AuditRepository,
|
||||||
albumMock,
|
albumMock,
|
||||||
albumUserMock,
|
albumUserMock as IAlbumUserRepository as AlbumUserRepository,
|
||||||
assetMock,
|
assetMock,
|
||||||
configMock,
|
configMock,
|
||||||
cronMock,
|
cronMock as ICronRepository as CronRepository,
|
||||||
cryptoMock,
|
cryptoMock,
|
||||||
databaseMock,
|
databaseMock,
|
||||||
eventMock,
|
eventMock,
|
||||||
@ -136,28 +154,28 @@ export const newTestService = <T extends BaseService>(
|
|||||||
keyMock as IApiKeyRepository as ApiKeyRepository,
|
keyMock as IApiKeyRepository as ApiKeyRepository,
|
||||||
libraryMock,
|
libraryMock,
|
||||||
machineLearningMock,
|
machineLearningMock,
|
||||||
mapMock,
|
mapMock as IMapRepository as MapRepository,
|
||||||
mediaMock as IMediaRepository as MediaRepository,
|
mediaMock as IMediaRepository as MediaRepository,
|
||||||
memoryMock as IMemoryRepository as MemoryRepository,
|
memoryMock as IMemoryRepository as MemoryRepository,
|
||||||
metadataMock,
|
metadataMock as IMetadataRepository as MetadataRepository,
|
||||||
moveMock,
|
moveMock,
|
||||||
notificationMock,
|
notificationMock as INotificationRepository as NotificationRepository,
|
||||||
oauthMock,
|
oauthMock as IOAuthRepository as OAuthRepository,
|
||||||
partnerMock,
|
partnerMock,
|
||||||
personMock,
|
personMock,
|
||||||
processMock,
|
processMock,
|
||||||
searchMock,
|
searchMock,
|
||||||
serverInfoMock,
|
serverInfoMock as IServerInfoRepository as ServerInfoRepository,
|
||||||
sessionMock,
|
sessionMock,
|
||||||
sharedLinkMock,
|
sharedLinkMock,
|
||||||
stackMock,
|
stackMock,
|
||||||
storageMock,
|
storageMock,
|
||||||
systemMock,
|
systemMock,
|
||||||
tagMock,
|
tagMock,
|
||||||
telemetryMock,
|
telemetryMock as unknown as TelemetryRepository,
|
||||||
trashMock,
|
trashMock as ITrashRepository as TrashRepository,
|
||||||
userMock,
|
userMock,
|
||||||
versionHistoryMock,
|
versionHistoryMock as IVersionHistoryRepository as VersionHistoryRepository,
|
||||||
viewMock as IViewRepository as ViewRepository,
|
viewMock as IViewRepository as ViewRepository,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user