Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/backend/events/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@ import { Socket } from 'socket.io';
import serialize from 'serialize-javascript';
import fs from 'fs';
import {
replaceUndefined,
deletePresetFolder,
getPresetsPath,
getProjectServers,
updateProjectSupportedDataVersion,
updateServerData,
getPresetsPath,
updateProjectSupportedDataVersion,
} from '../utils';
import { hasUncommittedChanges } from '../utils/git';
import { EVENT_KEYS } from '../../types/events';
import { listToHashmap } from '../utils/utils';
import { listToHashmap, replaceUndefined } from '../utils/utils';
import { Preset } from '../../types';
import { updateClientProjectData } from '../utils/events';

Expand Down
24 changes: 24 additions & 0 deletions src/backend/middleware/presetValidation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Request, Response, NextFunction } from 'express';
import {
validateCreatePresetRequest,
CreatePresetRequest,
} from '../utils/presetHelpers';

export const validateCreatePresetFromLogs = (
req: Request,
res: Response,
next: NextFunction,
): void => {
const errors = validateCreatePresetRequest(req.body as CreatePresetRequest);

if (errors.length > 0) {
res.status(400).json({
success: false,
message: 'Validation failed',
errors,
});
return;
}

next();
};
33 changes: 33 additions & 0 deletions src/backend/routers/presets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@ import {
import { listToHashmap } from '../utils/utils';
import { emitGlobalSocketMessage } from '../socket';
import { EVENT_KEYS } from '../../types/events';
import { validateCreatePresetFromLogs } from '../middleware/presetValidation';
import { createPresetFromLogs } from '../services/presetCreationService';
import { CreatePresetRequest } from '../utils/presetHelpers';

const presetsRouter = Router();

Expand Down Expand Up @@ -64,4 +67,34 @@ presetsRouter.get(
},
);

presetsRouter.post(
'/create-from-logs',
validateCreatePresetFromLogs,
async (req: Request, res: Response) => {
try {
const result = await createPresetFromLogs(
req.body as CreatePresetRequest,
);

if (!result.success) {
const statusCode = result.message?.includes('not found') ? 404 : 400;
return res.status(statusCode).json(result);
}

// Trigger client reload on success
emitGlobalSocketMessage(EVENT_KEYS.RELOAD, {
projectName: result.projectName,
});

return res.status(201).json(result);
} catch (error: any) {
console.error('Unexpected error in create-from-logs endpoint:', error);
return res.status(500).json({
success: false,
message: 'Internal server error',
});
}
},
);

export { presetsRouter };
139 changes: 139 additions & 0 deletions src/backend/services/presetCreationService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
import {
getProjectServers,
updateServerData,
updateProjectSupportedDataVersion,
} from '../utils';
import { listToHashmap } from '../utils/utils';
import { hasUncommittedChanges } from '../utils/git';
import { logger } from '../utils/logger';
import {
CreatePresetRequest,
ProcessedLogData,
resolvePresetFolder,
createPreset,
processLogEntry,
savePresetFolder,
addPresetToFolder,
} from '../utils/presetHelpers';

export interface CreatePresetResult {
success: boolean;
presetFolder?: any;
projectName?: string;
hasDiffs?: boolean;
message?: string;
}

export const initializeProjectData = async (projectName: string) => {
logger(`Initializing project data for: ${projectName}`);
await updateProjectSupportedDataVersion(projectName);

const servers = await getProjectServers(projectName);
const serversHash = listToHashmap(servers, (server) => server.name);

return { servers, serversHash };
};

export const processAllLogs = (
processedLogs: ProcessedLogData[],
serversHash: Record<string, any>,
preset: any,
) => {
logger(`Processing ${processedLogs.length} logs`);
const updatedServers: Record<string, any> = {};

processedLogs.forEach((logData) => {
processLogEntry(logData, serversHash, updatedServers, preset);
});

logger(`Updated ${Object.keys(updatedServers).length} servers`);
return updatedServers;
};

export const updateAllServers = async (
updatedServers: Record<string, any>,
projectName: string,
) => {
logger(`Updating servers in project: ${projectName}`);
await Promise.all(
Object.values(updatedServers).map((server) =>
updateServerData(projectName, server),
),
);
};

export const finalizePresetCreation = async (
presetFolder: any,
preset: any,
projectName: string,
) => {
// Add preset to folder
addPresetToFolder(presetFolder, preset);

// Save to file
await savePresetFolder(presetFolder, projectName);

// Check git status
const hasDiffs = await hasUncommittedChanges(projectName);

return { presetFolder, hasDiffs };
};

export const createPresetFromLogs = async (
request: CreatePresetRequest,
): Promise<CreatePresetResult> => {
const startTime = Date.now();
const { presetName, processedLogs, projectName } = request;

try {
logger(
`Starting preset creation: "${presetName}" for project: ${projectName}`,
);

// Initialize project data
const { serversHash } = await initializeProjectData(projectName);

// Resolve preset folder
const presetFolder = await resolvePresetFolder(request);
if (!presetFolder) {
return {
success: false,
message: 'Preset folder not found',
};
}

// Create preset
const preset = createPreset(presetName, processedLogs.length);

// Process all logs
const updatedServers = processAllLogs(processedLogs, serversHash, preset);

// Update servers
await updateAllServers(updatedServers, projectName);

// Finalize creation
const result = await finalizePresetCreation(
presetFolder,
preset,
projectName,
);

const duration = Date.now() - startTime;
logger(`Successfully created preset "${presetName}" in ${duration}ms`);

return {
success: true,
presetFolder: result.presetFolder,
projectName,
hasDiffs: result.hasDiffs,
};
} catch (error: any) {
const duration = Date.now() - startTime;
logger(`Error creating preset (${duration}ms):`, error);

return {
success: false,
message: error?.message || 'Failed to create preset from logs',
};
}
};
13 changes: 13 additions & 0 deletions src/backend/swagger_output.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@
}
}
},
"/presets/create-from-logs": {
"post": {
"description": "",
"responses": {
"201": {
"description": "Created"
},
"500": {
"description": "Internal Server Error"
}
}
}
},
"/routes/{projectName}/{serverName}/{parentId}/{routeId}": {
"get": {
"description": "",
Expand Down
Loading
Loading