chore(server): remove unused code (#30772)

chore(server): remove unnused code
This commit is contained in:
Jason Rasmussen 2026-08-14 16:58:14 -04:00 committed by GitHub
parent 6a61901e79
commit 14241ac7bc
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 5 additions and 328 deletions

View file

@ -1,9 +1,7 @@
export const uuidDto = {
invalid: 'invalid-uuid',
// valid uuid v4
notFound: '00000000-0000-4000-a000-000000000000',
dummy: '00000000-0000-4000-a000-000000000001',
dummy2: '00000000-0000-4000-a000-000000000002',
};
const adminLoginDto = {
@ -57,22 +55,6 @@ export const createUserDto = {
};
export const userDto = {
admin: {
name: signupDto.admin.name,
email: signupDto.admin.email,
password: signupDto.admin.password,
storageLabel: 'admin',
oauthId: '',
shouldChangePassword: false,
profileImagePath: '',
createdAt: new Date('2021-01-01'),
deletedAt: null,
updatedAt: new Date('2021-01-01'),
tags: [],
assets: [],
quotaSizeInBytes: null,
quotaUsageInBytes: 0,
},
user1: {
name: createUserDto.user1.name,
email: createUserDto.user1.email,

View file

@ -40,41 +40,6 @@ export const errorDto = {
},
};
export const signupResponseDto = {
admin: {
avatarColor: expect.any(String),
id: expect.any(String),
name: 'Immich Admin',
email: 'admin@immich.cloud',
storageLabel: 'admin',
profileImagePath: '',
// why? lol
shouldChangePassword: true,
isAdmin: true,
createdAt: expect.any(String),
updatedAt: expect.any(String),
deletedAt: null,
oauthId: '',
quotaUsageInBytes: 0,
quotaSizeInBytes: null,
status: 'active',
license: null,
profileChangedAt: expect.any(String),
},
};
export const loginResponseDto = {
admin: {
accessToken: expect.any(String),
name: 'Immich Admin',
isAdmin: true,
isOnboarded: false,
profileImagePath: '',
shouldChangePassword: true,
userEmail: 'admin@immich.cloud',
userId: expect.any(String),
},
};
export const deviceDto = {
current: {
id: expect.any(String),

View file

@ -24,13 +24,6 @@ export const ASPECT_RATIO_WEIGHTS = {
'3:1': 0.01, // 1% 3:1 panorama
} as const;
export type AspectRatio = {
width: number;
height: number;
ratio: number;
name: string;
};
// Mock configuration for asset generation - will be transformed to API response formats
export type MockTimelineAsset = {
id: string;

View file

@ -1,4 +1,4 @@
import { BrowserContext, expect, Page } from '@playwright/test';
import { expect, Page } from '@playwright/test';
import { DateTime } from 'luxon';
import { TimelineAssetConfig } from 'src/ui/generators/timeline';
@ -11,18 +11,6 @@ export const padYearMonth = (yearMonth: string) => {
return `${year}-${month.padStart(2, '0')}`;
};
export async function throttlePage(context: BrowserContext, page: Page) {
const session = await context.newCDPSession(page);
await session.send('Network.emulateNetworkConditions', {
offline: false,
downloadThroughput: (1.5 * 1024 * 1024) / 8,
uploadThroughput: (750 * 1024) / 8,
latency: 40,
connectionType: 'cellular3g',
});
await session.send('Emulation.setCPUThrottlingRate', { rate: 10 });
}
export const poll = async <T>(
page: Page,
query: () => Promise<T>,

View file

@ -1,4 +1,3 @@
import { randomUUID } from 'node:crypto';
import { dirname, join, resolve } from 'node:path';
import { StorageAsset } from 'src/database';
import {
@ -352,10 +351,6 @@ export class StorageCore {
return join(StorageCore.getNestedFolder(folder, ownerId, filename), filename);
}
static getTempPathInDir(dir: string): string {
return join(dir, `${randomUUID()}.tmp`);
}
private async getDevices() {
try {
return await this.storageRepository.readdir('/dev/dri');

View file

@ -1211,14 +1211,6 @@ export enum ApiTag {
Workflows = 'Workflows',
}
export enum PluginContext {
Asset = 'asset',
Album = 'album',
Person = 'person',
}
export const PluginContextSchema = z.enum(PluginContext).describe('Plugin context').meta({ id: 'PluginContextType' });
export const WorkflowTriggerSchema = z
.enum(WorkflowTrigger)
.describe('Plugin trigger type')

View file

@ -1,11 +1,4 @@
import {
CanActivate,
ExecutionContext,
Injectable,
SetMetadata,
applyDecorators,
createParamDecorator,
} from '@nestjs/common';
import { CanActivate, ExecutionContext, Injectable, SetMetadata, applyDecorators } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { Request } from 'express';
import { MaintenanceAuthDto } from 'src/dtos/maintenance.dto';
@ -22,14 +15,6 @@ export interface MaintenanceAuthRequest extends Request {
auth?: MaintenanceAuthDto;
}
export interface MaintenanceAuthenticatedRequest extends Request {
auth: MaintenanceAuthDto;
}
export const MaintenanceAuth = createParamDecorator((data, context: ExecutionContext): MaintenanceAuthDto => {
return context.switchToHttp().getRequest<MaintenanceAuthenticatedRequest>().auth;
});
@Injectable()
export class MaintenanceAuthGuard implements CanActivate {
constructor(

View file

@ -483,35 +483,6 @@ export class DatabaseRepository {
await sql`SELECT pg_advisory_unlock(${lock})`.execute(connection);
}
async revertLastMigration(): Promise<string | undefined> {
this.logger.debug('Reverting last migration');
const migrator = this.createMigrator();
const { error, results } = await migrator.migrateDown();
for (const result of results ?? []) {
if (result.status === 'Success') {
this.logger.log(`Reverted migration "${result.migrationName}"`);
} else if (result.status === 'Error') {
this.logger.warn(`Failed to revert migration "${result.migrationName}"`);
}
}
if (error) {
this.logger.error(`Failed to revert migrations: ${error}`);
throw error;
}
const reverted = results?.find((result) => result.direction === 'Down' && result.status === 'Success');
if (!reverted) {
this.logger.debug('No migrations to revert');
return undefined;
}
this.logger.debug('Finished reverting migration');
return reverted.migrationName;
}
private createMigrator(): Migrator {
return new Migrator({
db: this.db,

View file

@ -73,7 +73,6 @@ export interface Face {
}
export type FacialRecognitionResponse = { [ModelTask.FACIAL_RECOGNITION]: Face[] } & VisualResponse;
export type DetectedFaces = { faces: Face[] } & VisualResponse;
export type MachineLearningRequest = ClipVisualRequest | ClipTextualRequest | FacialRecognitionRequest | OcrRequest;
export type TextEncodingOptions = ModelOptions & { language?: string };

View file

@ -1,5 +1,5 @@
import { Injectable } from '@nestjs/common';
import { ExpressionBuilder, Insertable, Kysely, Selectable, sql, Updateable } from 'kysely';
import { ExpressionBuilder, Insertable, Kysely, sql, Updateable } from 'kysely';
import { jsonObjectFrom } from 'kysely/helpers/postgres';
import { InjectKysely } from 'nestjs-kysely';
import { AssetFace } from 'src/database';
@ -60,8 +60,6 @@ export interface GetAllFacesOptions {
export type UnassignFacesOptions = DeleteFacesOptions;
export type SelectFaceOptions = (keyof Selectable<AssetFaceTable>)[];
const withPerson = (eb: ExpressionBuilder<DB, 'asset_face'>) => {
return jsonObjectFrom(
eb.selectFrom('person').selectAll('person').whereRef('person.id', '=', 'asset_face.personId'),

View file

@ -158,8 +158,6 @@ export type SmartSearchOptions = SearchDateOptions &
SearchTagOptions &
SearchOcrOptions & { visibility?: AssetVisibility | 'not-locked' };
export type OcrSearchOptions = SearchDateOptions & SearchOcrOptions;
export type LargeAssetSearchOptions = AssetSearchOptions & { minFileSize?: number };
export interface FaceEmbeddingSearch extends SearchEmbeddingOptions {

View file

@ -8,16 +8,6 @@ import { ReleaseChannel } from 'src/dtos/system-config.dto';
import { ConfigRepository } from 'src/repositories/config.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 VersionResponse {
version: string;
published_at: string;

View file

@ -9,8 +9,6 @@ import { DB } from 'src/schema';
import { SessionTable } from 'src/schema/tables/session.table';
import { asUuid } from 'src/utils/database';
export type SessionSearchOptions = { updatedBefore: Date };
@Injectable()
export class SessionRepository {
constructor(@InjectKysely() private db: Kysely<DB>) {}

View file

@ -444,10 +444,6 @@ export class LibraryService extends BaseService {
await this.jobRepository.queue({ name: JobName.LibrarySyncAssetsQueueAll, data: { id } });
}
async queueScanAll() {
await this.jobRepository.queue({ name: JobName.LibraryScanQueueAll, data: {} });
}
@OnJob({ name: JobName.LibraryScanQueueAll, queue: QueueName.Library })
async handleQueueScanAll(): Promise<JobStatus> {
this.logger.log(`Initiating scan of all external libraries...`);

View file

@ -1,4 +1,3 @@
import { WorkflowTrigger } from '@immich/plugin-sdk';
import { ShallowDehydrateObject } from 'kysely';
import { SystemConfig } from 'src/config';
import { VECTOR_EXTENSIONS } from 'src/constants';
@ -30,7 +29,6 @@ import {
SystemMetadataKey,
TranscodeTarget,
UserMetadataKey,
WorkflowType,
} from 'src/enum';
import { Mocked } from 'vitest';
@ -79,14 +77,6 @@ export interface DecodeToBufferOptions extends DecodeImageOptions {
export type GenerateThumbnailOptions = Pick<ImageOptions, 'format' | 'quality' | 'progressive'> & DecodeToBufferOptions;
export type GenerateThumbhashOptions = DecodeImageOptions;
export interface GenerateThumbnailsOptions {
colorspace: string;
preview?: ImageOptions;
processInvalidImages: boolean;
thumbhash?: boolean;
thumbnail?: ImageOptions;
}
export interface VideoStreamInfo {
index: number;
height: number;
@ -143,10 +133,6 @@ export interface ImageDimensions {
height: number;
}
export interface InputDimensions extends ImageDimensions {
inputPath: string;
}
export interface VideoInfo {
format: VideoFormat;
videoStreams: VideoStreamInfo[];
@ -189,11 +175,6 @@ export interface BitrateDistribution {
unit: string;
}
export interface ImageBuffer {
data: Buffer;
info: RawImageInfo;
}
export interface VideoCodecSWConfig {
getCommand(
target: TranscodeTarget,
@ -260,18 +241,10 @@ export interface ILibraryBulkIdsJob {
totalAssets: number;
}
export interface IBulkEntityJob {
ids: string[];
}
export interface IDeleteFilesJob extends IBaseJob {
files: Array<string | null | undefined>;
}
export interface ISidecarWriteJob extends IEntityJob {
tags?: true;
}
export interface IDeferrableJob extends IEntityJob {
deferred?: boolean;
}
@ -307,12 +280,6 @@ export interface INotifyAlbumUpdateJob extends IEntityJob, IDelayedJob {
recipientId: string;
}
export type IWorkflowJob<T extends WorkflowType = WorkflowType> = {
id: string;
trigger: WorkflowTrigger;
type: T;
};
export interface IIntegrityJob {
refreshOnly?: boolean;
}

View file

@ -81,8 +81,6 @@ export const asUuid = (id: string | Expression<string>) => sql<string>`${id}::uu
export const anyUuid = (ids: string[]) => sql<string>`any(${`{${ids}}`}::uuid[])`;
export const asVector = (embedding: number[]) => sql<string>`${`[${embedding}]`}::vector`;
export const unnest = (array: string[]) => sql<Record<string, string>>`unnest(array[${sql.join(array)}]::text[])`;
export const removeUndefinedKeys = <T extends object>(update: T, template: unknown) => {

View file

@ -712,10 +712,6 @@ export class NvencSwDecodeConfig extends BaseHWConfig {
: ['-cq:v', String(this.config.crf)];
}
getThreadOptions() {
return [];
}
getEncoderOptions(): string[] {
const out = this.getOutputThreadOptions();
if (this.tune.strictGop) {

View file

@ -28,19 +28,6 @@ export const authStub = {
id: 'token-id',
} as AuthSession,
}),
user2: Object.freeze<AuthDto>({
user: {
id: 'user-2',
name: 'User 2',
email: 'user2@immich.cloud',
isAdmin: false,
quotaSizeInBytes: null,
quotaUsageInBytes: 0,
},
session: {
id: 'token-id',
} as AuthSession,
}),
adminWithElevatedPermission: Object.freeze<AuthDto>({
user: authUser.admin,
session: {

View file

@ -6,13 +6,6 @@ export const fileStub = {
originalName: 'asset_1.jpeg',
size: 42,
}),
livePhotoMotion: Object.freeze({
uuid: 'live-photo-motion-asset',
originalPath: 'fake_path/asset_1.mp4',
checksum: Buffer.from('live photo file hash', 'utf8'),
originalName: 'asset_1.mp4',
size: 69,
}),
photo: Object.freeze({
uuid: 'photo',
originalPath: 'fake_path/photo1.jpeg',

View file

@ -451,28 +451,6 @@ export const videoInfoStub = {
},
],
}),
videoStreamWithProfileLevel: Object.freeze<VideoInfo>({
...probeStubDefault,
videoStreams: [
{
...probeStubDefaultVideoStream[0],
codecName: 'h264',
profile: 100,
level: 40,
},
],
}),
audioStreamAAC: Object.freeze<VideoInfo>({
...probeStubDefault,
audioStreams: [
{
index: 1,
codecName: 'aac',
profile: 2,
bitrate: 128_000,
},
],
}),
};
interface SelectedStreams {

View file

@ -1,27 +1,6 @@
import { expect } from 'vitest';
export const errorDto = {
unauthorized: {
message: 'Authentication required',
},
forbidden: {
message: expect.any(String),
},
missingPermission: (permission: string) => ({
message: `Missing required permission: ${permission}`,
}),
wrongPassword: {
message: 'Wrong password',
},
invalidToken: {
message: 'Invalid user token',
},
invalidShareKey: {
message: 'Invalid share key',
},
invalidSharePassword: {
message: 'Invalid password',
},
badRequest: (message: any = null) => ({
message: message ?? expect.anything(),
}),
@ -29,10 +8,4 @@ export const errorDto = {
message: 'Validation failed',
errors: errors ? expect.arrayContaining(errors.map((e) => expect.objectContaining(e))) : expect.any(Array),
}),
noPermission: {
message: expect.stringContaining('Not found or no'),
},
incorrectLogin: {
message: 'Incorrect email or password',
},
};

View file

@ -1,7 +1,7 @@
import { AuthApiKey, AuthSharedLink, AuthUser, Exif, Library, UserAdmin } from 'src/database';
import { AuthApiKey, AuthSharedLink, AuthUser, Library, UserAdmin } from 'src/database';
import { AuthDto } from 'src/dtos/auth.dto';
import { QueueStatisticsDto } from 'src/dtos/queue.dto';
import { AssetFileType, Permission, UserStatus } from 'src/enum';
import { Permission, UserStatus } from 'src/enum';
import { v4, v7 } from 'uuid';
import { expect } from 'vitest';
@ -168,31 +168,6 @@ const versionHistoryFactory = () => ({
version: '1.123.45',
});
const assetSidecarWriteFactory = () => {
const id = newUuid();
return {
id,
originalPath: '/path/to/original-path.jpg.xmp',
tags: [],
files: [
{
id: newUuid(),
path: '/path/to/original-path.jpg.xmp',
type: AssetFileType.Sidecar,
isEdited: false,
},
],
exifInfo: {
assetId: id,
description: 'this is a description',
latitude: 12,
longitude: 12,
dateTimeOriginal: '2023-11-22T04:56:12.196Z',
timeZone: 'UTC-6',
} as unknown as Exif,
};
};
const assetOcrFactory = (
ocr: {
id?: string;
@ -236,9 +211,6 @@ export const factory = {
library: libraryFactory,
queueStatistics: queueStatisticsFactory,
versionHistory: versionHistoryFactory,
jobAssets: {
sidecarWrite: assetSidecarWriteFactory,
},
uuid: newUuid,
buffer: () => Buffer.from('this is a fake buffer'),
date: newDate,

View file

@ -553,43 +553,6 @@ export const mockDuplex =
return duplex;
};
export const mockFork = vitest.fn((exitCode: number, stdout: string, stderr: string, error?: unknown) => {
const stdoutStream = new Readable({
read() {
this.push(stdout); // write mock data to stdout
this.push(null); // end stream
},
});
return {
stdout: stdoutStream,
stderr: new Readable({
read() {
this.push(stderr); // write mock data to stderr
this.push(null); // end stream
},
}),
stdin: new Writable({
write(chunk, encoding, callback) {
callback();
},
}),
exitCode,
on: vitest.fn((event, callback: any) => {
if (event === 'close') {
stdoutStream.once('end', () => callback(0));
}
if (event === 'error' && error) {
stdoutStream.once('end', () => callback(error));
}
if (event === 'exit') {
stdoutStream.once('end', () => callback(exitCode));
}
}),
kill: vitest.fn(),
} as unknown as ChildProcessWithoutNullStreams;
});
export async function* makeStream<T>(items: T[] = []): AsyncGenerator<T> {
for (const item of items) {
await Promise.resolve();