From f4f8cb578afe4db4caab2a165c023910e98f204f Mon Sep 17 00:00:00 2001 From: RohitKini Date: Thu, 12 Sep 2024 17:15:46 +0530 Subject: [PATCH 1/3] removed csdx utilities code --- api/src/services/auth.service.ts | 5 ----- 1 file changed, 5 deletions(-) diff --git a/api/src/services/auth.service.ts b/api/src/services/auth.service.ts index fe5eff2f2..023998071 100644 --- a/api/src/services/auth.service.ts +++ b/api/src/services/auth.service.ts @@ -23,7 +23,6 @@ import logger from "../utils/logger.js"; */ const login = async (req: Request): Promise => { const srcFun = "Login"; - const cliUtilities: any = await import('@contentstack/cli-utilities'); /* handles user authentication by making a request to an API, performing various checks and validations, @@ -110,10 +109,6 @@ const login = async (req: Request): Promise => { data.users[userIndex].authtoken = res?.data.user?.authtoken; data.users[userIndex].updated_at = new Date().toISOString(); } - - cliUtilities?.configHandler?.set('region', userData?.region); - cliUtilities?.configHandler?.set('authtoken', res?.data.user?.authtoken); - }); // JWT token generation From f14ecdd26a360245f867ccc1e5d4e71ecb80fe30 Mon Sep 17 00:00:00 2001 From: umeshmore45 Date: Mon, 16 Sep 2024 19:25:39 +0530 Subject: [PATCH 2/3] added updated code --- .gitignore | 1 - api/.gitignore | 3 +- api/package.json | 2 + api/src/config/index.ts | 1 + api/src/controllers/migration.controller.ts | 2 +- api/src/services/migration.service.ts | 105 ++++++++++++------- api/src/services/sitecore.service.ts | 24 +++-- api/src/utils/content-type-creator.utils.ts | 14 +-- api/src/utils/field-attacher.utils.ts | 4 +- api/src/utils/index.ts | 24 +++++ locale-cli | 1 - ui/src/components/TestMigration/index.tsx | 2 +- upload-api/.env | 2 +- upload-api/src/config/index.ts | 2 +- upload-api/src/controllers/sitecore/index.ts | 2 +- 15 files changed, 123 insertions(+), 66 deletions(-) delete mode 160000 locale-cli diff --git a/.gitignore b/.gitignore index bc0132150..d69aec3b1 100644 --- a/.gitignore +++ b/.gitignore @@ -355,4 +355,3 @@ package-lock.json ui/.env upload-api/sitecoreMigrationData upload-api/extracted_files -locale-cli diff --git a/api/.gitignore b/api/.gitignore index 8fd3924df..e3a5464ee 100644 --- a/api/.gitignore +++ b/api/.gitignore @@ -361,4 +361,5 @@ package-lock.json !example.env database/ -/sitecoreMigrationData \ No newline at end of file +/sitecoreMigrationData +/migration-data \ No newline at end of file diff --git a/api/package.json b/api/package.json index 355708275..c2a2e752e 100644 --- a/api/package.json +++ b/api/package.json @@ -35,6 +35,7 @@ "express": "^4.18.2", "express-validator": "^7.0.1", "express-winston": "^4.2.0", + "fs-extra": "^11.2.0", "fs-readdir-recursive": "^1.1.0", "helmet": "^7.1.0", "html-to-json-parser": "^2.0.1", @@ -50,6 +51,7 @@ "devDependencies": { "@types/cors": "^2.8.17", "@types/express": "^4.17.21", + "@types/fs-extra": "^11.0.4", "@types/fs-readdir-recursive": "^1.1.3", "@types/jsdom": "^21.1.7", "@types/jsonwebtoken": "^9.0.5", diff --git a/api/src/config/index.ts b/api/src/config/index.ts index 12b3e5386..c388ff7ae 100644 --- a/api/src/config/index.ts +++ b/api/src/config/index.ts @@ -10,6 +10,7 @@ dotenv.config({ path: path.resolve(process.cwd(), `${process.env.NODE_ENV}.env`), }); + /** * Configuration type for the application. */ diff --git a/api/src/controllers/migration.controller.ts b/api/src/controllers/migration.controller.ts index ac2113ad9..3f8ac5c84 100644 --- a/api/src/controllers/migration.controller.ts +++ b/api/src/controllers/migration.controller.ts @@ -21,7 +21,7 @@ const createTestStack = async (req: Request, res: Response): Promise => { * @returns {Promise} - A Promise that resolves when the stack is deleted. */ const fieldMapping = async (req: Request, res: Response): Promise => { - const resp = await migrationService.fieldMapping(req); + const resp = migrationService.fieldMapping(req); res.status(200).json(resp); }; diff --git a/api/src/services/migration.service.ts b/api/src/services/migration.service.ts index 2f2639eb0..2a51f3ea9 100644 --- a/api/src/services/migration.service.ts +++ b/api/src/services/migration.service.ts @@ -1,5 +1,5 @@ import { Request } from "express"; -import cliUtilities from '@contentstack/cli-utilities'; +// import cliUtilities from '@contentstack/cli-utilities'; import { config } from "../config/index.js"; import { safePromise, getLogMessage } from "../utils/index.js"; import https from "../utils/https.utils.js"; @@ -10,12 +10,16 @@ import { HTTP_TEXTS, HTTP_CODES, CS_REGIONS } 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 shell from 'shelljs' +import path from "path"; import AuthenticationModel from "../models/authentication.js"; import { siteCoreService } from "./sitecore.service.js"; +import { fileURLToPath } from 'url'; +import { copyDirectory } from '../utils/index.js' + + + -// const importCmd: any = await import('@contentstack/cli-cm-import'); /** * Creates a test stack. @@ -198,61 +202,57 @@ const cliLogger = (child: any) => { console.info(`Error: Failed to install @contentstack/cli. Exit code: ${child.code}`); console.info(`stderr: ${child.stderr}`); } else { - console.info('Installation successful', child?.stdout); + console.info('Installation successful', child, child?.stdout); } }; -const runCli = async (rg: string, user_id: string) => { +const runCli = async (rg: string, user_id: string, project: any) => { try { const regionPresent = CS_REGIONS?.find((item: string) => item === rg) ?? 'NA'; - // const email = 'umesh.more+10@contentstack.com' await AuthenticationModel.read(); const userData = AuthenticationModel.chain .get("users") .find({ region: regionPresent, user_id }) .value(); - if (userData?.authtoken) { - - cliUtilities?.configHandler?.set('region', regionPresent); - cliUtilities?.configHandler?.set('authtoken', userData?.authtoken); - // shell.cd(path.resolve(process.cwd(), `../cli/packages/contentstack`)); - // const pwd = shell.exec('pwd'); - // cliLogger(pwd); - // const region = shell.exec(`node bin/run config:set:region ${regionPresent}`); - // cliLogger(region); - // const login = shell.exec(`node bin/run login -a ${userData?.authtoken} -e ${email}`) - // cliLogger(login); - // const exportData = shell.exec(`node bin/run cm:stacks:import -k blt3e7d2a4135d8bfab -d "/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/data" --backup-dir="/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/migrations/blt3e7d2a4135d8bfab"`); - // cliLogger(exportData); - // const cmd = [`-k ${userData?.authtoken}`, "-d /Users/umesh.more/Documents/ui-migration/migration-v2-node-server/api/sitecoreMigrationData", "--backup-dir=/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/migrations/blt3e7d2a4135d8bfab", "--yes"] - - // await importCmd.default.run(cmd); // This will bypass the type issue - // shell.cd(path.resolve(process.cwd(), '..', 'locale-cli', 'packages', 'contentstack')); - // const pwd = shell.exec('pwd'); - // cliLogger(pwd); - // const region = shell.exec(`node bin/run config:set:region ${regionPresent}`); - // cliLogger(region); - // const login = shell.exec(`node bin/run login -a ${userData?.authtoken} -e ${email}`) - // cliLogger(login); - // const exportData = shell.exec(`node bin/run cm:stacks:import -k blt69235b992c3d99c6 -d "/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/api/sitecoreMigrationData" --backup-dir="/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/test"`); - // cliLogger(exportData); + if (userData?.authtoken && project?.destination_stack_id) { + // Manually define __filename and __dirname + const __filename = fileURLToPath(import.meta.url); + const dirPath = path.join(path.dirname(__filename), '..', '..'); + const sourcePath = path.join(dirPath, 'sitecoreMigrationData', project?.destination_stack_id); + const backupPath = path.join(process.cwd(), 'migration-data', project?.destination_stack_id); + await copyDirectory(sourcePath, backupPath); + shell.cd(path.join(process.cwd(), '..', 'cli', 'packages', 'contentstack')); + const pwd = shell.exec('pwd'); + cliLogger(pwd); + const region = shell.exec(`node bin/run config:set:region ${regionPresent}`); + cliLogger(region); + const login = shell.exec(`node bin/run login -a ${userData?.authtoken} -e ${userData?.email}`); + cliLogger(login); + const exportData = shell.exec(`node bin/run cm:stacks:import -k ${project?.destination_stack_id} -d ${sourcePath} --backup-dir=${backupPath} --yes`); + cliLogger(exportData); } else { console.info('user not found.') } } catch (er) { - console.info("🚀 ~ runCli ~ er:", er) + console.error("🚀 ~ runCli ~ er:", er) } } const fieldMapping = async (req: Request): Promise => { const { orgId, projectId } = req?.params ?? {}; - const contentTypes = await fieldAttacher({ orgId, projectId }); - const packagePath = '/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/upload-api/extracted_files/package 45'; - await siteCoreService?.createEntry({ packagePath, contentTypes }); - await siteCoreService?.createLocale(req); - await siteCoreService?.createVersionFile(); const { region, user_id } = req?.body?.token_payload ?? {}; - await runCli(region, user_id); + const project = ProjectModelLowdb.chain + .get("projects") + .find({ id: projectId }) + .value(); + if (project?.extract_path && project?.destination_stack_id) { + const packagePath = project?.extract_path; + 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 runCli(region, user_id, project); + } } export const migrationService = { @@ -260,3 +260,30 @@ export const migrationService = { deleteTestStack, fieldMapping }; + + + + + +// cliUtilities?.configHandler?.set('region', regionPresent); +// cliUtilities?.configHandler?.set('authtoken', userData?.authtoken); +// shell.cd(path.resolve(process.cwd(), `../cli/packages/contentstack`)); +// const pwd = shell.exec('pwd'); +// cliLogger(pwd); +// const region = shell.exec(`node bin/run config:set:region ${regionPresent}`); +// cliLogger(region); +// const login = shell.exec(`node bin/run login -a ${userData?.authtoken} -e ${email}`) +// cliLogger(login); +// const exportData = shell.exec(`node bin/run cm:stacks:import -k blt3e7d2a4135d8bfab -d "/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/data" --backup-dir="/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/migrations/blt3e7d2a4135d8bfab"`); +// cliLogger(exportData); +// const cmd = [`-k ${userData?.authtoken}`, "-d /Users/umesh.more/Documents/ui-migration/migration-v2-node-server/api/sitecoreMigrationData", "--backup-dir=/Users/umesh.more/Documents/ui-migration/migration-v2-node-server/migrations/blt3e7d2a4135d8bfab", "--yes"] +// await importCmd.default.run(cmd); // This will bypass the type issue +// shell.cd(path.resolve(`${path?.dirname}`, '..', 'cli', 'packages', 'contentstack')); +// const importCmd: any = await import('@contentstack/cli-cm-import'); + + + + + + + diff --git a/api/src/services/sitecore.service.ts b/api/src/services/sitecore.service.ts index 966f7ba71..b77c31f5b 100644 --- a/api/src/services/sitecore.service.ts +++ b/api/src/services/sitecore.service.ts @@ -6,9 +6,7 @@ import _ from 'lodash'; import { LOCALE_MAPPER } from '../constants/index.js'; import { entriesFieldCreator, unflatten } from '../utils/entries-field-creator.utils.js'; import { orgService } from './org.service.js'; -const assetsSave = path.join('sitecoreMigrationData', 'assets'); -const entrySave = path.join('sitecoreMigrationData', 'entries'); -const localeSave = path.join('sitecoreMigrationData', 'locale'); + const append = "a"; const idCorrector = ({ id }: any) => { @@ -26,7 +24,7 @@ function startsWithNumber(str: string) { function getLastKey(path: string) { const keys = path?.split?.('.'); - const lastKey = keys[keys.length - 1]; + const lastKey = keys?.[keys?.length - 1]; return lastKey; } @@ -79,7 +77,8 @@ const uidCorrector = ({ uid }: any) => { return _.replace(uid, new RegExp("[ -]", "g"), '_')?.toLowerCase() } -const cretaeAssets = async ({ packagePath }: any) => { +const cretaeAssets = async ({ packagePath, baseDir }: any) => { + const assetsSave = path.join(baseDir, 'assets'); const allAssetJSON: any = {}; const folderName: any = path.join(packagePath, 'items', 'master', 'sitecore', 'media library'); const entryPath = read?.(folderName); @@ -163,9 +162,11 @@ const cretaeAssets = async ({ packagePath }: any) => { return allAssetJSON; } -const createEntry = async ({ packagePath, contentTypes, master_locale = 'en-us' }: { packagePath: any; contentTypes: any; master_locale?: string }) => { +const createEntry = async ({ packagePath, contentTypes, master_locale = 'en-us', destinationStackId }: { packagePath: any; contentTypes: any; master_locale?: string, destinationStackId: string }) => { try { - const allAssetJSON: any = await cretaeAssets({ packagePath }); + const baseDir = path.join('sitecoreMigrationData', destinationStackId); + const entrySave = path.join(baseDir, 'entries'); + const allAssetJSON: any = await cretaeAssets({ packagePath, baseDir }); const folderName: any = path.join(packagePath, 'items', 'master', 'sitecore', 'content'); const entriesData: any = []; if (fs.existsSync(folderName)) { @@ -240,7 +241,9 @@ const createEntry = async ({ packagePath, contentTypes, master_locale = 'en-us' } } -const createLocale = async (req: any) => { +const createLocale = async (req: any, destinationStackId: string) => { + const baseDir = path.join('sitecoreMigrationData', destinationStackId); + const localeSave = path.join(baseDir, 'locale'); const allLocalesResp = await orgService.getLocales(req) const masterLocale = Object?.keys?.(LOCALE_MAPPER?.masterLocale)?.[0]; const msLocale: any = {}; @@ -280,8 +283,9 @@ const createLocale = async (req: any) => { }) } -const createVersionFile = async () => { - fs.writeFile(path?.join?.('sitecoreMigrationData', 'export-info.json'), JSON.stringify({ +const createVersionFile = async (destinationStackId: string) => { + const baseDir = path.join('sitecoreMigrationData', destinationStackId); + fs.writeFile(path?.join?.(baseDir, 'export-info.json'), JSON.stringify({ "contentVersion": 2, "logsPath": "" }), (err) => { diff --git a/api/src/utils/content-type-creator.utils.ts b/api/src/utils/content-type-creator.utils.ts index 23227fb60..c08f40ee0 100644 --- a/api/src/utils/content-type-creator.utils.ts +++ b/api/src/utils/content-type-creator.utils.ts @@ -1,7 +1,5 @@ import fs from 'fs'; import path from 'path'; -const contentSave = path.join('sitecoreMigrationData', 'content_types'); -const globalSave = path.join('sitecoreMigrationData', 'global_fields'); interface Group { data_type: string; display_name?: string; // Assuming item?.contentstackField might be undefined @@ -332,7 +330,7 @@ const convertToSchemaFormate = ({ field, advanced = true }: any) => { } } -const saveContent = async (ct: any) => { +const saveContent = async (ct: any, contentSave: string) => { try { // Check if the directory exists await fs.promises.access(contentSave).catch(async () => { @@ -366,7 +364,7 @@ const saveContent = async (ct: any) => { } -const writeGlobalField = async (schema: any) => { +const writeGlobalField = async (schema: any, globalSave: string) => { const filePath = path.join(process.cwd(), globalSave, 'globalfields.json'); try { await fs.promises.access(globalSave); @@ -396,7 +394,7 @@ const writeGlobalField = async (schema: any) => { } }; -export const contenTypeMaker = async ({ contentType }: any) => { +export const contenTypeMaker = async ({ contentType, destinationStackId }: any) => { const ct: ContentType = { title: contentType?.contentstackTitle, uid: contentType?.contentstackUid, @@ -441,9 +439,11 @@ export const contenTypeMaker = async ({ contentType }: any) => { }) if (ct?.uid) { if (contentType?.type === 'global_field') { - await writeGlobalField(ct); + const globalSave = path.join('sitecoreMigrationData', destinationStackId, 'global_fields'); + await writeGlobalField(ct, globalSave); } else { - await saveContent(ct); + const contentSave = path.join('sitecoreMigrationData', destinationStackId, 'content_types'); + await saveContent(ct, contentSave); } } else { console.info(contentType?.contentstackUid, 'missing') diff --git a/api/src/utils/field-attacher.utils.ts b/api/src/utils/field-attacher.utils.ts index dafcb36f1..40459d52d 100644 --- a/api/src/utils/field-attacher.utils.ts +++ b/api/src/utils/field-attacher.utils.ts @@ -3,7 +3,7 @@ import ContentTypesMapperModelLowdb from "../models/contentTypesMapper-lowdb.js" import FieldMapperModel from "../models/FieldMapper.js"; import { contenTypeMaker } from "./content-type-creator.utils.js"; -export const fieldAttacher = async ({ projectId, orgId }: any) => { +export const fieldAttacher = async ({ projectId, orgId, destinationStackId }: any) => { await ProjectModelLowdb.read(); const projectData = ProjectModelLowdb.chain.get("projects").find({ id: projectId, @@ -27,7 +27,7 @@ export const fieldAttacher = async ({ projectId, orgId }: any) => { return field; }) } - await contenTypeMaker({ contentType }) + await contenTypeMaker({ contentType, destinationStackId }) contentTypes?.push?.(contentType); } } diff --git a/api/src/utils/index.ts b/api/src/utils/index.ts index 15e6ea61d..9404b302f 100644 --- a/api/src/utils/index.ts +++ b/api/src/utils/index.ts @@ -1,9 +1,11 @@ +import fs from 'fs-extra'; /** * Throws an error with a custom message and status code. * @param message - The error message. * @param statusCode - The HTTP status code associated with the error. * @throws {Error} - The error object with the specified message and status code. */ + export const throwError = (message: string, statusCode: number) => { throw Object.assign(new Error(message), { statusCode }); }; @@ -37,6 +39,7 @@ export const safePromise = (promise: Promise): Promise => * @param error - The error object. Optional. * @returns The log message object. */ + export const getLogMessage = ( methodName: string, message: string, @@ -50,3 +53,24 @@ export const getLogMessage = ( ...(error && { error }), }; }; + +/* + * Recursively copies a directory from source to destination + * @param srcDir - Source directory path + * @param destDir - Destination directory path +*/ + +export async function copyDirectory(srcDir: string, destDir: string): Promise { + try { + // Ensure the destination directory exists, if not, create it + await fs.ensureDir(destDir); + + // Copy the source directory to the destination + await fs.copy(srcDir, destDir); + + console.info(`Directory copied from ${srcDir} to ${destDir}`); + + } catch (error) { + console.error(`Error copying directory: ${error}`); + } +} \ No newline at end of file diff --git a/locale-cli b/locale-cli deleted file mode 160000 index c12e6b08d..000000000 --- a/locale-cli +++ /dev/null @@ -1 +0,0 @@ -Subproject commit c12e6b08dac6174a719d104b56f9f95ca273614f diff --git a/ui/src/components/TestMigration/index.tsx b/ui/src/components/TestMigration/index.tsx index a4bdf8b76..ed0189939 100644 --- a/ui/src/components/TestMigration/index.tsx +++ b/ui/src/components/TestMigration/index.tsx @@ -79,7 +79,7 @@ const TestMigration = () => {
Execution Logs
- +
diff --git a/upload-api/.env b/upload-api/.env index 2c50b6496..5f3a84b6c 100644 --- a/upload-api/.env +++ b/upload-api/.env @@ -1,2 +1,2 @@ PORT=4002 -NODE_BACKEND_API =http://localhost:5001 \ No newline at end of file +NODE_BACKEND_API =http://localhost:5000 \ No newline at end of file diff --git a/upload-api/src/config/index.ts b/upload-api/src/config/index.ts index 2ffc1d757..39e83b803 100644 --- a/upload-api/src/config/index.ts +++ b/upload-api/src/config/index.ts @@ -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' }; diff --git a/upload-api/src/controllers/sitecore/index.ts b/upload-api/src/controllers/sitecore/index.ts index ca56fce7c..69358c102 100644 --- a/upload-api/src/controllers/sitecore/index.ts +++ b/upload-api/src/controllers/sitecore/index.ts @@ -16,7 +16,7 @@ const createSitecoreMapper = async (filePath: string = "", projectId: string | s await contentTypes(newPath, affix, config); const infoMap = await reference(); if (infoMap?.contentTypeUids?.length) { - const fieldMapping: any = { contentTypes: [] }; + const fieldMapping: any = { contentTypes: [], extractPath: filePath }; for await (const contentType of infoMap?.contentTypeUids ?? []) { const fileContent = readFileSync(path?.join?.(infoMap?.path, 'content_types', contentType), 'utf8'); const jsonfileContent = JSON.parse(fileContent); From 61d94859ac08b541759dba294f46c95ac2db03ff Mon Sep 17 00:00:00 2001 From: RohitKini Date: Wed, 18 Sep 2024 11:59:03 +0530 Subject: [PATCH 3/3] logger functionality --- api/src/config/index.ts | 1 + api/src/server.ts | 99 +++++++++++++++++---------- api/src/services/migration.service.ts | 8 ++- 3 files changed, 68 insertions(+), 40 deletions(-) diff --git a/api/src/config/index.ts b/api/src/config/index.ts index c388ff7ae..c74d8cb45 100644 --- a/api/src/config/index.ts +++ b/api/src/config/index.ts @@ -35,6 +35,7 @@ export type ConfigType = { AZURE_EU?: string; GCP_NA?: string; }; + LOG_FILE_PATH: string; }; /** diff --git a/api/src/server.ts b/api/src/server.ts index fbaf4cb60..3f92cc681 100644 --- a/api/src/server.ts +++ b/api/src/server.ts @@ -21,21 +21,53 @@ import { Server } from "socket.io"; import http from "http"; import fs from "fs"; +// Initialize file watcher for the log file +const watcher = chokidar.watch(config.LOG_FILE_PATH,{ + usePolling: true, // Enables polling to detect changes in all environments + interval: 100, // Poll every 100ms (you can adjust this if needed) + awaitWriteFinish: { // Wait for file to finish being written before triggering + stabilityThreshold: 500, // Time to wait before considering the file stable + pollInterval: 100, // Interval at which to poll for file stability + }, + persistent: true, // Keeps watching the file even after initial change +}); // Initialize with initial log path + +let io: Server; // Socket.IO server instance + +// Dynamically change the log file path and update the watcher +export async function setLogFilePath(path:string) { + console.info(`Setting new log file path: ${path}`); + + // Stop watching the old log file + watcher.unwatch(config.LOG_FILE_PATH); + + // Update the config and start watching the new log file + config.LOG_FILE_PATH = path; + watcher.add(path); +} + try { const app = express(); + + // Set security-related HTTP headers app.use( helmet({ - crossOriginOpenerPolicy: false, + crossOriginOpenerPolicy: false, // Disable to allow cross-origin resource sharing }) ); + // Enable CORS for all origins app.use(cors({ origin: "*" })); + + // Parsing request bodies app.use(express.urlencoded({ extended: false, limit: "10mb" })); app.use(express.json({ limit: "10mb" })); + + // Custom middleware for logging and request headers app.use(loggerMiddleware); app.use(requestHeadersMiddleware); - // Routes + // Define routes app.use("/v2/auth", authRoutes); app.use("/v2/user", authenticateUser, userRoutes); app.use("/v2/org/:orgId", authenticateUser, orgRoutes); @@ -43,64 +75,55 @@ try { app.use("/v2/mapper", authenticateUser, contentMapperRoutes); app.use("/v2/migration", authenticateUser, migrationRoutes); - //For unmatched route patterns + // Handle unmatched routes app.use(unmatchedRoutesMiddleware); - // Error Middleware + // Handle errors app.use(errorMiddleware); - // starting the server & DB connection. + // Start the server and establish DB connection (async () => { - await connectToDatabase(); + await connectToDatabase(); // Establish DB connection + const server = app.listen(config.PORT, () => logger.info(`Server listening at port ${config.PORT}`) ); - // Chokidar - Watch for log file changes - const logFilePath = config.LOG_FILE_PATH; - const watcher = chokidar.watch(logFilePath); - // Socket.IO - Send logs to client - /** - * The Socket.IO server instance. - * - * @remarks - * This server instance is responsible for handling real-time communication between the client and the server using the Socket.IO library. - * - * @type {Server} - */ - const io = new Server( - server, - (http, - { - cors: { - origin: "*", // This allows all origins. For production, specify exact origins for security. - methods: ["GET", "POST"], // Specify which HTTP methods are allowed. - allowedHeaders: ["my-custom-header"], // Specify which headers are allowed. - credentials: true, // If your client needs to send cookies or credentials with the requests. - }, - }) - ); + // Initialize Socket.IO for real-time log updates + io = new Server(server, { + cors: { + origin: "*", // Allow all origins; adjust for production + methods: ["GET", "POST"], + allowedHeaders: ["my-custom-header"], + credentials: true, + }, + }); + + // Emit initial log file content to connected clients + + // File watcher for log file changes watcher.on("change", (path) => { - // Read the updated log file + console.info(`File changed: ${path}`); + + // Read the updated file content fs.readFile(path, "utf8", (err, data) => { if (err) { logger.error(`Error reading log file: ${err}`); return; } - // Get just the updated data - // const updatedData = data.slice(data.lastIndexOf("\n") + 1); - console.info("updates", data); - // Emit the updated data to all connected clients + try { - const parsedData = data; - io.emit("logUpdate", parsedData); + // Emit the updated log content to connected clients + io.emit("logUpdate", data); } catch (error) { - logger.error(`Error parsing data: ${error}`); + logger.error(`Error emitting log data: ${error}`); } }); }); + })(); } catch (e) { logger.error("Error while starting the server!"); logger.error(e); } + diff --git a/api/src/services/migration.service.ts b/api/src/services/migration.service.ts index 2a51f3ea9..ba17a6a95 100644 --- a/api/src/services/migration.service.ts +++ b/api/src/services/migration.service.ts @@ -16,7 +16,7 @@ import AuthenticationModel from "../models/authentication.js"; import { siteCoreService } from "./sitecore.service.js"; import { fileURLToPath } from 'url'; import { copyDirectory } from '../utils/index.js' - +import { setLogFilePath } from "../server.js"; @@ -221,6 +221,10 @@ const runCli = async (rg: string, user_id: string, project: any) => { const sourcePath = path.join(dirPath, 'sitecoreMigrationData', project?.destination_stack_id); const backupPath = path.join(process.cwd(), 'migration-data', project?.destination_stack_id); await copyDirectory(sourcePath, backupPath); + + const loggerPath = path.join(backupPath, 'logs', 'import','success.log'); + console.info('loggerPath', loggerPath); + await setLogFilePath(loggerPath); shell.cd(path.join(process.cwd(), '..', 'cli', 'packages', 'contentstack')); const pwd = shell.exec('pwd'); cliLogger(pwd); @@ -228,7 +232,7 @@ const runCli = async (rg: string, user_id: string, project: any) => { cliLogger(region); const login = shell.exec(`node bin/run login -a ${userData?.authtoken} -e ${userData?.email}`); cliLogger(login); - const exportData = shell.exec(`node bin/run cm:stacks:import -k ${project?.destination_stack_id} -d ${sourcePath} --backup-dir=${backupPath} --yes`); + const exportData = shell.exec(`node bin/run cm:stacks:import -k ${project?.destination_stack_id} -d ${sourcePath} --backup-dir=${backupPath} --yes`, { async: true }); cliLogger(exportData); } else { console.info('user not found.')