Skip to content
Merged
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
29 changes: 25 additions & 4 deletions api/src/controllers/migration.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,17 +14,37 @@ const createTestStack = async (req: Request, res: Response): Promise<void> => {
};

/**
* Deletes the test stack.
* Start Test Migartion.
*
* @param {Request} req - The request object.
* @param {Response} res - The response object.
* @returns {Promise<void>} - A Promise that resolves when the stack is deleted.
*/
const fieldMapping = async (req: Request, res: Response): Promise<void> => {
const resp = migrationService.fieldMapping(req);
const startTestMigration = async (req: Request, res: Response): Promise<void> => {
const resp = migrationService.startTestMigration(req);
res.status(200).json(resp);
};


/*
* Start Final Migartion.
*
* @param {Request} req - The request object.
* @param {Response} res - The response object.
* @returns {Promise<void>} - A Promise that resolves when the stack is deleted.
*/
const startMigration = async (req: Request, res: Response): Promise<void> => {
const resp = migrationService.startMigration(req);
res.status(200).json(resp);
};

/**
* Deletes the test stack.
*
* @param {Request} req - The request object.
* @param {Response} res - The response object.
* @returns {Promise<void>} - A Promise that resolves when the stack is deleted.
*/
const deleteTestStack = async (req: Request, res: Response): Promise<void> => {
const resp = await migrationService.deleteTestStack(req);
res.status(200).json(resp);
Expand All @@ -33,5 +53,6 @@ const deleteTestStack = async (req: Request, res: Response): Promise<void> => {
export const migrationController = {
createTestStack,
deleteTestStack,
fieldMapping,
startTestMigration,
startMigration
};
4 changes: 2 additions & 2 deletions api/src/routes/migration.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ const router = express.Router({ mergeParams: true });
*/
router.post(
"/test-stack/:orgId/:projectId",
asyncRouter(migrationController.fieldMapping)
asyncRouter(migrationController.startTestMigration)
);

/**
Expand Down Expand Up @@ -56,7 +56,7 @@ router.post(
*/
router.post(
"/start/:orgId/:projectId",
asyncRouter(migrationController.fieldMapping)
asyncRouter(migrationController.startMigration)
);


Expand Down
107 changes: 33 additions & 74 deletions api/src/services/migration.service.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,17 @@
import { Request } from "express";
import fs from 'fs';
// import cliUtilities from '@contentstack/cli-utilities';
import ProjectModelLowdb from "../models/project-lowdb.js";
import { config } from "../config/index.js";
import { safePromise, getLogMessage } from "../utils/index.js";
import https from "../utils/https.utils.js";
import { LoginServiceType } from "../models/types.js";
import { LoginServiceType } from "../models/types.js"
import getAuthtoken from "../utils/auth.utils.js";
import logger from "../utils/logger.js";
import { HTTP_TEXTS, HTTP_CODES, CS_REGIONS, LOCALE_MAPPER, STEPPER_STEPS } from "../constants/index.js";
import { HTTP_TEXTS, HTTP_CODES, LOCALE_MAPPER, STEPPER_STEPS } from "../constants/index.js";
import { ExceptionFunction } from "../utils/custom-errors.utils.js";
import { fieldAttacher } from "../utils/field-attacher.utils.js";
import ProjectModelLowdb from "../models/project-lowdb.js";
import shell from 'shelljs'
import path from "path";
import AuthenticationModel from "../models/authentication.js";
import { siteCoreService } from "./sitecore.service.js";
import { copyDirectory } from '../utils/index.js'
import { v4 } from "uuid";
import { setLogFilePath } from "../server.js";
import { mkdirp } from 'mkdirp';
import { testFolderCreator } from "../utils/test-folder-creator.utils.js";

import { utilsCli } from './runCli.service.js';



Expand Down Expand Up @@ -205,65 +196,12 @@ const deleteTestStack = async (req: Request): Promise<LoginServiceType> => {
};


function createDirectoryAndFile(filePath: string) {
// Get the directory from the file path
const dirPath = path.dirname(filePath);
// Create the directory if it doesn't exist
mkdirp.sync(dirPath);
// Check if the file exists; if not, create it
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, '', { mode: 0o666 }); // Create file with read/write for everyone
console.info(`File created at: ${filePath}`);
} else {
console.info(`File already exists at: ${filePath}`);
}
}


const runCli = async (rg: string, user_id: string, stack_uid: any, projectId: string) => {
try {
const regionPresent = CS_REGIONS?.find((item: string) => item === rg) ?? 'NA';
await AuthenticationModel.read();
const userData = AuthenticationModel.chain
.get("users")
.find({ region: regionPresent, user_id })
.value();
if (userData?.authtoken && stack_uid) {
const sourcePath = path.join(process.cwd(), 'sitecoreMigrationData', stack_uid);
const backupPath = path.join(process.cwd(), 'migration-data', `${stack_uid}_${v4().slice(0, 4)}`);
await copyDirectory(sourcePath, backupPath);
const loggerPath = path.join(backupPath, 'logs', 'import', 'success.log');
createDirectoryAndFile(loggerPath);
await setLogFilePath(loggerPath);
shell.cd(path.join(process.cwd(), '..', 'cli', 'packages', 'contentstack'));
shell.exec('pwd');
shell.exec(`node bin/run config:set:region ${regionPresent}`);
shell.exec(`node bin/run login -a ${userData?.authtoken} -e ${userData?.email}`);
const exportData = shell.exec(`node bin/run cm:stacks:import -k ${stack_uid} -d ${sourcePath} --backup-dir=${backupPath} --yes`, { async: true });
exportData.on('exit', (code) => {
console.info(`Process exited with code: ${code}`);
if (code === 1) {
const projectIndex = ProjectModelLowdb.chain.get("projects").findIndex({ id: projectId }).value();
if (projectIndex > -1) {
ProjectModelLowdb?.data.projects[projectIndex].test_stacks.map((item: any) => {
if (item?.stackUid === stack_uid) {
item.isMigrated = true;
}
return item;
})
ProjectModelLowdb.write();
}
}
});
} else {
console.info('user not found.')
}
} catch (er) {
console.error("🚀 ~ runCli ~ er:", er)
}
}

const fieldMapping = async (req: Request): Promise<any> => {
/**
* Start Test Migration.
*
* @param req - The request object containing the necessary parameters.
*/
const startTestMigration = async (req: Request): Promise<any> => {
const { orgId, projectId } = req?.params ?? {};
const { region, user_id } = req?.body?.token_payload ?? {};
const project = ProjectModelLowdb.chain.get("projects").find({ id: projectId }).value();
Expand All @@ -274,12 +212,33 @@ const fieldMapping = async (req: Request): Promise<any> => {
await siteCoreService?.createLocale(req, project?.current_test_stack_id);
await siteCoreService?.createVersionFile(project?.current_test_stack_id);
await testFolderCreator?.({ destinationStackId: project?.current_test_stack_id });
await runCli(region, user_id, project?.current_test_stack_id, projectId);
await utilsCli?.runCli(region, user_id, project?.current_test_stack_id, projectId, true);
}
}


/**
* Start final Migration.
*
* @param req - The request object containing the necessary parameters.
*/
const startMigration = async (req: Request): Promise<any> => {
const { orgId, projectId } = req?.params ?? {};
const { region, user_id } = req?.body?.token_payload ?? {};
const project = ProjectModelLowdb.chain.get("projects").find({ id: projectId }).value();
const packagePath = project?.extract_path;
if (packagePath && project?.destination_stack_id) {
const contentTypes = await fieldAttacher({ orgId, projectId, destinationStackId: project?.destination_stack_id });
await siteCoreService?.createEntry({ packagePath, contentTypes, destinationStackId: project?.destination_stack_id });
await siteCoreService?.createLocale(req, project?.destination_stack_id);
await siteCoreService?.createVersionFile(project?.destination_stack_id);
await utilsCli?.runCli(region, user_id, project?.destination_stack_id, projectId);
}
}

export const migrationService = {
createTestStack,
deleteTestStack,
fieldMapping
startTestMigration,
startMigration
};
74 changes: 74 additions & 0 deletions api/src/services/runCli.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import path from "path";
import fs from 'fs';
import shell from 'shelljs'
import { v4 } from "uuid";
import { setLogFilePath } from "../server.js";
import { copyDirectory, createDirectoryAndFile } from '../utils/index.js'
import { CS_REGIONS } from "../constants/index.js";
import ProjectModelLowdb from "../models/project-lowdb.js";
import AuthenticationModel from "../models/authentication.js";

const addCustomMessageInCliLogs = async (loggerPath: string, level: string = 'info', message: string) => {
try {
const logEntry = {
level,
message,
timestamp: new Date().toISOString(),
};
const logMessage = JSON.stringify(logEntry) + '\n'; // Convert to JSON and add a newline
await fs.promises.appendFile(loggerPath, logMessage);
} catch (error) {
console.error('Error reading the file:', error);
}
}


export const runCli = async (rg: string, user_id: string, stack_uid: any, projectId: string, isTest = false) => {
try {
const regionPresent = CS_REGIONS?.find((item: string) => item === rg) ?? 'NA';
await AuthenticationModel.read();
const userData = AuthenticationModel.chain
.get("users")
.find({ region: regionPresent, user_id })
.value();
if (userData?.authtoken && stack_uid) {
const sourcePath = path.join(process.cwd(), 'sitecoreMigrationData', stack_uid);
const backupPath = path.join(process.cwd(), 'migration-data', `${stack_uid}_${v4().slice(0, 4)}`);
await copyDirectory(sourcePath, backupPath);
const loggerPath = path.join(backupPath, 'logs', 'import', 'success.log');
createDirectoryAndFile(loggerPath);
await setLogFilePath(loggerPath);
shell.cd(path.join(process.cwd(), '..', 'cli', 'packages', 'contentstack'));
shell.exec('pwd');
shell.exec(`node bin/run config:set:region ${regionPresent}`);
shell.exec(`node bin/run login -a ${userData?.authtoken} -e ${userData?.email}`);
const importData = shell.exec(`node bin/run cm:stacks:import -k ${stack_uid} -d ${sourcePath} --backup-dir=${backupPath} --yes`, { async: true });
importData.on('exit', async (code) => {
console.info(`Process exited with code: ${code}`);
if (code === 1 || code === 0) {
const projectIndex = ProjectModelLowdb.chain.get("projects").findIndex({ id: projectId }).value();
if (projectIndex > -1 && isTest) {
ProjectModelLowdb?.data?.projects?.[projectIndex]?.test_stacks?.map((item: any) => {
if (item?.stackUid === stack_uid) {
item.isMigrated = true;
}
return item;
})
ProjectModelLowdb.write();
}
await addCustomMessageInCliLogs(loggerPath, 'info', 'Test Migration Process Completed');
}
});

} else {
console.info('user not found.')
}
} catch (er) {
console.error("🚀 ~ runCli ~ er:", er)
}
}


export const utilsCli = {
runCli
};
16 changes: 16 additions & 0 deletions api/src/utils/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import fs from 'fs-extra';
import path from "path";
import { mkdirp } from 'mkdirp';
/**
* Throws an error with a custom message and status code.
* @param message - The error message.
Expand Down Expand Up @@ -73,4 +75,18 @@ export async function copyDirectory(srcDir: string, destDir: string): Promise<vo
} catch (error) {
console.error(`Error copying directory: ${error}`);
}
}

export function createDirectoryAndFile(filePath: string) {
// Get the directory from the file path
const dirPath = path.dirname(filePath);
// Create the directory if it doesn't exist
mkdirp.sync(dirPath);
// Check if the file exists; if not, create it
if (!fs.existsSync(filePath)) {
fs.writeFileSync(filePath, '', { mode: 0o666 }); // Create file with read/write for everyone
console.info(`File created at: ${filePath}`);
} else {
console.info(`File already exists at: ${filePath}`);
}
}
4 changes: 2 additions & 2 deletions upload-api/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ export default {
plan: {
dropdown: { optionLimit: 100 }
},
cmsType: 'Sitecore',
cmsType: 'sitecore',
isLocalPath: true,
awsData: {
awsRegion: 'us-east-2',
Expand All @@ -12,5 +12,5 @@ export default {
bucketName: 'migartion-test',
buketKey: 'project/package 45.zip'
},
localPath: '/Users/rohit/Desktop/package 45.zip'
localPath: '/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/upload-api/extracted_files/package 45.zip'
};