mirror of
https://github.com/immich-app/immich.git
synced 2024-12-22 01:47:08 +02:00
refactor: infra folder (#8138)
This commit is contained in:
parent
9fd5d2ad9c
commit
16d0df796c
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -354,7 +354,7 @@ jobs:
|
||||
id: verify-changed-sql-files
|
||||
with:
|
||||
files: |
|
||||
server/src/infra/sql
|
||||
server/src/queries
|
||||
|
||||
- name: Verify SQL files have not changed
|
||||
if: steps.verify-changed-sql-files.outputs.files_changed == 'true'
|
||||
|
@ -5,7 +5,7 @@ After making any changes in the `server/src/entities`, a database migration need
|
||||
1. Run the command
|
||||
|
||||
```bash
|
||||
npm run typeorm:migrations:generate ./src/infra/<migration-name>
|
||||
npm run typeorm:migrations:generate <migration-name>
|
||||
```
|
||||
|
||||
2. Check if the migration file makes sense.
|
||||
|
@ -25,12 +25,12 @@
|
||||
"e2e:jobs": "jest --config e2e/jobs/jest-e2e.json --runInBand",
|
||||
"typeorm": "typeorm",
|
||||
"typeorm:migrations:create": "typeorm migration:create",
|
||||
"typeorm:migrations:generate": "typeorm migration:generate -d ./dist/infra/database.config.js",
|
||||
"typeorm:migrations:run": "typeorm migration:run -d ./dist/infra/database.config.js",
|
||||
"typeorm:migrations:revert": "typeorm migration:revert -d ./dist/infra/database.config.js",
|
||||
"typeorm:schema:drop": "typeorm query -d ./dist/infra/database.config.js 'DROP schema public cascade; CREATE schema public;'",
|
||||
"typeorm:migrations:generate": "typeorm migration:generate -d ./dist/database.config.js",
|
||||
"typeorm:migrations:run": "typeorm migration:run -d ./dist/database.config.js",
|
||||
"typeorm:migrations:revert": "typeorm migration:revert -d ./dist/database.config.js",
|
||||
"typeorm:schema:drop": "typeorm query -d ./dist/database.config.js 'DROP schema public cascade; CREATE schema public;'",
|
||||
"typeorm:schema:reset": "npm run typeorm:schema:drop && npm run typeorm:migrations:run",
|
||||
"sql:generate": "node ./dist/infra/sql-generator/"
|
||||
"sql:generate": "node ./dist/utils/sql.js"
|
||||
},
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.22.11",
|
||||
@ -146,15 +146,16 @@
|
||||
"^.+\\.ts$": "ts-jest"
|
||||
},
|
||||
"collectCoverageFrom": [
|
||||
"<rootDir>/src/**/*.(t|j)s",
|
||||
"!<rootDir>/src/infra/**/*",
|
||||
"!<rootDir>/src/migrations/**/*",
|
||||
"!<rootDir>/src/subscribers/**/*",
|
||||
"!<rootDir>/src/immich/controllers/**/*"
|
||||
"<rootDir>/src/cores/*.(t|j)s",
|
||||
"<rootDir>/src/dtos/*.(t|j)s",
|
||||
"<rootDir>/src/interfaces/*.(t|j)s",
|
||||
"<rootDir>/src/services/*.(t|j)s",
|
||||
"<rootDir>/src/utils/*.(t|j)s",
|
||||
"<rootDir>/src/*.t|j)s"
|
||||
],
|
||||
"coverageDirectory": "./coverage",
|
||||
"coverageThreshold": {
|
||||
"./src/domain/": {
|
||||
"./src/": {
|
||||
"branches": 75,
|
||||
"functions": 80,
|
||||
"lines": 85,
|
||||
|
@ -7,11 +7,11 @@ import sirv from 'sirv';
|
||||
import { ApiModule } from 'src/apps/api.module';
|
||||
import { ApiService } from 'src/apps/api.service';
|
||||
import { excludePaths } from 'src/config';
|
||||
import { WEB_ROOT, envName, isDev, serverVersion } from 'src/domain/domain.constant';
|
||||
import { WEB_ROOT, envName, isDev, serverVersion } from 'src/constants';
|
||||
import { useSwagger } from 'src/immich/app.utils';
|
||||
import { otelSDK } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { WebSocketAdapter } from 'src/infra/websocket.adapter';
|
||||
import { WebSocketAdapter } from 'src/middleware/websocket.adapter';
|
||||
import { otelSDK } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
const logger = new ImmichLogger('ImmichServer');
|
||||
const port = Number(process.env.SERVER_PORT) || 3001;
|
||||
|
@ -3,8 +3,7 @@ import { Cron, CronExpression, Interval } from '@nestjs/schedule';
|
||||
import { NextFunction, Request, Response } from 'express';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { ONE_HOUR, WEB_ROOT } from 'src/domain/domain.constant';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { ONE_HOUR, WEB_ROOT } from 'src/constants';
|
||||
import { AuthService } from 'src/services/auth.service';
|
||||
import { DatabaseService } from 'src/services/database.service';
|
||||
import { JobService } from 'src/services/job.service';
|
||||
@ -12,7 +11,8 @@ import { ServerInfoService } from 'src/services/server-info.service';
|
||||
import { SharedLinkService } from 'src/services/shared-link.service';
|
||||
import { StorageService } from 'src/services/storage.service';
|
||||
import { SystemConfigService } from 'src/services/system-config.service';
|
||||
import { OpenGraphTags } from 'src/utils';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { OpenGraphTags } from 'src/utils/misc';
|
||||
|
||||
const render = (index: string, meta: OpenGraphTags) => {
|
||||
const tags = `
|
||||
|
@ -6,10 +6,8 @@ import { ScheduleModule, SchedulerRegistry } from '@nestjs/schedule';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { OpenTelemetryModule } from 'nestjs-otel';
|
||||
import { bullConfig, bullQueues, immichAppConfig } from 'src/config';
|
||||
import { databaseConfig } from 'src/database.config';
|
||||
import { databaseEntities } from 'src/entities';
|
||||
import { databaseConfig } from 'src/infra/database.config';
|
||||
import { otelConfig } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { IActivityRepository } from 'src/interfaces/activity.repository';
|
||||
import { IAlbumRepository } from 'src/interfaces/album.repository';
|
||||
@ -88,6 +86,8 @@ import { SystemConfigService } from 'src/services/system-config.service';
|
||||
import { TagService } from 'src/services/tag.service';
|
||||
import { TrashService } from 'src/services/trash.service';
|
||||
import { UserService } from 'src/services/user.service';
|
||||
import { otelConfig } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
const services: Provider[] = [
|
||||
APIKeyService,
|
||||
|
@ -1,9 +1,9 @@
|
||||
import { NestFactory } from '@nestjs/core';
|
||||
import { MicroservicesModule } from 'src/apps/microservices.module';
|
||||
import { envName, serverVersion } from 'src/domain/domain.constant';
|
||||
import { otelSDK } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { WebSocketAdapter } from 'src/infra/websocket.adapter';
|
||||
import { envName, serverVersion } from 'src/constants';
|
||||
import { WebSocketAdapter } from 'src/middleware/websocket.adapter';
|
||||
import { otelSDK } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
const logger = new ImmichLogger('ImmichMicroservice');
|
||||
const port = Number(process.env.MICROSERVICES_PORT) || 3002;
|
||||
|
@ -1,7 +1,5 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { JobName } from 'src/domain/job/job.constants';
|
||||
import { IDeleteFilesJob } from 'src/domain/job/job.interface';
|
||||
import { otelSDK } from 'src/infra/instrumentation';
|
||||
import { IDeleteFilesJob, JobName } from 'src/interfaces/job.repository';
|
||||
import { AssetService } from 'src/services/asset.service';
|
||||
import { AuditService } from 'src/services/audit.service';
|
||||
import { DatabaseService } from 'src/services/database.service';
|
||||
@ -15,6 +13,7 @@ import { StorageTemplateService } from 'src/services/storage-template.service';
|
||||
import { StorageService } from 'src/services/storage.service';
|
||||
import { SystemConfigService } from 'src/services/system-config.service';
|
||||
import { UserService } from 'src/services/user.service';
|
||||
import { otelSDK } from 'src/utils/instrumentation';
|
||||
|
||||
@Injectable()
|
||||
export class MicroservicesService {
|
||||
|
@ -3,8 +3,8 @@ import { ConfigModuleOptions } from '@nestjs/config';
|
||||
import { QueueOptions } from 'bullmq';
|
||||
import { RedisOptions } from 'ioredis';
|
||||
import Joi from 'joi';
|
||||
import { QueueName } from 'src/domain/job/job.constants';
|
||||
import { LogLevel } from 'src/entities/system-config.entity';
|
||||
import { QueueName } from 'src/interfaces/job.repository';
|
||||
|
||||
const WHEN_DB_URL_SET = Joi.when('DB_URL', {
|
||||
is: Joi.exist(),
|
||||
|
105
server/src/constants.ts
Normal file
105
server/src/constants.ts
Normal file
@ -0,0 +1,105 @@
|
||||
import { Duration } from 'luxon';
|
||||
import { readFileSync } from 'node:fs';
|
||||
import { join } from 'node:path';
|
||||
import { Version } from 'src/utils/version';
|
||||
|
||||
const { version } = JSON.parse(readFileSync('./package.json', 'utf8'));
|
||||
export const serverVersion = Version.fromString(version);
|
||||
|
||||
export const AUDIT_LOG_MAX_DURATION = Duration.fromObject({ days: 100 });
|
||||
export const ONE_HOUR = Duration.fromObject({ hours: 1 });
|
||||
|
||||
export const envName = (process.env.NODE_ENV || 'development').toUpperCase();
|
||||
export const isDev = process.env.NODE_ENV === 'development';
|
||||
export const APP_MEDIA_LOCATION = process.env.IMMICH_MEDIA_LOCATION || './upload';
|
||||
export const WEB_ROOT = process.env.IMMICH_WEB_ROOT || '/usr/src/app/www';
|
||||
|
||||
const GEODATA_ROOT_PATH = process.env.IMMICH_REVERSE_GEOCODING_ROOT || '/usr/src/resources';
|
||||
|
||||
export const citiesFile = 'cities500.txt';
|
||||
export const geodataDatePath = join(GEODATA_ROOT_PATH, 'geodata-date.txt');
|
||||
export const geodataAdmin1Path = join(GEODATA_ROOT_PATH, 'admin1CodesASCII.txt');
|
||||
export const geodataAdmin2Path = join(GEODATA_ROOT_PATH, 'admin2Codes.txt');
|
||||
export const geodataCities500Path = join(GEODATA_ROOT_PATH, citiesFile);
|
||||
|
||||
export const MOBILE_REDIRECT = 'app.immich:/';
|
||||
export const LOGIN_URL = '/auth/login?autoLaunch=0';
|
||||
export const IMMICH_ACCESS_COOKIE = 'immich_access_token';
|
||||
export const IMMICH_IS_AUTHENTICATED = 'immich_is_authenticated';
|
||||
export const IMMICH_AUTH_TYPE_COOKIE = 'immich_auth_type';
|
||||
export const IMMICH_API_KEY_NAME = 'api_key';
|
||||
export const IMMICH_API_KEY_HEADER = 'x-api-key';
|
||||
export const IMMICH_SHARED_LINK_ACCESS_COOKIE = 'immich_shared_link_token';
|
||||
export enum AuthType {
|
||||
PASSWORD = 'password',
|
||||
OAUTH = 'oauth',
|
||||
}
|
||||
|
||||
export const FACE_THUMBNAIL_SIZE = 250;
|
||||
|
||||
export const supportedYearTokens = ['y', 'yy'];
|
||||
export const supportedMonthTokens = ['M', 'MM', 'MMM', 'MMMM'];
|
||||
export const supportedWeekTokens = ['W', 'WW'];
|
||||
export const supportedDayTokens = ['d', 'dd'];
|
||||
export const supportedHourTokens = ['h', 'hh', 'H', 'HH'];
|
||||
export const supportedMinuteTokens = ['m', 'mm'];
|
||||
export const supportedSecondTokens = ['s', 'ss', 'SSS'];
|
||||
export const supportedPresetTokens = [
|
||||
'{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MM}}/{{filename}}',
|
||||
'{{y}}/{{MMM}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}/{{filename}}',
|
||||
'{{y}}/{{MM}}/{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}/{{dd}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{MM}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MMM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MMMM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{MM}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{WW}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{MM}}-{{dd}}/{{assetId}}',
|
||||
'{{y}}/{{y}}-{{MM}}/{{assetId}}',
|
||||
'{{y}}/{{y}}-{{WW}}/{{assetId}}',
|
||||
'{{album}}/{{filename}}',
|
||||
];
|
||||
|
||||
type ModelInfo = { dimSize: number };
|
||||
export const CLIP_MODEL_INFO: Record<string, ModelInfo> = {
|
||||
RN50__openai: { dimSize: 1024 },
|
||||
RN50__yfcc15m: { dimSize: 1024 },
|
||||
RN50__cc12m: { dimSize: 1024 },
|
||||
RN101__openai: { dimSize: 512 },
|
||||
RN101__yfcc15m: { dimSize: 512 },
|
||||
RN50x4__openai: { dimSize: 640 },
|
||||
RN50x16__openai: { dimSize: 768 },
|
||||
RN50x64__openai: { dimSize: 1024 },
|
||||
'ViT-B-32__openai': { dimSize: 512 },
|
||||
'ViT-B-32__laion2b_e16': { dimSize: 512 },
|
||||
'ViT-B-32__laion400m_e31': { dimSize: 512 },
|
||||
'ViT-B-32__laion400m_e32': { dimSize: 512 },
|
||||
'ViT-B-32__laion2b-s34b-b79k': { dimSize: 512 },
|
||||
'ViT-B-16__openai': { dimSize: 512 },
|
||||
'ViT-B-16__laion400m_e31': { dimSize: 512 },
|
||||
'ViT-B-16__laion400m_e32': { dimSize: 512 },
|
||||
'ViT-B-16-plus-240__laion400m_e31': { dimSize: 640 },
|
||||
'ViT-B-16-plus-240__laion400m_e32': { dimSize: 640 },
|
||||
'ViT-L-14__openai': { dimSize: 768 },
|
||||
'ViT-L-14__laion400m_e31': { dimSize: 768 },
|
||||
'ViT-L-14__laion400m_e32': { dimSize: 768 },
|
||||
'ViT-L-14__laion2b-s32b-b82k': { dimSize: 768 },
|
||||
'ViT-L-14-336__openai': { dimSize: 768 },
|
||||
'ViT-L-14-quickgelu__dfn2b': { dimSize: 768 },
|
||||
'ViT-H-14__laion2b-s32b-b79k': { dimSize: 1024 },
|
||||
'ViT-H-14-quickgelu__dfn5b': { dimSize: 1024 },
|
||||
'ViT-H-14-378-quickgelu__dfn5b': { dimSize: 1024 },
|
||||
'ViT-g-14__laion2b-s12b-b42k': { dimSize: 1024 },
|
||||
'LABSE-Vit-L-14': { dimSize: 768 },
|
||||
'XLM-Roberta-Large-Vit-B-32': { dimSize: 512 },
|
||||
'XLM-Roberta-Large-Vit-B-16Plus': { dimSize: 640 },
|
||||
'XLM-Roberta-Large-Vit-L-14': { dimSize: 768 },
|
||||
'XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k': { dimSize: 1024 },
|
||||
'nllb-clip-base-siglip__v1': { dimSize: 768 },
|
||||
'nllb-clip-large-siglip__v1': { dimSize: 1152 },
|
||||
};
|
@ -1,7 +1,7 @@
|
||||
import { Body, Controller, Delete, Get, HttpCode, HttpStatus, Param, Post, Req, Res } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { Request, Response } from 'express';
|
||||
import { IMMICH_ACCESS_COOKIE, IMMICH_AUTH_TYPE_COOKIE, IMMICH_IS_AUTHENTICATED } from 'src/domain/auth/auth.constant';
|
||||
import { IMMICH_ACCESS_COOKIE, IMMICH_AUTH_TYPE_COOKIE, IMMICH_IS_AUTHENTICATED } from 'src/constants';
|
||||
import {
|
||||
AuthDeviceResponseDto,
|
||||
AuthDto,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Body, Controller, Delete, Get, Param, Patch, Post, Put, Query, Req, Res } from '@nestjs/common';
|
||||
import { ApiTags } from '@nestjs/swagger';
|
||||
import { Request, Response } from 'express';
|
||||
import { IMMICH_SHARED_LINK_ACCESS_COOKIE } from 'src/domain/auth/auth.constant';
|
||||
import { IMMICH_SHARED_LINK_ACCESS_COOKIE } from 'src/constants';
|
||||
import { AssetIdsResponseDto } from 'src/dtos/asset-ids.response.dto';
|
||||
import { AssetIdsDto } from 'src/dtos/asset.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
|
@ -2,7 +2,7 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { setDifference, setIsEqual, setUnion } from 'src/utils';
|
||||
import { setDifference, setIsEqual, setUnion } from 'src/utils/set';
|
||||
|
||||
export enum Permission {
|
||||
ACTIVITY_CREATE = 'activity.create',
|
||||
|
@ -1,16 +1,16 @@
|
||||
import { dirname, join, resolve } from 'node:path';
|
||||
import { APP_MEDIA_LOCATION } from 'src/constants';
|
||||
import { SystemConfigCore } from 'src/cores/system-config.core';
|
||||
import { APP_MEDIA_LOCATION } from 'src/domain/domain.constant';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { AssetPathType, PathType, PersonPathType } from 'src/entities/move.entity';
|
||||
import { PersonEntity } from 'src/entities/person.entity';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { ICryptoRepository } from 'src/interfaces/crypto.repository';
|
||||
import { IMoveRepository } from 'src/interfaces/move.repository';
|
||||
import { IPersonRepository } from 'src/interfaces/person.repository';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.repository';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
export enum StorageFolder {
|
||||
ENCODED_VIDEO = 'encoded-video',
|
||||
|
@ -5,7 +5,6 @@ import { validate } from 'class-validator';
|
||||
import { load as loadYaml } from 'js-yaml';
|
||||
import * as _ from 'lodash';
|
||||
import { Subject } from 'rxjs';
|
||||
import { QueueName } from 'src/domain/job/job.constants';
|
||||
import { SystemConfigDto } from 'src/dtos/system-config.dto';
|
||||
import {
|
||||
AudioCodec,
|
||||
@ -21,8 +20,9 @@ import {
|
||||
TranscodePolicy,
|
||||
VideoCodec,
|
||||
} from 'src/entities/system-config.entity';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { QueueName } from 'src/interfaces/job.repository';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
export type SystemConfigValidator = (config: SystemConfig, newConfig: SystemConfig) => void | Promise<void>;
|
||||
|
||||
|
@ -16,9 +16,9 @@ const urlOrParts = url
|
||||
/* eslint unicorn/prefer-module: "off" -- We can fix this when migrating to ESM*/
|
||||
export const databaseConfig: PostgresConnectionOptions = {
|
||||
type: 'postgres',
|
||||
entities: [__dirname + '/../entities/*.entity.{js,ts}'],
|
||||
migrations: [__dirname + '/../migrations/*.{js,ts}'],
|
||||
subscribers: [__dirname + '/../subscribers/*.{js,ts}'],
|
||||
entities: [__dirname + '/entities/*.entity.{js,ts}'],
|
||||
migrations: [__dirname + '/migrations/*.{js,ts}'],
|
||||
subscribers: [__dirname + '/subscribers/*.{js,ts}'],
|
||||
migrationsRun: false,
|
||||
synchronize: false,
|
||||
connectTimeoutMS: 10_000, // 10 seconds
|
@ -1,6 +1,6 @@
|
||||
import { SetMetadata } from '@nestjs/common';
|
||||
import _ from 'lodash';
|
||||
import { setUnion } from 'src/utils';
|
||||
import { setUnion } from 'src/utils/set';
|
||||
|
||||
// PostgreSQL uses a 16-bit integer to indicate the number of bound parameters. This means that the
|
||||
// maximum number of parameters is 65535. Any query that tries to bind more than that (e.g. searching
|
||||
|
@ -1,12 +0,0 @@
|
||||
export const MOBILE_REDIRECT = 'app.immich:/';
|
||||
export const LOGIN_URL = '/auth/login?autoLaunch=0';
|
||||
export const IMMICH_ACCESS_COOKIE = 'immich_access_token';
|
||||
export const IMMICH_IS_AUTHENTICATED = 'immich_is_authenticated';
|
||||
export const IMMICH_AUTH_TYPE_COOKIE = 'immich_auth_type';
|
||||
export const IMMICH_API_KEY_NAME = 'api_key';
|
||||
export const IMMICH_API_KEY_HEADER = 'x-api-key';
|
||||
export const IMMICH_SHARED_LINK_ACCESS_COOKIE = 'immich_shared_link_token';
|
||||
export enum AuthType {
|
||||
PASSWORD = 'password',
|
||||
OAUTH = 'oauth',
|
||||
}
|
@ -1,155 +0,0 @@
|
||||
export enum QueueName {
|
||||
THUMBNAIL_GENERATION = 'thumbnailGeneration',
|
||||
METADATA_EXTRACTION = 'metadataExtraction',
|
||||
VIDEO_CONVERSION = 'videoConversion',
|
||||
FACE_DETECTION = 'faceDetection',
|
||||
FACIAL_RECOGNITION = 'facialRecognition',
|
||||
SMART_SEARCH = 'smartSearch',
|
||||
BACKGROUND_TASK = 'backgroundTask',
|
||||
STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration',
|
||||
MIGRATION = 'migration',
|
||||
SEARCH = 'search',
|
||||
SIDECAR = 'sidecar',
|
||||
LIBRARY = 'library',
|
||||
}
|
||||
|
||||
export type ConcurrentQueueName = Exclude<
|
||||
QueueName,
|
||||
QueueName.STORAGE_TEMPLATE_MIGRATION | QueueName.FACIAL_RECOGNITION
|
||||
>;
|
||||
|
||||
export enum JobCommand {
|
||||
START = 'start',
|
||||
PAUSE = 'pause',
|
||||
RESUME = 'resume',
|
||||
EMPTY = 'empty',
|
||||
CLEAR_FAILED = 'clear-failed',
|
||||
}
|
||||
|
||||
export enum JobName {
|
||||
// conversion
|
||||
QUEUE_VIDEO_CONVERSION = 'queue-video-conversion',
|
||||
VIDEO_CONVERSION = 'video-conversion',
|
||||
|
||||
// thumbnails
|
||||
QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails',
|
||||
GENERATE_JPEG_THUMBNAIL = 'generate-jpeg-thumbnail',
|
||||
GENERATE_WEBP_THUMBNAIL = 'generate-webp-thumbnail',
|
||||
GENERATE_THUMBHASH_THUMBNAIL = 'generate-thumbhash-thumbnail',
|
||||
GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail',
|
||||
|
||||
// metadata
|
||||
QUEUE_METADATA_EXTRACTION = 'queue-metadata-extraction',
|
||||
METADATA_EXTRACTION = 'metadata-extraction',
|
||||
LINK_LIVE_PHOTOS = 'link-live-photos',
|
||||
|
||||
// user
|
||||
USER_DELETION = 'user-deletion',
|
||||
USER_DELETE_CHECK = 'user-delete-check',
|
||||
USER_SYNC_USAGE = 'user-sync-usage',
|
||||
|
||||
// asset
|
||||
ASSET_DELETION = 'asset-deletion',
|
||||
ASSET_DELETION_CHECK = 'asset-deletion-check',
|
||||
|
||||
// storage template
|
||||
STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration',
|
||||
STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single',
|
||||
|
||||
// migration
|
||||
QUEUE_MIGRATION = 'queue-migration',
|
||||
MIGRATE_ASSET = 'migrate-asset',
|
||||
MIGRATE_PERSON = 'migrate-person',
|
||||
|
||||
// facial recognition
|
||||
PERSON_CLEANUP = 'person-cleanup',
|
||||
QUEUE_FACE_DETECTION = 'queue-face-detection',
|
||||
FACE_DETECTION = 'face-detection',
|
||||
QUEUE_FACIAL_RECOGNITION = 'queue-facial-recognition',
|
||||
FACIAL_RECOGNITION = 'facial-recognition',
|
||||
|
||||
// library managment
|
||||
LIBRARY_SCAN = 'library-refresh',
|
||||
LIBRARY_SCAN_ASSET = 'library-refresh-asset',
|
||||
LIBRARY_REMOVE_OFFLINE = 'library-remove-offline',
|
||||
LIBRARY_DELETE = 'library-delete',
|
||||
LIBRARY_QUEUE_SCAN_ALL = 'library-queue-all-refresh',
|
||||
LIBRARY_QUEUE_CLEANUP = 'library-queue-cleanup',
|
||||
|
||||
// cleanup
|
||||
DELETE_FILES = 'delete-files',
|
||||
CLEAN_OLD_AUDIT_LOGS = 'clean-old-audit-logs',
|
||||
|
||||
// smart search
|
||||
QUEUE_SMART_SEARCH = 'queue-smart-search',
|
||||
SMART_SEARCH = 'smart-search',
|
||||
|
||||
// XMP sidecars
|
||||
QUEUE_SIDECAR = 'queue-sidecar',
|
||||
SIDECAR_DISCOVERY = 'sidecar-discovery',
|
||||
SIDECAR_SYNC = 'sidecar-sync',
|
||||
SIDECAR_WRITE = 'sidecar-write',
|
||||
}
|
||||
|
||||
export const JOBS_ASSET_PAGINATION_SIZE = 1000;
|
||||
|
||||
export const JOBS_TO_QUEUE: Record<JobName, QueueName> = {
|
||||
// misc
|
||||
[JobName.ASSET_DELETION]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.ASSET_DELETION_CHECK]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.USER_DELETE_CHECK]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.USER_DELETION]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.DELETE_FILES]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.CLEAN_OLD_AUDIT_LOGS]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.PERSON_CLEANUP]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.USER_SYNC_USAGE]: QueueName.BACKGROUND_TASK,
|
||||
|
||||
// conversion
|
||||
[JobName.QUEUE_VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION,
|
||||
[JobName.VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION,
|
||||
|
||||
// thumbnails
|
||||
[JobName.QUEUE_GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_JPEG_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_WEBP_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_THUMBHASH_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
|
||||
// metadata
|
||||
[JobName.QUEUE_METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION,
|
||||
[JobName.METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION,
|
||||
[JobName.LINK_LIVE_PHOTOS]: QueueName.METADATA_EXTRACTION,
|
||||
|
||||
// storage template
|
||||
[JobName.STORAGE_TEMPLATE_MIGRATION]: QueueName.STORAGE_TEMPLATE_MIGRATION,
|
||||
[JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE]: QueueName.STORAGE_TEMPLATE_MIGRATION,
|
||||
|
||||
// migration
|
||||
[JobName.QUEUE_MIGRATION]: QueueName.MIGRATION,
|
||||
[JobName.MIGRATE_ASSET]: QueueName.MIGRATION,
|
||||
[JobName.MIGRATE_PERSON]: QueueName.MIGRATION,
|
||||
|
||||
// facial recognition
|
||||
[JobName.QUEUE_FACE_DETECTION]: QueueName.FACE_DETECTION,
|
||||
[JobName.FACE_DETECTION]: QueueName.FACE_DETECTION,
|
||||
[JobName.QUEUE_FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION,
|
||||
[JobName.FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION,
|
||||
|
||||
// smart search
|
||||
[JobName.QUEUE_SMART_SEARCH]: QueueName.SMART_SEARCH,
|
||||
[JobName.SMART_SEARCH]: QueueName.SMART_SEARCH,
|
||||
|
||||
// XMP sidecars
|
||||
[JobName.QUEUE_SIDECAR]: QueueName.SIDECAR,
|
||||
[JobName.SIDECAR_DISCOVERY]: QueueName.SIDECAR,
|
||||
[JobName.SIDECAR_SYNC]: QueueName.SIDECAR,
|
||||
[JobName.SIDECAR_WRITE]: QueueName.SIDECAR,
|
||||
|
||||
// Library management
|
||||
[JobName.LIBRARY_SCAN_ASSET]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_SCAN]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_DELETE]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_REMOVE_OFFLINE]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_QUEUE_SCAN_ALL]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_QUEUE_CLEANUP]: QueueName.LIBRARY,
|
||||
};
|
@ -1,41 +0,0 @@
|
||||
export interface IBaseJob {
|
||||
force?: boolean;
|
||||
}
|
||||
|
||||
export interface IEntityJob extends IBaseJob {
|
||||
id: string;
|
||||
source?: 'upload' | 'sidecar-write';
|
||||
}
|
||||
|
||||
export interface IAssetDeletionJob extends IEntityJob {
|
||||
fromExternal?: boolean;
|
||||
}
|
||||
|
||||
export interface ILibraryFileJob extends IEntityJob {
|
||||
ownerId: string;
|
||||
assetPath: string;
|
||||
}
|
||||
|
||||
export interface ILibraryRefreshJob extends IEntityJob {
|
||||
refreshModifiedFiles: boolean;
|
||||
refreshAllFiles: boolean;
|
||||
}
|
||||
|
||||
export interface IBulkEntityJob extends IBaseJob {
|
||||
ids: string[];
|
||||
}
|
||||
|
||||
export interface IDeleteFilesJob extends IBaseJob {
|
||||
files: Array<string | null | undefined>;
|
||||
}
|
||||
|
||||
export interface ISidecarWriteJob extends IEntityJob {
|
||||
description?: string;
|
||||
dateTimeOriginal?: string;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
}
|
||||
|
||||
export interface IDeferrableJob extends IEntityJob {
|
||||
deferred?: boolean;
|
||||
}
|
@ -1 +0,0 @@
|
||||
export const FACE_THUMBNAIL_SIZE = 250;
|
@ -1,129 +0,0 @@
|
||||
export type ModelInfo = {
|
||||
dimSize: number;
|
||||
};
|
||||
|
||||
export const CLIP_MODEL_INFO: Record<string, ModelInfo> = {
|
||||
RN50__openai: {
|
||||
dimSize: 1024,
|
||||
},
|
||||
RN50__yfcc15m: {
|
||||
dimSize: 1024,
|
||||
},
|
||||
RN50__cc12m: {
|
||||
dimSize: 1024,
|
||||
},
|
||||
RN101__openai: {
|
||||
dimSize: 512,
|
||||
},
|
||||
RN101__yfcc15m: {
|
||||
dimSize: 512,
|
||||
},
|
||||
RN50x4__openai: {
|
||||
dimSize: 640,
|
||||
},
|
||||
RN50x16__openai: {
|
||||
dimSize: 768,
|
||||
},
|
||||
RN50x64__openai: {
|
||||
dimSize: 1024,
|
||||
},
|
||||
'ViT-B-32__openai': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'ViT-B-32__laion2b_e16': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'ViT-B-32__laion400m_e31': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'ViT-B-32__laion400m_e32': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'ViT-B-32__laion2b-s34b-b79k': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'ViT-B-16__openai': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'ViT-B-16__laion400m_e31': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'ViT-B-16__laion400m_e32': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'ViT-B-16-plus-240__laion400m_e31': {
|
||||
dimSize: 640,
|
||||
},
|
||||
'ViT-B-16-plus-240__laion400m_e32': {
|
||||
dimSize: 640,
|
||||
},
|
||||
'ViT-L-14__openai': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'ViT-L-14__laion400m_e31': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'ViT-L-14__laion400m_e32': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'ViT-L-14__laion2b-s32b-b82k': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'ViT-L-14-336__openai': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'ViT-L-14-quickgelu__dfn2b': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'ViT-H-14__laion2b-s32b-b79k': {
|
||||
dimSize: 1024,
|
||||
},
|
||||
'ViT-H-14-quickgelu__dfn5b': {
|
||||
dimSize: 1024,
|
||||
},
|
||||
'ViT-H-14-378-quickgelu__dfn5b': {
|
||||
dimSize: 1024,
|
||||
},
|
||||
'ViT-g-14__laion2b-s12b-b42k': {
|
||||
dimSize: 1024,
|
||||
},
|
||||
'LABSE-Vit-L-14': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'XLM-Roberta-Large-Vit-B-32': {
|
||||
dimSize: 512,
|
||||
},
|
||||
'XLM-Roberta-Large-Vit-B-16Plus': {
|
||||
dimSize: 640,
|
||||
},
|
||||
'XLM-Roberta-Large-Vit-L-14': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'XLM-Roberta-Large-ViT-H-14__frozen_laion5b_s13b_b90k': {
|
||||
dimSize: 1024,
|
||||
},
|
||||
'nllb-clip-base-siglip__v1': {
|
||||
dimSize: 768,
|
||||
},
|
||||
'nllb-clip-large-siglip__v1': {
|
||||
dimSize: 1152,
|
||||
},
|
||||
};
|
||||
|
||||
export function cleanModelName(modelName: string): string {
|
||||
const token = modelName.split('/').at(-1);
|
||||
if (!token) {
|
||||
throw new Error(`Invalid model name: ${modelName}`);
|
||||
}
|
||||
|
||||
return token.replaceAll(':', '_');
|
||||
}
|
||||
|
||||
export function getCLIPModelInfo(modelName: string): ModelInfo {
|
||||
const modelInfo = CLIP_MODEL_INFO[cleanModelName(modelName)];
|
||||
if (!modelInfo) {
|
||||
throw new Error(`Unknown CLIP model: ${modelName}`);
|
||||
}
|
||||
|
||||
return modelInfo;
|
||||
}
|
@ -1,27 +0,0 @@
|
||||
export const supportedYearTokens = ['y', 'yy'];
|
||||
export const supportedMonthTokens = ['M', 'MM', 'MMM', 'MMMM'];
|
||||
export const supportedWeekTokens = ['W', 'WW'];
|
||||
export const supportedDayTokens = ['d', 'dd'];
|
||||
export const supportedHourTokens = ['h', 'hh', 'H', 'HH'];
|
||||
export const supportedMinuteTokens = ['m', 'mm'];
|
||||
export const supportedSecondTokens = ['s', 'ss', 'SSS'];
|
||||
export const supportedPresetTokens = [
|
||||
'{{y}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MM}}/{{filename}}',
|
||||
'{{y}}/{{MMM}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}/{{filename}}',
|
||||
'{{y}}/{{MM}}/{{dd}}/{{filename}}',
|
||||
'{{y}}/{{MMMM}}/{{dd}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{MM}}/{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MMM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}-{{MMMM}}-{{dd}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{MM}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{WW}}/{{filename}}',
|
||||
'{{y}}/{{y}}-{{MM}}-{{dd}}/{{assetId}}',
|
||||
'{{y}}/{{y}}-{{MM}}/{{assetId}}',
|
||||
'{{y}}/{{y}}-{{WW}}/{{assetId}}',
|
||||
'{{album}}/{{filename}}',
|
||||
];
|
@ -1,6 +1,6 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { IsEnum, IsNotEmpty } from 'class-validator';
|
||||
import { JobCommand, QueueName } from 'src/domain/job/job.constants';
|
||||
import { JobCommand, QueueName } from 'src/interfaces/job.repository';
|
||||
import { ValidateBoolean } from 'src/validation';
|
||||
|
||||
export class JobIdParamDto {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { ApiProperty, ApiResponseProperty } from '@nestjs/swagger';
|
||||
import type { DateTime } from 'luxon';
|
||||
import { FeatureFlags } from 'src/cores/system-config.core';
|
||||
import { IVersion, VersionType } from 'src/domain/domain.constant';
|
||||
import { SystemConfigThemeDto } from 'src/dtos/system-config-theme.dto';
|
||||
import { IVersion, VersionType } from 'src/utils/version';
|
||||
|
||||
export class ServerPingResponse {
|
||||
@ApiResponseProperty({ type: String, example: 'pong' })
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ApiProperty } from '@nestjs/swagger';
|
||||
import { Type } from 'class-transformer';
|
||||
import { IsInt, IsObject, IsPositive, ValidateNested } from 'class-validator';
|
||||
import { ConcurrentQueueName, QueueName } from 'src/domain/job/job.constants';
|
||||
import { ConcurrentQueueName, QueueName } from 'src/interfaces/job.repository';
|
||||
|
||||
export class JobSettingsDto {
|
||||
@IsInt()
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { ConcurrentQueueName } from 'src/domain/job/job.constants';
|
||||
import { ConcurrentQueueName } from 'src/interfaces/job.repository';
|
||||
import { Column, Entity, PrimaryColumn } from 'typeorm';
|
||||
|
||||
@Entity('system_config')
|
||||
|
@ -7,7 +7,7 @@ import { CheckExistingAssetsDto } from 'src/immich/api-v1/asset/dto/check-existi
|
||||
import { SearchPropertiesDto } from 'src/immich/api-v1/asset/dto/search-properties.dto';
|
||||
import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto';
|
||||
import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto';
|
||||
import { OptionalBetween } from 'src/infra/infra.utils';
|
||||
import { OptionalBetween } from 'src/utils/database';
|
||||
import { In } from 'typeorm/find-options/operator/In.js';
|
||||
import { Repository } from 'typeorm/repository/Repository.js';
|
||||
export interface AssetCheck {
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { when } from 'jest-when';
|
||||
import { JobName } from 'src/domain/job/job.constants';
|
||||
import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/entities/asset.entity';
|
||||
import { ExifEntity } from 'src/entities/exif.entity';
|
||||
import { IAssetRepositoryV1 } from 'src/immich/api-v1/asset/asset-repository';
|
||||
@ -7,7 +6,7 @@ import { AssetService } from 'src/immich/api-v1/asset/asset.service';
|
||||
import { CreateAssetDto } from 'src/immich/api-v1/asset/dto/create-asset.dto';
|
||||
import { AssetRejectReason, AssetUploadAction } from 'src/immich/api-v1/asset/response-dto/asset-check-response.dto';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { IJobRepository } from 'src/interfaces/job.repository';
|
||||
import { IJobRepository, JobName } from 'src/interfaces/job.repository';
|
||||
import { ILibraryRepository } from 'src/interfaces/library.repository';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.repository';
|
||||
import { IUserRepository } from 'src/interfaces/user.repository';
|
||||
|
@ -6,8 +6,6 @@ import {
|
||||
NotFoundException,
|
||||
} from '@nestjs/common';
|
||||
import { AccessCore, Permission } from 'src/cores/access.core';
|
||||
import { mimeTypes } from 'src/domain/domain.constant';
|
||||
import { JobName } from 'src/domain/job/job.constants';
|
||||
import { AssetResponseDto, mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { ASSET_CHECKSUM_CONSTRAINT, AssetEntity, AssetType } from 'src/entities/asset.entity';
|
||||
@ -28,15 +26,16 @@ import { AssetFileUploadResponseDto } from 'src/immich/api-v1/asset/response-dto
|
||||
import { CheckExistingAssetsResponseDto } from 'src/immich/api-v1/asset/response-dto/check-existing-assets-response.dto';
|
||||
import { CuratedLocationsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-locations-response.dto';
|
||||
import { CuratedObjectsResponseDto } from 'src/immich/api-v1/asset/response-dto/curated-objects-response.dto';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { IJobRepository } from 'src/interfaces/job.repository';
|
||||
import { IJobRepository, JobName } from 'src/interfaces/job.repository';
|
||||
import { ILibraryRepository } from 'src/interfaces/library.repository';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.repository';
|
||||
import { IUserRepository } from 'src/interfaces/user.repository';
|
||||
import { UploadFile } from 'src/services/asset.service';
|
||||
import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/utils';
|
||||
import { CacheControl, ImmichFileResponse, getLivePhotoMotionFilename } from 'src/utils/file';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
import { QueryFailedError } from 'typeorm';
|
||||
|
||||
@Injectable()
|
||||
|
@ -13,12 +13,12 @@ import { writeFileSync } from 'node:fs';
|
||||
import { access, constants } from 'node:fs/promises';
|
||||
import path, { isAbsolute } from 'node:path';
|
||||
import { promisify } from 'node:util';
|
||||
import { IMMICH_ACCESS_COOKIE, IMMICH_API_KEY_HEADER, IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant';
|
||||
import { serverVersion } from 'src/domain/domain.constant';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IMMICH_ACCESS_COOKIE, IMMICH_API_KEY_HEADER, IMMICH_API_KEY_NAME, serverVersion } from 'src/constants';
|
||||
import { ImmichReadStream } from 'src/interfaces/storage.repository';
|
||||
import { Metadata } from 'src/middleware/auth.guard';
|
||||
import { CacheControl, ImmichFileResponse, isConnectionAborted } from 'src/utils';
|
||||
import { CacheControl, ImmichFileResponse } from 'src/utils/file';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { isConnectionAborted } from 'src/utils/misc';
|
||||
|
||||
type SendFile = Parameters<Response['sendFile']>;
|
||||
type SendFileOptions = SendFile[1];
|
||||
|
@ -1,25 +0,0 @@
|
||||
import { format } from 'sql-formatter';
|
||||
import { Logger } from 'typeorm';
|
||||
|
||||
export class SqlLogger implements Logger {
|
||||
queries: string[] = [];
|
||||
errors: Array<{ error: string | Error; query: string }> = [];
|
||||
|
||||
clear() {
|
||||
this.queries = [];
|
||||
this.errors = [];
|
||||
}
|
||||
|
||||
logQuery(query: string) {
|
||||
this.queries.push(format(query, { language: 'postgresql' }));
|
||||
}
|
||||
|
||||
logQueryError(error: string | Error, query: string) {
|
||||
this.errors.push({ error, query });
|
||||
}
|
||||
|
||||
logQuerySlow() {}
|
||||
logSchemaBuild() {}
|
||||
logMigration() {}
|
||||
log() {}
|
||||
}
|
@ -4,7 +4,7 @@ import { AssetEntity, AssetType } from 'src/entities/asset.entity';
|
||||
import { ExifEntity } from 'src/entities/exif.entity';
|
||||
import { ReverseGeocodeResult } from 'src/interfaces/metadata.repository';
|
||||
import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.repository';
|
||||
import { Paginated, PaginationOptions } from 'src/utils';
|
||||
import { Paginated, PaginationOptions } from 'src/utils/pagination';
|
||||
import { FindOptionsRelations, FindOptionsSelect } from 'typeorm';
|
||||
|
||||
export type AssetStats = Record<AssetType, number>;
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Version } from 'src/domain/domain.constant';
|
||||
import { Version } from 'src/utils/version';
|
||||
|
||||
export enum DatabaseExtension {
|
||||
CUBE = 'cube',
|
||||
|
@ -1,14 +1,139 @@
|
||||
import { JobName, QueueName } from 'src/domain/job/job.constants';
|
||||
import {
|
||||
IAssetDeletionJob,
|
||||
IBaseJob,
|
||||
IDeferrableJob,
|
||||
IDeleteFilesJob,
|
||||
IEntityJob,
|
||||
ILibraryFileJob,
|
||||
ILibraryRefreshJob,
|
||||
ISidecarWriteJob,
|
||||
} from 'src/domain/job/job.interface';
|
||||
export enum QueueName {
|
||||
THUMBNAIL_GENERATION = 'thumbnailGeneration',
|
||||
METADATA_EXTRACTION = 'metadataExtraction',
|
||||
VIDEO_CONVERSION = 'videoConversion',
|
||||
FACE_DETECTION = 'faceDetection',
|
||||
FACIAL_RECOGNITION = 'facialRecognition',
|
||||
SMART_SEARCH = 'smartSearch',
|
||||
BACKGROUND_TASK = 'backgroundTask',
|
||||
STORAGE_TEMPLATE_MIGRATION = 'storageTemplateMigration',
|
||||
MIGRATION = 'migration',
|
||||
SEARCH = 'search',
|
||||
SIDECAR = 'sidecar',
|
||||
LIBRARY = 'library',
|
||||
}
|
||||
|
||||
export type ConcurrentQueueName = Exclude<
|
||||
QueueName,
|
||||
QueueName.STORAGE_TEMPLATE_MIGRATION | QueueName.FACIAL_RECOGNITION
|
||||
>;
|
||||
|
||||
export enum JobCommand {
|
||||
START = 'start',
|
||||
PAUSE = 'pause',
|
||||
RESUME = 'resume',
|
||||
EMPTY = 'empty',
|
||||
CLEAR_FAILED = 'clear-failed',
|
||||
}
|
||||
|
||||
export enum JobName {
|
||||
// conversion
|
||||
QUEUE_VIDEO_CONVERSION = 'queue-video-conversion',
|
||||
VIDEO_CONVERSION = 'video-conversion',
|
||||
|
||||
// thumbnails
|
||||
QUEUE_GENERATE_THUMBNAILS = 'queue-generate-thumbnails',
|
||||
GENERATE_JPEG_THUMBNAIL = 'generate-jpeg-thumbnail',
|
||||
GENERATE_WEBP_THUMBNAIL = 'generate-webp-thumbnail',
|
||||
GENERATE_THUMBHASH_THUMBNAIL = 'generate-thumbhash-thumbnail',
|
||||
GENERATE_PERSON_THUMBNAIL = 'generate-person-thumbnail',
|
||||
|
||||
// metadata
|
||||
QUEUE_METADATA_EXTRACTION = 'queue-metadata-extraction',
|
||||
METADATA_EXTRACTION = 'metadata-extraction',
|
||||
LINK_LIVE_PHOTOS = 'link-live-photos',
|
||||
|
||||
// user
|
||||
USER_DELETION = 'user-deletion',
|
||||
USER_DELETE_CHECK = 'user-delete-check',
|
||||
USER_SYNC_USAGE = 'user-sync-usage',
|
||||
|
||||
// asset
|
||||
ASSET_DELETION = 'asset-deletion',
|
||||
ASSET_DELETION_CHECK = 'asset-deletion-check',
|
||||
|
||||
// storage template
|
||||
STORAGE_TEMPLATE_MIGRATION = 'storage-template-migration',
|
||||
STORAGE_TEMPLATE_MIGRATION_SINGLE = 'storage-template-migration-single',
|
||||
|
||||
// migration
|
||||
QUEUE_MIGRATION = 'queue-migration',
|
||||
MIGRATE_ASSET = 'migrate-asset',
|
||||
MIGRATE_PERSON = 'migrate-person',
|
||||
|
||||
// facial recognition
|
||||
PERSON_CLEANUP = 'person-cleanup',
|
||||
QUEUE_FACE_DETECTION = 'queue-face-detection',
|
||||
FACE_DETECTION = 'face-detection',
|
||||
QUEUE_FACIAL_RECOGNITION = 'queue-facial-recognition',
|
||||
FACIAL_RECOGNITION = 'facial-recognition',
|
||||
|
||||
// library management
|
||||
LIBRARY_SCAN = 'library-refresh',
|
||||
LIBRARY_SCAN_ASSET = 'library-refresh-asset',
|
||||
LIBRARY_REMOVE_OFFLINE = 'library-remove-offline',
|
||||
LIBRARY_DELETE = 'library-delete',
|
||||
LIBRARY_QUEUE_SCAN_ALL = 'library-queue-all-refresh',
|
||||
LIBRARY_QUEUE_CLEANUP = 'library-queue-cleanup',
|
||||
|
||||
// cleanup
|
||||
DELETE_FILES = 'delete-files',
|
||||
CLEAN_OLD_AUDIT_LOGS = 'clean-old-audit-logs',
|
||||
|
||||
// smart search
|
||||
QUEUE_SMART_SEARCH = 'queue-smart-search',
|
||||
SMART_SEARCH = 'smart-search',
|
||||
|
||||
// XMP sidecars
|
||||
QUEUE_SIDECAR = 'queue-sidecar',
|
||||
SIDECAR_DISCOVERY = 'sidecar-discovery',
|
||||
SIDECAR_SYNC = 'sidecar-sync',
|
||||
SIDECAR_WRITE = 'sidecar-write',
|
||||
}
|
||||
|
||||
export const JOBS_ASSET_PAGINATION_SIZE = 1000;
|
||||
|
||||
export interface IBaseJob {
|
||||
force?: boolean;
|
||||
}
|
||||
|
||||
export interface IEntityJob extends IBaseJob {
|
||||
id: string;
|
||||
source?: 'upload' | 'sidecar-write';
|
||||
}
|
||||
|
||||
export interface IAssetDeletionJob extends IEntityJob {
|
||||
fromExternal?: boolean;
|
||||
}
|
||||
|
||||
export interface ILibraryFileJob extends IEntityJob {
|
||||
ownerId: string;
|
||||
assetPath: string;
|
||||
}
|
||||
|
||||
export interface ILibraryRefreshJob extends IEntityJob {
|
||||
refreshModifiedFiles: boolean;
|
||||
refreshAllFiles: boolean;
|
||||
}
|
||||
|
||||
export interface IBulkEntityJob extends IBaseJob {
|
||||
ids: string[];
|
||||
}
|
||||
|
||||
export interface IDeleteFilesJob extends IBaseJob {
|
||||
files: Array<string | null | undefined>;
|
||||
}
|
||||
|
||||
export interface ISidecarWriteJob extends IEntityJob {
|
||||
description?: string;
|
||||
dateTimeOriginal?: string;
|
||||
latitude?: number;
|
||||
longitude?: number;
|
||||
}
|
||||
|
||||
export interface IDeferrableJob extends IEntityJob {
|
||||
deferred?: boolean;
|
||||
}
|
||||
|
||||
export interface JobCounts {
|
||||
active: number;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { PersonEntity } from 'src/entities/person.entity';
|
||||
import { Paginated, PaginationOptions } from 'src/utils';
|
||||
import { Paginated, PaginationOptions } from 'src/utils/pagination';
|
||||
import { FindManyOptions, FindOptionsRelations, FindOptionsSelect } from 'typeorm';
|
||||
|
||||
export const IPersonRepository = 'IPersonRepository';
|
||||
|
@ -2,7 +2,7 @@ import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||
import { AssetEntity, AssetType } from 'src/entities/asset.entity';
|
||||
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
||||
import { SmartInfoEntity } from 'src/entities/smart-info.entity';
|
||||
import { Paginated } from 'src/utils';
|
||||
import { Paginated } from 'src/utils/pagination';
|
||||
|
||||
export const ISearchRepository = 'ISearchRepository';
|
||||
|
||||
|
@ -9,10 +9,10 @@ import {
|
||||
import { Reflector } from '@nestjs/core';
|
||||
import { ApiBearerAuth, ApiCookieAuth, ApiOkResponse, ApiQuery, ApiSecurity } from '@nestjs/swagger';
|
||||
import { Request } from 'express';
|
||||
import { IMMICH_API_KEY_NAME } from 'src/domain/auth/auth.constant';
|
||||
import { IMMICH_API_KEY_NAME } from 'src/constants';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { AuthService, LoginDetails } from 'src/services/auth.service';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { UAParser } from 'ua-parser-js';
|
||||
|
||||
export enum Metadata {
|
||||
|
@ -8,8 +8,8 @@ import {
|
||||
} from '@nestjs/common';
|
||||
import { Observable, catchError, throwError } from 'rxjs';
|
||||
import { routeToErrorMessage } from 'src/immich/app.utils';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { isConnectionAborted } from 'src/utils';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { isConnectionAborted } from 'src/utils/misc';
|
||||
|
||||
@Injectable()
|
||||
export class ErrorInterceptor implements NestInterceptor {
|
||||
|
@ -7,9 +7,9 @@ import multer, { StorageEngine, diskStorage } from 'multer';
|
||||
import { createHash, randomUUID } from 'node:crypto';
|
||||
import { Observable } from 'rxjs';
|
||||
import { UploadFieldName } from 'src/dtos/asset.dto';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { AuthRequest } from 'src/middleware/auth.guard';
|
||||
import { AssetService, UploadFile } from 'src/services/asset.service';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
export enum Route {
|
||||
ASSET = 'asset',
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant';
|
||||
import { vectorExt } from 'src/infra/database.config';
|
||||
import { vectorExt } from 'src/database.config';
|
||||
import { getCLIPModelInfo } from 'src/utils/misc';
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
export class UsePgVectors1700713871511 implements MigrationInterface {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { vectorExt } from 'src/infra/database.config';
|
||||
import { vectorExt } from 'src/database.config';
|
||||
import { DatabaseExtension } from 'src/interfaces/database.repository';
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { vectorExt } from 'src/infra/database.config';
|
||||
import { vectorExt } from 'src/database.config';
|
||||
import { DatabaseExtension } from 'src/interfaces/database.repository';
|
||||
import { MigrationInterface, QueryRunner } from 'typeorm';
|
||||
|
||||
|
@ -9,8 +9,8 @@ import { PartnerEntity } from 'src/entities/partner.entity';
|
||||
import { PersonEntity } from 'src/entities/person.entity';
|
||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
import { UserTokenEntity } from 'src/entities/user-token.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Brackets, In, Repository } from 'typeorm';
|
||||
|
||||
type IActivityAccess = IAccessRepository['activity'];
|
||||
|
@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { ActivityEntity } from 'src/entities/activity.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { IActivityRepository } from 'src/interfaces/activity.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { IsNull, Repository } from 'typeorm';
|
||||
|
||||
export interface ActivitySearch {
|
||||
|
@ -1,11 +1,10 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectDataSource, InjectRepository } from '@nestjs/typeorm';
|
||||
import _ from 'lodash';
|
||||
import { dataSource } from 'src/database.config';
|
||||
import { Chunked, ChunkedArray, DATABASE_PARAMETER_CHUNK_SIZE, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AlbumEntity } from 'src/entities/album.entity';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { dataSource } from 'src/infra/database.config';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import {
|
||||
AlbumAsset,
|
||||
AlbumAssetCount,
|
||||
@ -13,7 +12,8 @@ import {
|
||||
AlbumInfoOptions,
|
||||
IAlbumRepository,
|
||||
} from 'src/interfaces/album.repository';
|
||||
import { setUnion } from 'src/utils';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { setUnion } from 'src/utils/set';
|
||||
import { DataSource, FindOptionsOrder, FindOptionsRelations, In, IsNull, Not, Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { APIKeyEntity } from 'src/entities/api-key.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { IKeyRepository } from 'src/interfaces/api-key.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { AssetStackEntity } from 'src/entities/asset-stack.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -8,8 +8,6 @@ import { AssetJobStatusEntity } from 'src/entities/asset-job-status.entity';
|
||||
import { AssetEntity, AssetType } from 'src/entities/asset.entity';
|
||||
import { ExifEntity } from 'src/entities/exif.entity';
|
||||
import { SmartInfoEntity } from 'src/entities/smart-info.entity';
|
||||
import { OptionalBetween, paginate, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import {
|
||||
AssetBuilderOptions,
|
||||
AssetCreate,
|
||||
@ -32,7 +30,9 @@ import {
|
||||
WithoutProperty,
|
||||
} from 'src/interfaces/asset.repository';
|
||||
import { AssetSearchOptions, SearchExploreItem } from 'src/interfaces/search.repository';
|
||||
import { Paginated, PaginationMode, PaginationOptions } from 'src/utils';
|
||||
import { OptionalBetween, searchAssetBuilder } from 'src/utils/database';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Paginated, PaginationMode, PaginationOptions, paginate, paginatedBuilder } from 'src/utils/pagination';
|
||||
import {
|
||||
Brackets,
|
||||
FindOptionsRelations,
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { AuditEntity } from 'src/entities/audit.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { AuditSearch, IAuditRepository } from 'src/interfaces/audit.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { LessThan, MoreThan, Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -7,8 +7,6 @@ import {
|
||||
WebSocketServer,
|
||||
} from '@nestjs/websockets';
|
||||
import { Server, Socket } from 'socket.io';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import {
|
||||
ClientEvent,
|
||||
ICommunicationRepository,
|
||||
@ -18,6 +16,8 @@ import {
|
||||
ServerEvent,
|
||||
} from 'src/interfaces/communication.repository';
|
||||
import { AuthService } from 'src/services/auth.service';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
@Instrumentation()
|
||||
@WebSocketGateway({
|
||||
|
@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { compareSync, hash } from 'bcrypt';
|
||||
import { createHash, randomBytes, randomUUID } from 'node:crypto';
|
||||
import { createReadStream } from 'node:fs';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ICryptoRepository } from 'src/interfaces/crypto.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
|
||||
@Instrumentation()
|
||||
@Injectable()
|
||||
|
@ -1,10 +1,7 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectDataSource } from '@nestjs/typeorm';
|
||||
import AsyncLock from 'async-lock';
|
||||
import { Version, VersionType } from 'src/domain/domain.constant';
|
||||
import { vectorExt } from 'src/infra/database.config';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { vectorExt } from 'src/database.config';
|
||||
import {
|
||||
DatabaseExtension,
|
||||
DatabaseLock,
|
||||
@ -14,6 +11,9 @@ import {
|
||||
VectorUpdateResult,
|
||||
extName,
|
||||
} from 'src/interfaces/database.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { Version, VersionType } from 'src/utils/version';
|
||||
import { isValidInteger } from 'src/validation';
|
||||
import { DataSource, EntityManager, QueryRunner } from 'typeorm';
|
||||
|
||||
|
@ -4,10 +4,7 @@ import { glob, globStream } from 'fast-glob';
|
||||
import { constants, createReadStream, existsSync, mkdirSync } from 'node:fs';
|
||||
import fs from 'node:fs/promises';
|
||||
import path from 'node:path';
|
||||
import { mimeTypes } from 'src/domain/domain.constant';
|
||||
import { CrawlOptionsDto } from 'src/dtos/library.dto';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import {
|
||||
DiskUsage,
|
||||
IStorageRepository,
|
||||
@ -16,6 +13,9 @@ import {
|
||||
StorageEventType,
|
||||
WatchEvents,
|
||||
} from 'src/interfaces/storage.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
|
||||
@Instrumentation()
|
||||
export class FilesystemProvider implements IStorageRepository {
|
||||
|
@ -6,10 +6,78 @@ import { Job, JobsOptions, Processor, Queue, Worker, WorkerOptions } from 'bullm
|
||||
import { CronJob, CronTime } from 'cron';
|
||||
import { setTimeout } from 'node:timers/promises';
|
||||
import { bullConfig } from 'src/config';
|
||||
import { JOBS_TO_QUEUE, JobName, QueueName } from 'src/domain/job/job.constants';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IJobRepository, JobCounts, JobItem, QueueCleanType, QueueStatus } from 'src/interfaces/job.repository';
|
||||
import {
|
||||
IJobRepository,
|
||||
JobCounts,
|
||||
JobItem,
|
||||
JobName,
|
||||
QueueCleanType,
|
||||
QueueName,
|
||||
QueueStatus,
|
||||
} from 'src/interfaces/job.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
export const JOBS_TO_QUEUE: Record<JobName, QueueName> = {
|
||||
// misc
|
||||
[JobName.ASSET_DELETION]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.ASSET_DELETION_CHECK]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.USER_DELETE_CHECK]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.USER_DELETION]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.DELETE_FILES]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.CLEAN_OLD_AUDIT_LOGS]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.PERSON_CLEANUP]: QueueName.BACKGROUND_TASK,
|
||||
[JobName.USER_SYNC_USAGE]: QueueName.BACKGROUND_TASK,
|
||||
|
||||
// conversion
|
||||
[JobName.QUEUE_VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION,
|
||||
[JobName.VIDEO_CONVERSION]: QueueName.VIDEO_CONVERSION,
|
||||
|
||||
// thumbnails
|
||||
[JobName.QUEUE_GENERATE_THUMBNAILS]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_JPEG_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_WEBP_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_THUMBHASH_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
[JobName.GENERATE_PERSON_THUMBNAIL]: QueueName.THUMBNAIL_GENERATION,
|
||||
|
||||
// metadata
|
||||
[JobName.QUEUE_METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION,
|
||||
[JobName.METADATA_EXTRACTION]: QueueName.METADATA_EXTRACTION,
|
||||
[JobName.LINK_LIVE_PHOTOS]: QueueName.METADATA_EXTRACTION,
|
||||
|
||||
// storage template
|
||||
[JobName.STORAGE_TEMPLATE_MIGRATION]: QueueName.STORAGE_TEMPLATE_MIGRATION,
|
||||
[JobName.STORAGE_TEMPLATE_MIGRATION_SINGLE]: QueueName.STORAGE_TEMPLATE_MIGRATION,
|
||||
|
||||
// migration
|
||||
[JobName.QUEUE_MIGRATION]: QueueName.MIGRATION,
|
||||
[JobName.MIGRATE_ASSET]: QueueName.MIGRATION,
|
||||
[JobName.MIGRATE_PERSON]: QueueName.MIGRATION,
|
||||
|
||||
// facial recognition
|
||||
[JobName.QUEUE_FACE_DETECTION]: QueueName.FACE_DETECTION,
|
||||
[JobName.FACE_DETECTION]: QueueName.FACE_DETECTION,
|
||||
[JobName.QUEUE_FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION,
|
||||
[JobName.FACIAL_RECOGNITION]: QueueName.FACIAL_RECOGNITION,
|
||||
|
||||
// smart search
|
||||
[JobName.QUEUE_SMART_SEARCH]: QueueName.SMART_SEARCH,
|
||||
[JobName.SMART_SEARCH]: QueueName.SMART_SEARCH,
|
||||
|
||||
// XMP sidecars
|
||||
[JobName.QUEUE_SIDECAR]: QueueName.SIDECAR,
|
||||
[JobName.SIDECAR_DISCOVERY]: QueueName.SIDECAR,
|
||||
[JobName.SIDECAR_SYNC]: QueueName.SIDECAR,
|
||||
[JobName.SIDECAR_WRITE]: QueueName.SIDECAR,
|
||||
|
||||
// Library management
|
||||
[JobName.LIBRARY_SCAN_ASSET]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_SCAN]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_DELETE]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_REMOVE_OFFLINE]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_QUEUE_SCAN_ALL]: QueueName.LIBRARY,
|
||||
[JobName.LIBRARY_QUEUE_CLEANUP]: QueueName.LIBRARY,
|
||||
};
|
||||
|
||||
@Instrumentation()
|
||||
@Injectable()
|
||||
|
@ -3,8 +3,8 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { LibraryStatsResponseDto } from 'src/dtos/library.dto';
|
||||
import { LibraryEntity, LibraryType } from 'src/entities/library.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ILibraryRepository } from 'src/interfaces/library.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { IsNull, Not } from 'typeorm';
|
||||
import { Repository } from 'typeorm/repository/Repository.js';
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { CLIPConfig, ModelConfig, RecognitionConfig } from 'src/dtos/model-config.dto';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import {
|
||||
CLIPMode,
|
||||
DetectFaceResult,
|
||||
@ -10,6 +9,7 @@ import {
|
||||
TextModelInput,
|
||||
VisionModelInput,
|
||||
} from 'src/interfaces/machine-learning.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
|
||||
const errorPrefix = 'Machine learning request';
|
||||
|
||||
|
@ -4,8 +4,6 @@ import { Writable } from 'node:stream';
|
||||
import { promisify } from 'node:util';
|
||||
import sharp from 'sharp';
|
||||
import { Colorspace } from 'src/entities/system-config.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import {
|
||||
CropOptions,
|
||||
IMediaRepository,
|
||||
@ -13,7 +11,9 @@ import {
|
||||
TranscodeOptions,
|
||||
VideoInfo,
|
||||
} from 'src/interfaces/media.repository';
|
||||
import { handlePromiseError } from 'src/utils';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { handlePromiseError } from 'src/utils/misc';
|
||||
|
||||
const probe = promisify<string, FfprobeData>(ffmpeg.ffprobe);
|
||||
sharp.concurrency(0);
|
||||
|
@ -6,21 +6,15 @@ import { getName } from 'i18n-iso-countries';
|
||||
import { createReadStream, existsSync } from 'node:fs';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import readLine from 'node:readline';
|
||||
import { citiesFile, geodataAdmin1Path, geodataAdmin2Path, geodataCities500Path, geodataDatePath } from 'src/constants';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import {
|
||||
citiesFile,
|
||||
geodataAdmin1Path,
|
||||
geodataAdmin2Path,
|
||||
geodataCities500Path,
|
||||
geodataDatePath,
|
||||
} from 'src/domain/domain.constant';
|
||||
import { ExifEntity } from 'src/entities/exif.entity';
|
||||
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
||||
import { SystemMetadataKey } from 'src/entities/system-metadata.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { GeoPoint, IMetadataRepository, ImmichTags, ReverseGeocodeResult } from 'src/interfaces/metadata.repository';
|
||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { DataSource, QueryRunner, Repository } from 'typeorm';
|
||||
import { QueryDeepPartialEntity } from 'typeorm/query-builder/QueryPartialEntity.js';
|
||||
|
||||
|
@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { MoveEntity, PathType } from 'src/entities/move.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { IMoveRepository, MoveCreate } from 'src/interfaces/move.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { PartnerEntity } from 'src/entities/partner.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { IPartnerRepository, PartnerIds } from 'src/interfaces/partner.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { DeepPartial, Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -4,8 +4,6 @@ import { ChunkedArray, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { PersonEntity } from 'src/entities/person.entity';
|
||||
import { asVector, paginate } from 'src/infra/infra.utils';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import {
|
||||
AssetFaceId,
|
||||
IPersonRepository,
|
||||
@ -15,7 +13,9 @@ import {
|
||||
PersonStatistics,
|
||||
UpdateFacesData,
|
||||
} from 'src/interfaces/person.repository';
|
||||
import { Paginated, PaginationOptions } from 'src/utils';
|
||||
import { asVector } from 'src/utils/database';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Paginated, PaginationOptions, paginate } from 'src/utils/pagination';
|
||||
import { FindManyOptions, FindOptionsRelations, FindOptionsSelect, In, Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -1,16 +1,12 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { vectorExt } from 'src/database.config';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { getCLIPModelInfo } from 'src/domain/smart-info/smart-info.constant';
|
||||
import { AssetFaceEntity } from 'src/entities/asset-face.entity';
|
||||
import { AssetEntity, AssetType } from 'src/entities/asset.entity';
|
||||
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
|
||||
import { SmartInfoEntity } from 'src/entities/smart-info.entity';
|
||||
import { SmartSearchEntity } from 'src/entities/smart-search.entity';
|
||||
import { vectorExt } from 'src/infra/database.config';
|
||||
import { asVector, paginatedBuilder, searchAssetBuilder } from 'src/infra/infra.utils';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { DatabaseExtension } from 'src/interfaces/database.repository';
|
||||
import {
|
||||
AssetSearchOptions,
|
||||
@ -21,7 +17,11 @@ import {
|
||||
SearchPaginationOptions,
|
||||
SmartSearchOptions,
|
||||
} from 'src/interfaces/search.repository';
|
||||
import { Paginated, PaginationMode, PaginationResult } from 'src/utils';
|
||||
import { asVector, searchAssetBuilder } from 'src/utils/database';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { getCLIPModelInfo } from 'src/utils/misc';
|
||||
import { Paginated, PaginationMode, PaginationResult, paginatedBuilder } from 'src/utils/pagination';
|
||||
import { isValidInteger } from 'src/validation';
|
||||
import { Repository, SelectQueryBuilder } from 'typeorm';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@nestjs/common';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { GitHubRelease, IServerInfoRepository } from 'src/interfaces/server-info.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
|
||||
@Instrumentation()
|
||||
@Injectable()
|
||||
|
@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { SharedLinkEntity } from 'src/entities/shared-link.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -2,8 +2,8 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { Chunked, DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { SystemConfigEntity } from 'src/entities/system-config.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { In, Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { SystemMetadata, SystemMetadataEntity } from 'src/entities/system-metadata.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ISystemMetadataRepository } from 'src/interfaces/system-metadata.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { TagEntity } from 'src/entities/tag.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { ITagRepository } from 'src/interfaces/tag.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common';
|
||||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { UserTokenEntity } from 'src/entities/user-token.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import { IUserTokenRepository } from 'src/interfaces/user-token.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -3,13 +3,13 @@ import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { DummyValue, GenerateSql } from 'src/decorators';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { UserEntity } from 'src/entities/user.entity';
|
||||
import { Instrumentation } from 'src/infra/instrumentation';
|
||||
import {
|
||||
IUserRepository,
|
||||
UserFindOptions,
|
||||
UserListFilter,
|
||||
UserStatsQueryResponse,
|
||||
} from 'src/interfaces/user.repository';
|
||||
import { Instrumentation } from 'src/utils/instrumentation';
|
||||
import { IsNull, Not, Repository } from 'typeorm';
|
||||
|
||||
@Instrumentation()
|
||||
|
@ -21,7 +21,7 @@ import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { AlbumAssetCount, AlbumInfoOptions, IAlbumRepository } from 'src/interfaces/album.repository';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { IUserRepository } from 'src/interfaces/user.repository';
|
||||
import { setUnion } from 'src/utils';
|
||||
import { setUnion } from 'src/utils/set';
|
||||
|
||||
@Injectable()
|
||||
export class AlbumService {
|
||||
|
@ -1,13 +1,12 @@
|
||||
import { BadRequestException, UnauthorizedException } from '@nestjs/common';
|
||||
import { when } from 'jest-when';
|
||||
import { JobName } from 'src/domain/job/job.constants';
|
||||
import { mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AssetJobName, AssetStatsResponseDto, UploadFieldName } from 'src/dtos/asset.dto';
|
||||
import { AssetEntity, AssetType } from 'src/entities/asset.entity';
|
||||
import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository';
|
||||
import { AssetStats, IAssetRepository, TimeBucketSize } from 'src/interfaces/asset.repository';
|
||||
import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository';
|
||||
import { IJobRepository, JobItem } from 'src/interfaces/job.repository';
|
||||
import { IJobRepository, JobItem, JobName } from 'src/interfaces/job.repository';
|
||||
import { IPartnerRepository } from 'src/interfaces/partner.repository';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.repository';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
|
@ -6,9 +6,6 @@ import sanitize from 'sanitize-filename';
|
||||
import { AccessCore, Permission } from 'src/cores/access.core';
|
||||
import { StorageCore, StorageFolder } from 'src/cores/storage.core';
|
||||
import { SystemConfigCore } from 'src/cores/system-config.core';
|
||||
import { mimeTypes } from 'src/domain/domain.constant';
|
||||
import { JOBS_ASSET_PAGINATION_SIZE, JobName } from 'src/domain/job/job.constants';
|
||||
import { IAssetDeletionJob, ISidecarWriteJob } from 'src/domain/job/job.interface';
|
||||
import {
|
||||
AssetResponseDto,
|
||||
MemoryLaneResponseDto,
|
||||
@ -31,17 +28,26 @@ import { UpdateStackParentDto } from 'src/dtos/stack.dto';
|
||||
import { TimeBucketAssetDto, TimeBucketDto, TimeBucketResponseDto } from 'src/dtos/time-bucket.dto';
|
||||
import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { LibraryType } from 'src/entities/library.entity';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { IAssetStackRepository } from 'src/interfaces/asset-stack.repository';
|
||||
import { IAssetRepository, TimeBucketOptions } from 'src/interfaces/asset.repository';
|
||||
import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository';
|
||||
import { IJobRepository, JobItem, JobStatus } from 'src/interfaces/job.repository';
|
||||
import {
|
||||
IAssetDeletionJob,
|
||||
IJobRepository,
|
||||
ISidecarWriteJob,
|
||||
JOBS_ASSET_PAGINATION_SIZE,
|
||||
JobItem,
|
||||
JobName,
|
||||
JobStatus,
|
||||
} from 'src/interfaces/job.repository';
|
||||
import { IPartnerRepository } from 'src/interfaces/partner.repository';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.repository';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
import { IUserRepository } from 'src/interfaces/user.repository';
|
||||
import { usePagination } from 'src/utils';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
import { usePagination } from 'src/utils/pagination';
|
||||
|
||||
export interface UploadRequest {
|
||||
auth: AuthDto | null;
|
||||
|
@ -1,10 +1,9 @@
|
||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||
import { DateTime } from 'luxon';
|
||||
import { resolve } from 'node:path';
|
||||
import { AUDIT_LOG_MAX_DURATION } from 'src/constants';
|
||||
import { AccessCore, Permission } from 'src/cores/access.core';
|
||||
import { StorageCore, StorageFolder } from 'src/cores/storage.core';
|
||||
import { AUDIT_LOG_MAX_DURATION } from 'src/domain/domain.constant';
|
||||
import { JOBS_ASSET_PAGINATION_SIZE } from 'src/domain/job/job.constants';
|
||||
import {
|
||||
AuditDeletesDto,
|
||||
AuditDeletesResponseDto,
|
||||
@ -16,16 +15,16 @@ import {
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { DatabaseAction } from 'src/entities/audit.entity';
|
||||
import { AssetPathType, PersonPathType, UserPathType } from 'src/entities/move.entity';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { IAuditRepository } from 'src/interfaces/audit.repository';
|
||||
import { ICryptoRepository } from 'src/interfaces/crypto.repository';
|
||||
import { JobStatus } from 'src/interfaces/job.repository';
|
||||
import { JOBS_ASSET_PAGINATION_SIZE, JobStatus } from 'src/interfaces/job.repository';
|
||||
import { IPersonRepository } from 'src/interfaces/person.repository';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.repository';
|
||||
import { IUserRepository } from 'src/interfaces/user.repository';
|
||||
import { usePagination } from 'src/utils';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { usePagination } from 'src/utils/pagination';
|
||||
|
||||
@Injectable()
|
||||
export class AuditService {
|
||||
|
@ -2,7 +2,7 @@ import { BadRequestException, UnauthorizedException } from '@nestjs/common';
|
||||
import { IncomingHttpHeaders } from 'node:http';
|
||||
import { Issuer, generators } from 'openid-client';
|
||||
import { Socket } from 'socket.io';
|
||||
import { AuthType } from 'src/domain/auth/auth.constant';
|
||||
import { AuthType } from 'src/constants';
|
||||
import { AuthDto, SignUpDto } from 'src/dtos/auth.dto';
|
||||
import { UserEntity } from 'src/entities/user.entity';
|
||||
import { IKeyRepository } from 'src/interfaces/api-key.repository';
|
||||
|
@ -10,9 +10,6 @@ import cookieParser from 'cookie';
|
||||
import { DateTime } from 'luxon';
|
||||
import { IncomingHttpHeaders } from 'node:http';
|
||||
import { ClientMetadata, Issuer, UserinfoResponse, custom, generators } from 'openid-client';
|
||||
import { AccessCore, Permission } from 'src/cores/access.core';
|
||||
import { SystemConfigCore } from 'src/cores/system-config.core';
|
||||
import { UserCore } from 'src/cores/user.core';
|
||||
import {
|
||||
AuthType,
|
||||
IMMICH_ACCESS_COOKIE,
|
||||
@ -21,7 +18,10 @@ import {
|
||||
IMMICH_IS_AUTHENTICATED,
|
||||
LOGIN_URL,
|
||||
MOBILE_REDIRECT,
|
||||
} from 'src/domain/auth/auth.constant';
|
||||
} from 'src/constants';
|
||||
import { AccessCore, Permission } from 'src/cores/access.core';
|
||||
import { SystemConfigCore } from 'src/cores/system-config.core';
|
||||
import { UserCore } from 'src/cores/user.core';
|
||||
import {
|
||||
AuthDeviceResponseDto,
|
||||
AuthDto,
|
||||
@ -39,7 +39,6 @@ import {
|
||||
import { UserResponseDto, mapUser } from 'src/dtos/user.dto';
|
||||
import { SystemConfig } from 'src/entities/system-config.entity';
|
||||
import { UserEntity } from 'src/entities/user.entity';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { IKeyRepository } from 'src/interfaces/api-key.repository';
|
||||
import { ICryptoRepository } from 'src/interfaces/crypto.repository';
|
||||
@ -48,7 +47,8 @@ import { ISharedLinkRepository } from 'src/interfaces/shared-link.repository';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
import { IUserTokenRepository } from 'src/interfaces/user-token.repository';
|
||||
import { IUserRepository } from 'src/interfaces/user.repository';
|
||||
import { HumanReadableSize } from 'src/utils';
|
||||
import { HumanReadableSize } from 'src/utils/bytes';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
export interface LoginDetails {
|
||||
isSecure: boolean;
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { Version, VersionType } from 'src/domain/domain.constant';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { DatabaseExtension, IDatabaseRepository, VectorIndex } from 'src/interfaces/database.repository';
|
||||
import { DatabaseService } from 'src/services/database.service';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { Version, VersionType } from 'src/utils/version';
|
||||
import { newDatabaseRepositoryMock } from 'test/repositories/database.repository.mock';
|
||||
|
||||
describe(DatabaseService.name, () => {
|
||||
|
@ -1,6 +1,4 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Version, VersionType } from 'src/domain/domain.constant';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import {
|
||||
DatabaseExtension,
|
||||
DatabaseLock,
|
||||
@ -9,6 +7,8 @@ import {
|
||||
VectorIndex,
|
||||
extName,
|
||||
} from 'src/interfaces/database.repository';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
import { Version, VersionType } from 'src/utils/version';
|
||||
|
||||
@Injectable()
|
||||
export class DatabaseService {
|
||||
|
@ -4,7 +4,7 @@ import { DownloadResponseDto } from 'src/dtos/download.dto';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { IStorageRepository } from 'src/interfaces/storage.repository';
|
||||
import { DownloadService } from 'src/services/download.service';
|
||||
import { CacheControl, ImmichFileResponse } from 'src/utils';
|
||||
import { CacheControl, ImmichFileResponse } from 'src/utils/file';
|
||||
import { assetStub } from 'test/fixtures/asset.stub';
|
||||
import { authStub } from 'test/fixtures/auth.stub';
|
||||
import { IAccessRepositoryMock, newAccessRepositoryMock } from 'test/repositories/access.repository.mock';
|
||||
|
@ -1,7 +1,6 @@
|
||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||
import { parse } from 'node:path';
|
||||
import { AccessCore, Permission } from 'src/cores/access.core';
|
||||
import { mimeTypes } from 'src/domain/domain.constant';
|
||||
import { AssetIdsDto } from 'src/dtos/asset.dto';
|
||||
import { AuthDto } from 'src/dtos/auth.dto';
|
||||
import { DownloadArchiveInfo, DownloadInfoDto, DownloadResponseDto } from 'src/dtos/download.dto';
|
||||
@ -9,7 +8,10 @@ import { AssetEntity } from 'src/entities/asset.entity';
|
||||
import { IAccessRepository } from 'src/interfaces/access.repository';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { IStorageRepository, ImmichReadStream } from 'src/interfaces/storage.repository';
|
||||
import { CacheControl, HumanReadableSize, ImmichFileResponse, usePagination } from 'src/utils';
|
||||
import { HumanReadableSize } from 'src/utils/bytes';
|
||||
import { CacheControl, ImmichFileResponse } from 'src/utils/file';
|
||||
import { mimeTypes } from 'src/utils/mime-types';
|
||||
import { usePagination } from 'src/utils/pagination';
|
||||
|
||||
@Injectable()
|
||||
export class DownloadService {
|
||||
|
@ -1,10 +1,17 @@
|
||||
import { BadRequestException } from '@nestjs/common';
|
||||
import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core';
|
||||
import { JobCommand, JobName, QueueName } from 'src/domain/job/job.constants';
|
||||
import { SystemConfig, SystemConfigKey } from 'src/entities/system-config.entity';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { ICommunicationRepository } from 'src/interfaces/communication.repository';
|
||||
import { IJobRepository, JobHandler, JobItem, JobStatus } from 'src/interfaces/job.repository';
|
||||
import {
|
||||
IJobRepository,
|
||||
JobCommand,
|
||||
JobHandler,
|
||||
JobItem,
|
||||
JobName,
|
||||
JobStatus,
|
||||
QueueName,
|
||||
} from 'src/interfaces/job.repository';
|
||||
import { IPersonRepository } from 'src/interfaces/person.repository';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
import { JobService } from 'src/services/job.service';
|
||||
|
@ -1,15 +1,24 @@
|
||||
import { BadRequestException, Inject, Injectable } from '@nestjs/common';
|
||||
import { FeatureFlag, SystemConfigCore } from 'src/cores/system-config.core';
|
||||
import { ConcurrentQueueName, JobCommand, JobName, QueueName } from 'src/domain/job/job.constants';
|
||||
import { mapAsset } from 'src/dtos/asset-response.dto';
|
||||
import { AllJobStatusResponseDto, JobCommandDto, JobStatusDto } from 'src/dtos/job.dto';
|
||||
import { AssetType } from 'src/entities/asset.entity';
|
||||
import { ImmichLogger } from 'src/infra/logger';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { ClientEvent, ICommunicationRepository } from 'src/interfaces/communication.repository';
|
||||
import { IJobRepository, JobHandler, JobItem, JobStatus, QueueCleanType } from 'src/interfaces/job.repository';
|
||||
import {
|
||||
ConcurrentQueueName,
|
||||
IJobRepository,
|
||||
JobCommand,
|
||||
JobHandler,
|
||||
JobItem,
|
||||
JobName,
|
||||
JobStatus,
|
||||
QueueCleanType,
|
||||
QueueName,
|
||||
} from 'src/interfaces/job.repository';
|
||||
import { IPersonRepository } from 'src/interfaces/person.repository';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
import { ImmichLogger } from 'src/utils/logger';
|
||||
|
||||
@Injectable()
|
||||
export class JobService {
|
||||
|
@ -3,8 +3,6 @@ import { when } from 'jest-when';
|
||||
import { R_OK } from 'node:constants';
|
||||
import { Stats } from 'node:fs';
|
||||
import { SystemConfigCore } from 'src/cores/system-config.core';
|
||||
import { JobName } from 'src/domain/job/job.constants';
|
||||
import { ILibraryFileJob, ILibraryRefreshJob } from 'src/domain/job/job.interface';
|
||||
import { mapLibrary } from 'src/dtos/library.dto';
|
||||
import { AssetType } from 'src/entities/asset.entity';
|
||||
import { LibraryType } from 'src/entities/library.entity';
|
||||
@ -13,7 +11,7 @@ import { UserEntity } from 'src/entities/user.entity';
|
||||
import { IAssetRepository } from 'src/interfaces/asset.repository';
|
||||
import { ICryptoRepository } from 'src/interfaces/crypto.repository';
|
||||
import { IDatabaseRepository } from 'src/interfaces/database.repository';
|
||||
import { IJobRepository, JobStatus } from 'src/interfaces/job.repository';
|
||||
import { IJobRepository, ILibraryFileJob, ILibraryRefreshJob, JobName, JobStatus } from 'src/interfaces/job.repository';
|
||||
import { ILibraryRepository } from 'src/interfaces/library.repository';
|
||||
import { IStorageRepository, StorageEventType } from 'src/interfaces/storage.repository';
|
||||
import { ISystemConfigRepository } from 'src/interfaces/system-config.repository';
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user