V3 project migration (#1652)

* migrate settings

* migrate viewsettings

* migrate url preset

* migrate project data

* migrate custom fields

* migrate automations

* migrate rundown

* lint

* return custom field translation table

* check regex

* new url type

* refactor

* migrate old OSC subscriptions

* migrate old http subscriptions

* update comments

* migrate the whole db

* remove automation logging unlis there is an error

* return a new object

* refactor: copy currup is only used in one place

* make a copy of original migrated file

* refactor: ensure image flder is part of project service init

* add entrys to groups

* small cleanup

* just drop incorrect custom fields in the default data parser
This commit is contained in:
Alex Christoffer Rasmussen
2025-08-07 15:48:58 +02:00
committed by GitHub
parent 35347e8d63
commit 9ebb3decdb
12 changed files with 993 additions and 87 deletions
@@ -33,13 +33,13 @@ import {
import { runtimeService } from '../runtime-service/RuntimeService.js';
import {
copyCorruptFile,
doesProjectExist,
getPathToProject,
getProjectFiles,
moveCorruptFile,
parseJsonFile,
} from './projectServiceUtils.js';
import { join } from 'path';
type ProjectState =
| {
@@ -65,6 +65,8 @@ init();
function init() {
ensureDirectory(publicDir.projectsDir);
ensureDirectory(publicDir.corruptDir);
ensureDirectory(publicDir.logoDir);
ensureDirectory(publicDir.migrateDir);
}
export async function getCurrentProject(): Promise<{ filename: string; pathToFile: string }> {
@@ -130,7 +132,8 @@ async function loadNewProject(): Promise<string> {
*/
async function handleCorruptedFile(filePath: string, fileName: string): Promise<string> {
// copy file to corrupted folder
await copyCorruptFile(filePath, fileName).catch((_) => {
const copyPath = join(publicDir.corruptDir, fileName);
await copyFile(filePath, copyPath).catch((_) => {
/* while we have to catch the error, we dont need to handle it */
});
@@ -140,6 +143,19 @@ async function handleCorruptedFile(filePath: string, fileName: string): Promise<
return getFileNameFromPath(newPath);
}
async function handleMigratedFile(filePath: string, fileName: string): Promise<string> {
// copy file to migrated folder
const copyPath = join(publicDir.migrateDir, fileName);
await copyFile(filePath, copyPath).catch((_) => {
/* while we have to catch the error, we dont need to handle it */
});
// and make a new file with the recovered data
const newPath = appendToName(filePath, '(migrated)');
await dockerSafeRename(filePath, newPath);
return getFileNameFromPath(newPath);
}
/**
* Coordinates the initial load of a project on app startup
* This is different from the load project since we need to always load something
@@ -190,6 +206,10 @@ export async function loadProjectFile(fileName: string): Promise<string> {
logger.warning(LogOrigin.Server, 'Project loaded with errors');
parsedFileName = await handleCorruptedFile(filePath, fileName);
}
if (result.migrated) {
logger.warning(LogOrigin.Server, 'The imported project is migrate, the original file has been backed up');
parsedFileName = await handleMigratedFile(filePath, fileName);
}
const projectName = await loadProject(result.data, parsedFileName);
return projectName;