0
Fork 0
mirror of https://github.com/immich-app/immich.git synced 2025-01-21 00:52:43 -05:00

refactor(server): resource paths (#13194)

This commit is contained in:
Jason Rasmussen 2024-10-04 17:09:02 -04:00 committed by GitHub
parent 5d0a4bb1a5
commit 6bbaba7866
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 68 additions and 29 deletions

View file

@ -1,6 +1,5 @@
import { Duration } from 'luxon'; import { Duration } from 'luxon';
import { readFileSync } from 'node:fs'; import { readFileSync } from 'node:fs';
import { join } from 'node:path';
import { SemVer } from 'semver'; import { SemVer } from 'semver';
export const POSTGRES_VERSION_RANGE = '>=14.0.0'; export const POSTGRES_VERSION_RANGE = '>=14.0.0';
@ -26,28 +25,6 @@ export const DEFAULT_EXTERNAL_DOMAIN = 'http://localhost:' + HOST_SERVER_PORT;
export const citiesFile = 'cities500.txt'; export const citiesFile = 'cities500.txt';
const buildFolder = process.env.IMMICH_BUILD_DATA || '/build';
const folders = {
geodata: join(buildFolder, 'geodata'),
web: join(buildFolder, 'www'),
};
export const resourcePaths = {
lockFile: join(buildFolder, 'build-lock.json'),
geodata: {
dateFile: join(folders.geodata, 'geodata-date.txt'),
admin1: join(folders.geodata, 'admin1CodesASCII.txt'),
admin2: join(folders.geodata, 'admin2Codes.txt'),
cities500: join(folders.geodata, citiesFile),
naturalEarthCountriesPath: join(folders.geodata, 'ne_10m_admin_0_countries.geojson'),
},
web: {
root: folders.web,
indexHtml: join(folders.web, 'index.html'),
},
};
export const MOBILE_REDIRECT = 'app.immich:///oauth-callback'; export const MOBILE_REDIRECT = 'app.immich:///oauth-callback';
export const LOGIN_URL = '/auth/login?autoLaunch=0'; export const LOGIN_URL = '/auth/login?autoLaunch=0';

View file

@ -41,6 +41,21 @@ export interface EnvData {
server: string; server: string;
}; };
resourcePaths: {
lockFile: string;
geodata: {
dateFile: string;
admin1: string;
admin2: string;
cities500: string;
naturalEarthCountriesPath: string;
};
web: {
root: string;
indexHtml: string;
};
};
storage: { storage: {
ignoreMountCheckErrors: boolean; ignoreMountCheckErrors: boolean;
}; };

View file

