Source Code added

This commit is contained in:
Fr4nz D13trich 2026-02-02 15:06:40 +01:00
parent 800376eafd
commit 9efa9bc6dd
3912 changed files with 754770 additions and 2 deletions

View file

@ -0,0 +1,73 @@
import { AccessRepository } from 'src/repositories/access.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
type IAccessRepository = { [K in keyof AccessRepository]: RepositoryInterface<AccessRepository[K]> };
export type IAccessRepositoryMock = {
[K in keyof IAccessRepository]: Mocked<IAccessRepository[K]>;
};
export const newAccessRepositoryMock = (): IAccessRepositoryMock => {
return {
activity: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
checkAlbumOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
checkCreateAccess: vitest.fn().mockResolvedValue(new Set()),
},
asset: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
checkAlbumAccess: vitest.fn().mockResolvedValue(new Set()),
checkPartnerAccess: vitest.fn().mockResolvedValue(new Set()),
checkSharedLinkAccess: vitest.fn().mockResolvedValue(new Set()),
},
album: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
checkSharedAlbumAccess: vitest.fn().mockResolvedValue(new Set()),
checkSharedLinkAccess: vitest.fn().mockResolvedValue(new Set()),
},
authDevice: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
memory: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
notification: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
person: {
checkFaceOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
partner: {
checkUpdateAccess: vitest.fn().mockResolvedValue(new Set()),
},
session: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
stack: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
timeline: {
checkPartnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
tag: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
workflow: {
checkOwnerAccess: vitest.fn().mockResolvedValue(new Set()),
},
};
};

View file

@ -0,0 +1,57 @@
import { AssetRepository } from 'src/repositories/asset.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newAssetRepositoryMock = (): Mocked<RepositoryInterface<AssetRepository>> => {
return {
create: vitest.fn(),
createAll: vitest.fn(),
upsertExif: vitest.fn(),
updateAllExif: vitest.fn(),
updateDateTimeOriginal: vitest.fn().mockResolvedValue([]),
unlockProperties: vitest.fn().mockResolvedValue([]),
upsertJobStatus: vitest.fn(),
getForCopy: vitest.fn(),
getByDayOfYear: vitest.fn(),
getByIds: vitest.fn().mockResolvedValue([]),
getByIdsWithAllRelationsButStacks: vitest.fn().mockResolvedValue([]),
getByDeviceIds: vitest.fn(),
getById: vitest.fn(),
getByChecksum: vitest.fn(),
getByChecksums: vitest.fn(),
getUploadAssetIdByChecksum: vitest.fn(),
getRandom: vitest.fn(),
getAllByDeviceId: vitest.fn(),
getLivePhotoCount: vitest.fn(),
getLibraryAssetCount: vitest.fn(),
updateAll: vitest.fn(),
getByLibraryIdAndOriginalPath: vitest.fn(),
deleteAll: vitest.fn(),
update: vitest.fn(),
remove: vitest.fn(),
findLivePhotoMatch: vitest.fn(),
getStatistics: vitest.fn(),
getTimeBucket: vitest.fn(),
getTimeBuckets: vitest.fn(),
getAssetIdByCity: vitest.fn(),
getAllForUserFullSync: vitest.fn(),
getChangedDeltaSync: vitest.fn(),
upsertFile: vitest.fn(),
upsertFiles: vitest.fn(),
deleteFile: vitest.fn(),
deleteFiles: vitest.fn(),
detectOfflineExternalAssets: vitest.fn(),
filterNewExternalAssetPaths: vitest.fn(),
updateByLibraryId: vitest.fn(),
getFileSamples: vitest.fn(),
getMetadata: vitest.fn(),
getMetadataByKey: vitest.fn(),
upsertMetadata: vitest.fn(),
upsertBulkMetadata: vitest.fn(),
deleteMetadataByKey: vitest.fn(),
deleteBulkMetadata: vitest.fn(),
getForOriginal: vitest.fn(),
getForThumbnail: vitest.fn(),
getForVideo: vitest.fn(),
};
};

View file

