refactor(settings): use migrator for dynamic settings migrations

This commit is contained in:
fallenbagel
2024-06-01 02:31:16 +05:00
parent 226d451adf
commit 130bb298f7
4 changed files with 83 additions and 33 deletions

View File

@@ -1,10 +1,12 @@
import { MediaServerType } from '@server/constants/server';
import { Permission } from '@server/lib/permissions';
import { SettingsMigrator } from '@server/lib/settings/settingsMigrator';
import logger from '@server/logger';
import { randomUUID } from 'crypto';
import fs from 'fs';
import { merge } from 'lodash';
import path from 'path';
import webpush from 'web-push';
import { Permission } from './permissions';
export interface Library {
id: string;
@@ -276,7 +278,7 @@ export type JobId =
| 'image-cache-cleanup'
| 'availability-sync';
interface AllSettings {
export interface AllSettings {
clientId: string;
vapidPublic: string;
vapidPrivate: string;
@@ -641,38 +643,20 @@ class Settings {
if (data) {
const parsedJson = JSON.parse(data);
const oldJellyfinSettings = parsedJson.jellyfin;
if (oldJellyfinSettings && oldJellyfinSettings.hostname) {
const { hostname } = oldJellyfinSettings;
const protocolMatch = hostname.match(/^(https?):\/\//i);
const useSsl =
protocolMatch && protocolMatch[1].toLowerCase() === 'https';
SettingsMigrator.migrateSettings(parsedJson)
.then((migrated) => {
this.data = Object.assign(this.data, migrated);
this.data = merge(this.data, migrated);
const remainingUrl = hostname.replace(/^(https?):\/\//i, '');
const urlMatch = remainingUrl.match(/^([^:]+)(:([0-9]+))?(\/.*)?$/);
delete oldJellyfinSettings.hostname;
if (urlMatch) {
const [, ip, , port, urlBase] = urlMatch;
this.data.jellyfin = {
...this.data.jellyfin,
ip,
port: port || (useSsl ? 443 : 80),
useSsl,
urlBase: urlBase ? urlBase.replace(/\/$/, '') : '',
};
}
}
if (parsedJson.jellyfin && parsedJson.jellyfin.hostname) {
delete parsedJson.jellyfin.hostname;
}
this.data = merge(this.data, parsedJson);
this.save();
this.save();
})
.catch((error) => {
logger.error('Error migrating settings', {
label: 'Settings',
error: error,
});
});
}
return this;
}

View File

@@ -0,0 +1,33 @@
import type { AllSettings } from '@server/lib/settings';
export default function removeHostnameMigration(settings: any): AllSettings {
const oldJellyfinSettings = settings.jellyfin;
if (oldJellyfinSettings && oldJellyfinSettings.hostname) {
const { hostname } = oldJellyfinSettings;
const protocolMatch = hostname.match(/^(https?):\/\//i);
const useSsl = protocolMatch && protocolMatch[1].toLowerCase() === 'https';
const remainingUrl = hostname.replace(/^(https?):\/\//i, '');
const urlMatch = remainingUrl.match(/^([^:]+)(:([0-9]+))?(\/.*)?$/);
delete oldJellyfinSettings.hostname;
if (urlMatch) {
const [, ip, , port, urlBase] = urlMatch;
settings.jellyfin = {
...settings.jellyfin,
ip,
port: port || (useSsl ? 443 : 80),
useSsl,
urlBase: urlBase ? urlBase.replace(/\/$/, '') : '',
};
}
}
if (settings.jellyfin && settings.jellyfin.hostname) {
delete settings.jellyfin.hostname;
}
return settings;
}

View File

@@ -0,0 +1,33 @@
import type { AllSettings } from '@server/lib/settings';
import fs from 'fs';
import path from 'path';
export class SettingsMigrator {
static async migrateSettings(settings: AllSettings): Promise<AllSettings> {
const migrations = await this.loadMigrations();
for (const migration of Object.values(migrations)) {
settings = await migration(settings);
}
return settings;
}
private static async loadMigrations(): Promise<
((settings: AllSettings) => AllSettings)[]
> {
const migrationDir = path.join(__dirname, 'migrations');
const migrationFiles = fs.readdirSync(migrationDir);
const migrationScripts: ((settings: AllSettings) => AllSettings)[] = [];
for (const file of migrationFiles) {
if (file.endsWith('.js') || file.endsWith('.ts')) {
const scriptPath = path.join(migrationDir, file);
const migrationScript = (await import(scriptPath)).default;
if (typeof migrationScript === 'function') {
migrationScripts.push(migrationScript);
}
}
}
return migrationScripts;
}
}

View File

@@ -986,7 +986,7 @@
"components.Settings.plexlibraries": "Plex Libraries",
"components.Settings.plexlibrariesDescription": "The libraries Jellyseerr scans for titles. Set up and save your Plex connection settings, then click the button below if no libraries are listed.",
"components.Settings.plexsettings": "Plex Settings",
"components.Settings.plexsettingsDescription": "Configure the settings for your Plex server. Overseerr scans your Plex libraries to determine content availability.",
"components.Settings.plexsettingsDescription": "Configure the settings for your Plex server. Jellyseerr scans your Plex libraries to determine content availability.",
"components.Settings.port": "Port",
"components.Settings.radarrsettings": "Radarr Settings",
"components.Settings.restartrequiredTooltip": "Jellyseerr must be restarted for changes to this setting to take effect",