@ -1,4 +1,6 @@
import { Injectable } from '@nestjs/common'; import { Injectable } from '@nestjs/common';
import { join } from 'node:path';
import { citiesFile } from 'src/constants';
import { ImmichEnvironment, ImmichWorker, LogLevel } from 'src/enum'; import { ImmichEnvironment, ImmichWorker, LogLevel } from 'src/enum';
import { EnvData, IConfigRepository } from 'src/interfaces/config.interface'; import { EnvData, IConfigRepository } from 'src/interfaces/config.interface';
import { DatabaseExtension } from 'src/interfaces/database.interface'; import { DatabaseExtension } from 'src/interfaces/database.interface';
@ -41,6 +43,11 @@ export class ConfigRepository implements IConfigRepository {
const environment = process.env.IMMICH_ENV as ImmichEnvironment; const environment = process.env.IMMICH_ENV as ImmichEnvironment;
const isProd = environment === ImmichEnvironment.PRODUCTION; const isProd = environment === ImmichEnvironment.PRODUCTION;
const buildFolder = process.env.IMMICH_BUILD_DATA || '/build';
const folders = {
geodata: join(buildFolder, 'geodata'),
web: join(buildFolder, 'www'),
};
return { return {
port: Number(process.env.IMMICH_PORT) || 3001, port: Number(process.env.IMMICH_PORT) || 3001,
@ -79,6 +86,21 @@ export class ConfigRepository implements IConfigRepository {
licensePublicKey: isProd ? productionKeys : stagingKeys, licensePublicKey: isProd ? productionKeys : stagingKeys,
resourcePaths: {
lockFile: join(buildFolder, 'build-lock.json'),
geodata: {
dateFile: join(folders.geodata, 'geodata-date.txt'),
admin1: join(folders.geodata, 'admin1CodesASCII.txt'),
admin2: join(folders.geodata, 'admin2Codes.txt'),
cities500: join(folders.geodata, citiesFile),
naturalEarthCountriesPath: join(folders.geodata, 'ne_10m_admin_0_countries.geojson'),
},
web: {
root: folders.web,
indexHtml: join(folders.web, 'index.html'),
},
},
storage: { storage: {
ignoreMountCheckErrors: process.env.IMMICH_IGNORE_MOUNT_CHECK_ERRORS === 'true', ignoreMountCheckErrors: process.env.IMMICH_IGNORE_MOUNT_CHECK_ERRORS === 'true',
}, },

View file

@ -4,11 +4,12 @@ import { getName } from 'i18n-iso-countries';
import { createReadStream, existsSync } from 'node:fs'; import { createReadStream, existsSync } from 'node:fs';
import { readFile } from 'node:fs/promises'; import { readFile } from 'node:fs/promises';
import readLine from 'node:readline'; import readLine from 'node:readline';
import { citiesFile, resourcePaths } from 'src/constants'; import { citiesFile } from 'src/constants';
import { AssetEntity } from 'src/entities/asset.entity'; import { AssetEntity } from 'src/entities/asset.entity';
import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity'; import { GeodataPlacesEntity } from 'src/entities/geodata-places.entity';
import { NaturalEarthCountriesEntity } from 'src/entities/natural-earth-countries.entity'; import { NaturalEarthCountriesEntity } from 'src/entities/natural-earth-countries.entity';
import { SystemMetadataKey } from 'src/enum'; import { SystemMetadataKey } from 'src/enum';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { import {
GeoPoint, GeoPoint,
@ -32,6 +33,7 @@ export class MapRepository implements IMapRepository {
@InjectRepository(NaturalEarthCountriesEntity) @InjectRepository(NaturalEarthCountriesEntity)
private naturalEarthCountriesRepository: Repository<NaturalEarthCountriesEntity>, private naturalEarthCountriesRepository: Repository<NaturalEarthCountriesEntity>,
@InjectDataSource() private dataSource: DataSource, @InjectDataSource() private dataSource: DataSource,
@Inject(IConfigRepository) private configRepository: IConfigRepository,
@Inject(ISystemMetadataRepository) private metadataRepository: ISystemMetadataRepository, @Inject(ISystemMetadataRepository) private metadataRepository: ISystemMetadataRepository,
@Inject(ILoggerRepository) private logger: ILoggerRepository, @Inject(ILoggerRepository) private logger: ILoggerRepository,
) { ) {
@ -40,6 +42,7 @@ export class MapRepository implements IMapRepository {
async init(): Promise<void> { async init(): Promise<void> {
this.logger.log('Initializing metadata repository'); this.logger.log('Initializing metadata repository');
const { resourcePaths } = this.configRepository.getEnv();
const geodataDate = await readFile(resourcePaths.geodata.dateFile, 'utf8'); const geodataDate = await readFile(resourcePaths.geodata.dateFile, 'utf8');
// TODO move to service init // TODO move to service init
@ -181,6 +184,8 @@ export class MapRepository implements IMapRepository {
const queryRunner = this.dataSource.createQueryRunner(); const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
const { resourcePaths } = this.configRepository.getEnv();
try { try {
await queryRunner.startTransaction(); await queryRunner.startTransaction();
await queryRunner.manager.clear(NaturalEarthCountriesEntity); await queryRunner.manager.clear(NaturalEarthCountriesEntity);
@ -225,6 +230,7 @@ export class MapRepository implements IMapRepository {
const queryRunner = this.dataSource.createQueryRunner(); const queryRunner = this.dataSource.createQueryRunner();
await queryRunner.connect(); await queryRunner.connect();
const { resourcePaths } = this.configRepository.getEnv();
const admin1 = await this.loadAdmin(resourcePaths.geodata.admin1); const admin1 = await this.loadAdmin(resourcePaths.geodata.admin1);
const admin2 = await this.loadAdmin(resourcePaths.geodata.admin2); const admin2 = await this.loadAdmin(resourcePaths.geodata.admin2);
@ -280,6 +286,7 @@ export class MapRepository implements IMapRepository {
admin1Map: Map<string, string>, admin1Map: Map<string, string>,
admin2Map: Map<string, string>, admin2Map: Map<string, string>,
) { ) {
const { resourcePaths } = this.configRepository.getEnv();
await this.loadGeodataToTableFromFile( await this.loadGeodataToTableFromFile(
queryRunner, queryRunner,
(lineSplit: string[]) => (lineSplit: string[]) =>

View file

@ -4,7 +4,6 @@ import { exec as execCallback } from 'node:child_process';
import { readFile } from 'node:fs/promises'; import { readFile } from 'node:fs/promises';
import { promisify } from 'node:util'; import { promisify } from 'node:util';
import sharp from 'sharp'; import sharp from 'sharp';
import { resourcePaths } from 'src/constants';
import { IConfigRepository } from 'src/interfaces/config.interface'; import { IConfigRepository } from 'src/interfaces/config.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { GitHubRelease, IServerInfoRepository, ServerBuildVersions } from 'src/interfaces/server-info.interface'; import { GitHubRelease, IServerInfoRepository, ServerBuildVersions } from 'src/interfaces/server-info.interface';
@ -60,7 +59,7 @@ export class ServerInfoRepository implements IServerInfoRepository {
} }
async getBuildVersions(): Promise<ServerBuildVersions> { async getBuildVersions(): Promise<ServerBuildVersions> {
const { nodeVersion } = this.configRepository.getEnv(); const { nodeVersion, resourcePaths } = this.configRepository.getEnv();
const [nodejsOutput, ffmpegOutput, magickOutput] = await Promise.all([ const [nodejsOutput, ffmpegOutput, magickOutput] = await Promise.all([
maybeFirstLine('node --version'), maybeFirstLine('node --version'),

View file

@ -2,7 +2,8 @@ import { Inject, Injectable } from '@nestjs/common';
import { Cron, CronExpression, Interval } from '@nestjs/schedule'; import { Cron, CronExpression, Interval } from '@nestjs/schedule';
import { NextFunction, Request, Response } from 'express'; import { NextFunction, Request, Response } from 'express';
import { readFileSync } from 'node:fs'; import { readFileSync } from 'node:fs';
import { ONE_HOUR, resourcePaths } from 'src/constants'; import { ONE_HOUR } from 'src/constants';
import { IConfigRepository } from 'src/interfaces/config.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface';
import { AuthService } from 'src/services/auth.service'; import { AuthService } from 'src/services/auth.service';
import { JobService } from 'src/services/job.service'; import { JobService } from 'src/services/job.service';
@ -37,6 +38,7 @@ export class ApiService {
private jobService: JobService, private jobService: JobService,
private sharedLinkService: SharedLinkService, private sharedLinkService: SharedLinkService,
private versionService: VersionService, private versionService: VersionService,
@Inject(IConfigRepository) private configRepository: IConfigRepository,
@Inject(ILoggerRepository) private logger: ILoggerRepository, @Inject(ILoggerRepository) private logger: ILoggerRepository,
) { ) {
this.logger.setContext(ApiService.name); this.logger.setContext(ApiService.name);
@ -53,6 +55,8 @@ export class ApiService {
} }
ssr(excludePaths: string[]) { ssr(excludePaths: string[]) {
const { resourcePaths } = this.configRepository.getEnv();
let index = ''; let index = '';
try { try {
index = readFileSync(resourcePaths.web.indexHtml).toString(); index = readFileSync(resourcePaths.web.indexHtml).toString();

View file

@ -5,7 +5,7 @@ import cookieParser from 'cookie-parser';
import { existsSync } from 'node:fs'; import { existsSync } from 'node:fs';
import sirv from 'sirv'; import sirv from 'sirv';
import { ApiModule } from 'src/app.module'; import { ApiModule } from 'src/app.module';
import { excludePaths, resourcePaths, serverVersion } from 'src/constants'; import { excludePaths, serverVersion } from 'src/constants';
import { ImmichEnvironment } from 'src/enum'; import { ImmichEnvironment } from 'src/enum';
import { IConfigRepository } from 'src/interfaces/config.interface'; import { IConfigRepository } from 'src/interfaces/config.interface';
import { ILoggerRepository } from 'src/interfaces/logger.interface'; import { ILoggerRepository } from 'src/interfaces/logger.interface';
@ -36,7 +36,7 @@ async function bootstrap() {
const logger = await app.resolve<ILoggerRepository>(ILoggerRepository); const logger = await app.resolve<ILoggerRepository>(ILoggerRepository);
const configRepository = app.get<IConfigRepository>(IConfigRepository); const configRepository = app.get<IConfigRepository>(IConfigRepository);
const { environment, port } = configRepository.getEnv(); const { environment, port, resourcePaths } = configRepository.getEnv();
const isDev = environment === ImmichEnvironment.DEVELOPMENT; const isDev = environment === ImmichEnvironment.DEVELOPMENT;
logger.setContext('Bootstrap'); logger.setContext('Bootstrap');

View file

@ -25,6 +25,21 @@ const envData: EnvData = {
server: 'server-public-key', server: 'server-public-key',
}, },
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',
},
},
storage: { storage: {
ignoreMountCheckErrors: false, ignoreMountCheckErrors: false,
}, },