@ -0,0 +1,112 @@
import { DatabaseExtension, ImmichEnvironment, ImmichWorker, LogFormat } from 'src/enum';
import { ConfigRepository, EnvData } from 'src/repositories/config.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
const envData: EnvData = {
port: 2283,
environment: ImmichEnvironment.Production,
logFormat: LogFormat.Console,
buildMetadata: {},
bull: {
config: {
connection: {},
prefix: 'immich_bull',
},
queues: [{ name: 'queue-1' }],
},
cls: {
config: {},
},
database: {
config: {
connectionType: 'parts',
database: 'immich',
host: 'database',
port: 5432,
username: 'postgres',
password: 'postgres',
},
skipMigrations: false,
vectorExtension: DatabaseExtension.Vectors,
},
licensePublicKey: {
client: 'client-public-key',
server: 'server-public-key',
},
network: {
trustedProxies: [],
},
otel: {
metrics: {
hostMetrics: false,
apiMetrics: {
enable: false,
ignoreRoutes: [],
},
},
},
redis: {
host: 'redis',
port: 6379,
db: 0,
},
resourcePaths: {
lockFile: 'build-lock.json',
geodata: {
dateFile: '/build/geodata/geodata-date.txt',
admin1: '/build/geodata/admin1CodesASCII.txt',
admin2: '/build/geodata/admin2Codes.txt',
cities500: '/build/geodata/cities500.txt',
naturalEarthCountriesPath: 'build/ne_10m_admin_0_countries.geojson',
},
web: {
root: '/build/www',
indexHtml: '/build/www/index.html',
},
corePlugin: '/build/corePlugin',
},
setup: {
allow: true,
},
storage: {
ignoreMountCheckErrors: false,
},
telemetry: {
apiPort: 8081,
microservicesPort: 8082,
metrics: new Set(),
},
workers: [ImmichWorker.Api, ImmichWorker.Microservices],
plugins: {
external: {
allow: true,
installFolder: '/app/data/plugins',
},
},
noColor: false,
};
export const mockEnvData = (config: Partial<EnvData>) => ({ ...envData, ...config });
export const newConfigRepositoryMock = (): Mocked<RepositoryInterface<ConfigRepository>> => {
return {
getEnv: vitest.fn().mockReturnValue(mockEnvData({})),
getWorker: vitest.fn().mockReturnValue(ImmichWorker.Api),
isDev: vitest.fn().mockReturnValue(false),
};
};

View file

@ -0,0 +1,19 @@
import { CryptoRepository } from 'src/repositories/crypto.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newCryptoRepositoryMock = (): Mocked<RepositoryInterface<CryptoRepository>> => {
return {
randomUUID: vitest.fn().mockReturnValue('random-uuid'),
randomBytes: vitest.fn().mockReturnValue(Buffer.from('random-bytes', 'utf8')),
compareBcrypt: vitest.fn().mockReturnValue(true),
hashBcrypt: vitest.fn().mockImplementation((input) => Promise.resolve(`${input} (hashed)`)),
hashSha256: vitest.fn().mockImplementation((input) => `${input} (hashed)`),
verifySha256: vitest.fn().mockImplementation(() => true),
hashSha1: vitest.fn().mockImplementation((input) => Buffer.from(`${input.toString()} (hashed)`)),
hashFile: vitest.fn().mockImplementation((input) => `${input} (file-hashed)`),
randomBytesAsText: vitest.fn().mockReturnValue(Buffer.from('random-bytes').toString('base64')),
signJwt: vitest.fn().mockReturnValue('mock-jwt-token'),
verifyJwt: vitest.fn().mockImplementation((token) => ({ verified: true, token })),
};
};

View file

@ -0,0 +1,29 @@
import { DatabaseRepository } from 'src/repositories/database.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newDatabaseRepositoryMock = (): Mocked<RepositoryInterface<DatabaseRepository>> => {
return {
shutdown: vitest.fn(),
getExtensionVersions: vitest.fn(),
getVectorExtension: vitest.fn(),
getExtensionVersionRange: vitest.fn(),
getPostgresVersion: vitest.fn().mockResolvedValue('14.10 (Debian 14.10-1.pgdg120+1)'),
getPostgresVersionRange: vitest.fn().mockReturnValue('>=14.0.0'),
createExtension: vitest.fn().mockResolvedValue(void 0),
dropExtension: vitest.fn(),
updateVectorExtension: vitest.fn(),
reindexVectorsIfNeeded: vitest.fn(),
getDimensionSize: vitest.fn(),
setDimensionSize: vitest.fn(),
deleteAllSearchEmbeddings: vitest.fn(),
prewarm: vitest.fn(),
runMigrations: vitest.fn(),
revertLastMigration: vitest.fn(),
withLock: vitest.fn().mockImplementation((_, function_: <R>() => Promise<R>) => function_()),
tryLock: vitest.fn(),
isBusy: vitest.fn(),
wait: vitest.fn(),
migrateFilePaths: vitest.fn(),
};
};

View file

@ -0,0 +1,24 @@
import { JobRepository } from 'src/repositories/job.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newJobRepositoryMock = (): Mocked<RepositoryInterface<JobRepository>> => {
return {
setup: vitest.fn(),
startWorkers: vitest.fn(),
run: vitest.fn(),
setConcurrency: vitest.fn(),
empty: vitest.fn(),
pause: vitest.fn(),
resume: vitest.fn(),
searchJobs: vitest.fn(),
queue: vitest.fn().mockImplementation(() => Promise.resolve()),
queueAll: vitest.fn().mockImplementation(() => Promise.resolve()),
isActive: vitest.fn(),
isPaused: vitest.fn(),
getJobCounts: vitest.fn(),
clear: vitest.fn(),
waitForQueueCompletion: vitest.fn(),
removeJob: vitest.fn(),
};
};

View file

