Files
ontime/apps/server/src/services/project-service/projectServiceUtils.ts
T
Alex Christoffer Rasmussen 9ebb3decdb 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
2025-08-07 15:48:58 +02:00

106 lines
3.4 KiB
TypeScript

import { DatabaseModel, MaybeString, ProjectFile } from 'ontime-types';
import { existsSync } from 'fs';
import { readFile, stat } from 'fs/promises';
import { extname, join } from 'path';
import { publicDir } from '../../setup/index.js';
import { dockerSafeRename, getFilesFromFolder, removeFileExtension } from '../../utils/fileManagement.js';
/**
* Handles the upload of a new project file
* @param filePath
* @param name
*/
export async function handleUploaded(filePath: string, name: string) {
const newFilePath = join(publicDir.projectsDir, name);
await dockerSafeRename(filePath, newFilePath);
}
export async function handleImageUpload(filePath: string, name: string): Promise<string> {
const newFilePath = join(publicDir.logoDir, name);
await dockerSafeRename(filePath, newFilePath);
return name;
}
/**
* Asynchronously retrieves and returns an array of project files from the 'uploads' folder.
* Each file in the 'uploads' folder is checked, and only those with a '.json' extension are processed.
* For each qualifying file, its metadata is retrieved, including filename, creation time, and last modification time.
*
* @returns {Promise<Array<ProjectFile>>} A promise that resolves to an array of ProjectFile objects,
* each representing a file in the 'uploads' folder with its metadata.
* The metadata includes the filename, creation or overwriting time (updatedAt)
*
* @throws {Error} Throws an error if there is an issue in reading the directory or fetching file statistics.
*/
export async function getProjectFiles(): Promise<ProjectFile[]> {
const allFiles = await getFilesFromFolder(publicDir.projectsDir);
const filteredFiles = filterProjectFiles(allFiles);
const projectFiles: ProjectFile[] = [];
for (const file of filteredFiles) {
const filePath = join(publicDir.projectsDir, file);
const stats = await stat(filePath);
projectFiles.push({
filename: removeFileExtension(file),
updatedAt: stats.mtime.toISOString(),
});
}
return projectFiles;
}
/**
* Checks whether a project of a given name exists
* @param name
*/
export function doesProjectExist(name: string): MaybeString {
const projectFilePath = getPathToProject(name);
if (existsSync(projectFilePath)) {
return projectFilePath;
}
return null;
}
/**
* Returns the absolute path to a project file
*/
export function getPathToProject(name: string): string {
return join(publicDir.projectsDir, name);
}
/**
* Moves a file permanently to the corrupted directory
*/
export async function moveCorruptFile(filePath: string, name: string): Promise<void> {
const newPath = join(publicDir.corruptDir, name);
return dockerSafeRename(filePath, newPath);
}
/**
* Given an array of file names, filters out any files that do not have a '.json' extension.
* We assume these are project files
*/
export function filterProjectFiles(files: Array<string>): Array<string> {
return files.filter((file) => {
const ext = extname(file).toLowerCase();
return ext === '.json';
});
}
/**
* Parses a project file and returns the JSON object
* @throws It will throw an error if it cannot read or parse the file
*/
export async function parseJsonFile(filePath: string): Promise<Partial<DatabaseModel>> {
if (!filePath.endsWith('.json')) {
throw new Error('Invalid file type');
}
const rawdata = await readFile(filePath, 'utf-8');
return JSON.parse(rawdata);
}