@ -0,0 +1,17 @@
import { MediaRepository } from 'src/repositories/media.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newMediaRepositoryMock = (): Mocked<RepositoryInterface<MediaRepository>> => {
return {
generateThumbnail: vitest.fn().mockImplementation(() => Promise.resolve()),
writeExif: vitest.fn().mockImplementation(() => Promise.resolve()),
copyTagGroup: vitest.fn().mockImplementation(() => Promise.resolve()),
generateThumbhash: vitest.fn().mockResolvedValue(Buffer.from('')),
decodeImage: vitest.fn().mockResolvedValue({ data: Buffer.from(''), info: {} }),
extract: vitest.fn().mockResolvedValue(null),
probe: vitest.fn(),
transcode: vitest.fn(),
getImageDimensions: vitest.fn(),
};
};

View file

@ -0,0 +1,13 @@
import { MetadataRepository } from 'src/repositories/metadata.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
export const newMetadataRepositoryMock = (): Mocked<RepositoryInterface<MetadataRepository>> => {
return {
setMaxConcurrency: vitest.fn(),
teardown: vitest.fn(),
readTags: vitest.fn(),
writeTags: vitest.fn(),
extractBinaryTag: vitest.fn(),
};
};

View file

@ -0,0 +1,78 @@
import { ChokidarOptions } from 'chokidar';
import { StorageCore } from 'src/cores/storage.core';
import { StorageRepository, WatchEvents } from 'src/repositories/storage.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
interface MockWatcherOptions {
items?: Array<{ event: 'change' | 'add' | 'unlink' | 'error'; value: string }>;
close?: () => Promise<void>;
}
export const makeMockWatcher =
({ items, close }: MockWatcherOptions) =>
(paths: string[], options: ChokidarOptions, events: Partial<WatchEvents>) => {
events.onReady?.();
for (const item of items || []) {
switch (item.event) {
case 'add': {
events.onAdd?.(item.value);
break;
}
case 'change': {
events.onChange?.(item.value);
break;
}
case 'unlink': {
events.onUnlink?.(item.value);
break;
}
case 'error': {
events.onError?.(new Error(item.value));
break;
}
}
}
if (close) {
return () => close();
}
// eslint-disable-next-line unicorn/consistent-function-scoping
return () => Promise.resolve();
};
export const newStorageRepositoryMock = (): Mocked<RepositoryInterface<StorageRepository>> => {
StorageCore.reset();
StorageCore.setMediaLocation('/data');
return {
createZipStream: vitest.fn(),
createReadStream: vitest.fn(),
createPlainReadStream: vitest.fn(),
createGzip: vitest.fn(),
createGunzip: vitest.fn(),
readFile: vitest.fn(),
readTextFile: vitest.fn(),
createFile: vitest.fn(),
createWriteStream: vitest.fn(),
createOrOverwriteFile: vitest.fn(),
existsSync: vitest.fn(),
overwriteFile: vitest.fn(),
unlink: vitest.fn(),
unlinkDir: vitest.fn().mockResolvedValue(true),
removeEmptyDirs: vitest.fn(),
checkFileExists: vitest.fn(),
mkdirSync: vitest.fn(),
checkDiskUsage: vitest.fn(),
readdir: vitest.fn(),
realpath: vitest.fn().mockImplementation((filepath: string) => Promise.resolve(filepath)),
stat: vitest.fn(),
crawl: vitest.fn(),
walk: vitest.fn().mockImplementation(async function* () {}),
rename: vitest.fn(),
copyFile: vitest.fn(),
utimes: vitest.fn(),
watch: vitest.fn().mockImplementation(makeMockWatcher({})),
};
};

View file

@ -0,0 +1,14 @@
import { SystemMetadataRepository } from 'src/repositories/system-metadata.repository';
import { RepositoryInterface } from 'src/types';
import { clearConfigCache } from 'src/utils/config';
import { Mocked, vitest } from 'vitest';
export const newSystemMetadataRepositoryMock = (): Mocked<RepositoryInterface<SystemMetadataRepository>> => {
clearConfigCache();
return {
get: vitest.fn() as any,
set: vitest.fn(),
delete: vitest.fn(),
readFile: vitest.fn(),
};
};

View file

@ -0,0 +1,28 @@
import { TelemetryRepository } from 'src/repositories/telemetry.repository';
import { RepositoryInterface } from 'src/types';
import { Mocked, vitest } from 'vitest';
const newMetricGroupMock = () => {
return {
addToCounter: vitest.fn(),
addToGauge: vitest.fn(),
addToHistogram: vitest.fn(),
configure: vitest.fn(),
};
};
type ITelemetryRepository = RepositoryInterface<TelemetryRepository>;
export type ITelemetryRepositoryMock = {
[K in keyof ITelemetryRepository]: Mocked<RepositoryInterface<ITelemetryRepository[K]>>;
};
export const newTelemetryRepositoryMock = (): ITelemetryRepositoryMock => {
return {
setup: vitest.fn(),
api: newMetricGroupMock(),
host: newMetricGroupMock(),
jobs: newMetricGroupMock(),
repo: newMetricGroupMock(),
};
};