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
3 changes: 3 additions & 0 deletions api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,17 @@
"homepage": "https://github.com/contentstack-expert-services/migration-v2-node-server#readme",
"dependencies": {
"axios": "^1.6.5",
"chokidar": "^3.6.0",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
"express": "^4.18.2",
"express-validator": "^7.0.1",
"express-winston": "^4.2.0",
"helmet": "^7.1.0",
"http": "^0.0.1-security",
"jsonwebtoken": "^9.0.2",
"lowdb": "^7.0.1",
"socket.io": "^4.7.5",
"uuid": "^9.0.1",
"winston": "^3.11.0"
},
Expand Down
8 changes: 3 additions & 5 deletions api/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,8 @@ export const HTTP_TEXTS = {
"Sorry, the requested content mapper id does not exists.",
ADMIN_LOGIN_ERROR:
"Sorry, You Don't have admin access in any of the Organisation",
PROJECT_DELETE:
"Project Deleted Successfully",
PROJECT_REVERT:
"Project Reverted Successfully"
PROJECT_DELETE: "Project Deleted Successfully",
PROJECT_REVERT: "Project Reverted Successfully",
};

export const HTTP_RESPONSE_HEADERS = {
Expand Down Expand Up @@ -145,4 +143,4 @@ export const CONTENT_TYPE_STATUS = {
2: 2, //verified
3: 3, //mapping failed
4: 4, //auto-dump
}
};
2 changes: 1 addition & 1 deletion api/src/controllers/projects.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,5 +77,5 @@ export const projectController = {
updateDestinationStack,
updateCurrentStep,
deleteProject,
revertProject
revertProject,
};
2 changes: 1 addition & 1 deletion api/src/models/contentTypesMapper-lowdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export interface ContentTypesMapper {
updateAt: Date;
contentstackTitle: string;
contentstackUid: string;
status:number;
status: number;
fieldMapping: [];
}

Expand Down
2 changes: 1 addition & 1 deletion api/src/models/project-lowdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ interface LegacyCMS {
awsRegion: string;
bucketName: string;
buketKey: string;
}
};
file_path: string;
is_fileValid: boolean;
}
Expand Down
1 change: 0 additions & 1 deletion api/src/routes/contentMapper.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,4 @@ router.get(
asyncRouter(contentMapperController.removeContentMapper)
);


export default router;
2 changes: 1 addition & 1 deletion api/src/routes/projects.routes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,6 @@ router.put(
router.delete("/:projectId", asyncRouter(projectController.deleteProject));

//revert Project Route
router.patch("/:projectId", asyncRouter(projectController.revertProject))
router.patch("/:projectId", asyncRouter(projectController.revertProject));

export default router;
43 changes: 41 additions & 2 deletions api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import { unmatchedRoutesMiddleware } from "./middlewares/unmatched-routes.middle
import logger from "./utils/logger.js";
import contentMapperRoutes from "./routes/contentMapper.routes.js";
import migrationRoutes from "./routes/migration.routes.js";

import chokidar from "chokidar";
import { Server } from "socket.io";
import http from "http";
import fs from "fs";
try {
const app = express();
app.use(
Expand Down Expand Up @@ -48,9 +51,45 @@ try {
// starting the server & DB connection.
(async () => {
await connectToDatabase();
app.listen(config.PORT, () =>
const server = app.listen(config.PORT, () =>
logger.info(`Server listening at port ${config.PORT}`)
);
// Chokidar - Watch for log file changes
const logFilePath = "/Users/sayali.joshi/Projects/migration-v2-node-server/api/combine.log"; // Replace with the actual path to your log file
const watcher = chokidar.watch(logFilePath);
// Socket.IO - Send logs to client
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.
},
})
);

watcher.on("change", (path) => {
// Read the updated log file
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);
} catch (error) {
logger.error(`Error parsing data: ${error}`);
}
});
});
})();
} catch (e) {
logger.error("Error while starting the server!");
Expand Down
41 changes: 24 additions & 17 deletions api/src/services/contentMapper.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import {
STEPPER_STEPS,
NEW_PROJECT_STATUS,
CONTENT_TYPE_STATUS,
VALIDATION_ERRORS
VALIDATION_ERRORS,
} from "../constants/index.js";
import logger from "../utils/logger.js";
import { config } from "../config/index.js";
Expand All @@ -37,7 +37,7 @@ const putTestData = async (req: Request) => {
return { id, isDeleted: true, ...field };
});
FieldMapperModel.update((data: any) => {
data.field_mapper = [...data?.field_mapper ?? [], ...fields];
data.field_mapper = [...(data?.field_mapper ?? []), ...fields];
});
contentTypes[index].fieldMapping = fieldIds;
});
Expand Down Expand Up @@ -109,7 +109,7 @@ const getContentTypes = async (req: Request) => {
.value();
content_mapper.push(contentMapperData);
});

if (!isEmpty(content_mapper)) {
if (search) {
const filteredResult = content_mapper
Expand Down Expand Up @@ -255,10 +255,7 @@ const updateContentType = async (req: Request) => {
const project = ProjectModelLowdb.data.projects[projectIndex];

if (
[
NEW_PROJECT_STATUS[5],
NEW_PROJECT_STATUS[4],
].includes(project.status) ||
[NEW_PROJECT_STATUS[5], NEW_PROJECT_STATUS[4]].includes(project.status) ||
project.current_step < STEPPER_STEPS.CONTENT_MAPPING
) {
logger.error(
Expand All @@ -281,25 +278,36 @@ const updateContentType = async (req: Request) => {
throw new BadRequestError(HTTP_TEXTS.INVALID_CONTENT_TYPE);
}


try {
await ContentTypesMapperModelLowdb.read();

if (fieldMapping) {
fieldMapping.forEach(async(field: any) => {
if (!field.ContentstackFieldType || field.ContentstackFieldType === '' || field.ContentstackFieldType === 'No matches found' || field.contentstackFieldUid === '') {
fieldMapping.forEach(async (field: any) => {
if (
!field.ContentstackFieldType ||
field.ContentstackFieldType === "" ||
field.ContentstackFieldType === "No matches found" ||
field.contentstackFieldUid === ""
) {
logger.error(
getLogMessage(
srcFun,
`${VALIDATION_ERRORS.STRING_REQUIRED.replace("$", "ContentstackFieldType or contentstackFieldUid")}`
`${VALIDATION_ERRORS.STRING_REQUIRED.replace(
"$",
"ContentstackFieldType or contentstackFieldUid"
)}`
)
);
await ContentTypesMapperModelLowdb.read();
ContentTypesMapperModelLowdb.update((data: any) => {
data.ContentTypesMappers[updateIndex].status = CONTENT_TYPE_STATUS[3];
data.ContentTypesMappers[updateIndex].status =
CONTENT_TYPE_STATUS[3];
});
throw new BadRequestError(
`${VALIDATION_ERRORS.STRING_REQUIRED.replace("$", "ContentstackFieldType or contentstackFieldUid")}`
`${VALIDATION_ERRORS.STRING_REQUIRED.replace(
"$",
"ContentstackFieldType or contentstackFieldUid"
)}`
);
}
});
Expand All @@ -324,7 +332,6 @@ const updateContentType = async (req: Request) => {
data.ContentTypesMappers[updateIndex].contentstackUid =
contentTypeData?.contentstackUid;
}

});

if (updateIndex < 0) {
Expand All @@ -343,7 +350,7 @@ const updateContentType = async (req: Request) => {
const fieldIndex = FieldMapperModel.data.field_mapper.findIndex(
(f: any) => f?.id === field?.id
);
if (fieldIndex > -1 && field?.ContentstackFieldType !== '') {
if (fieldIndex > -1 && field?.ContentstackFieldType !== "") {
FieldMapperModel.update((data: any) => {
data.field_mapper[fieldIndex] = field;
data.field_mapper[fieldIndex].isDeleted = false;
Expand All @@ -361,7 +368,7 @@ const updateContentType = async (req: Request) => {
.get("ContentTypesMappers")
.find({ id: contentTypeId })
.value();

return { updatedContentType };
} catch (error: any) {
logger.error(
Expand Down Expand Up @@ -807,5 +814,5 @@ export const contentMapperService = {
resetAllContentTypesMapping,
removeContentMapper,
removeMapping,
getSingleContentTypes
getSingleContentTypes,
};
13 changes: 7 additions & 6 deletions api/src/services/org.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,14 @@ const getAllStacks = async (req: Request): Promise<LoginServiceType> => {
};
}
let stacks = res?.data?.stacks;
if(search){
stacks = stacks.filter((stack:{name: string, description:string})=>{
if (search) {
stacks = stacks.filter((stack: { name: string; description: string }) => {
const stackName = stack?.name?.toLowerCase();
const stackDescription = stack?.description?.toLowerCase();
return stackName?.includes(search) || stackDescription?.includes(search);

})
return (
stackName?.includes(search) || stackDescription?.includes(search)
);
});
}
const locale = await getStackLocal(token_payload, stacks);
return {
Expand Down Expand Up @@ -301,7 +302,7 @@ const getStackLocal = async (token_payload: any, data: any) => {
token_payload?.region as keyof typeof config.CS_API
]!}/locales`,
headers: {
api_key: stack.api_key,
api_key: stack.api_key,
authtoken,
},
})
Expand Down
41 changes: 23 additions & 18 deletions api/src/services/projects.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Request } from "express";
import ProjectModelLowdb from "../models/project-lowdb.js";
import ContentTypesMapperModelLowdb from "../models/contentTypesMapper-lowdb.js"
import ContentTypesMapperModelLowdb from "../models/contentTypesMapper-lowdb.js";
import FieldMapperModel from "../models/FieldMapper.js";

import {
BadRequestError,
ExceptionFunction,
Expand Down Expand Up @@ -36,7 +36,7 @@ const getAllProjects = async (req: Request) => {
org_id: orgId,
region,
owner: user_id,
isDeleted:false
isDeleted: false,
})
.value();

Expand Down Expand Up @@ -85,18 +85,19 @@ const createProject = async (req: Request) => {
test_stacks: [],
current_test_stack_id: "",
legacy_cms: {
"is_fileValid":false,
is_fileValid: false,
awsDetails: {
awsRegion: "",
bucketName: "",
buketKey: ""
} },
buketKey: "",
},
},
content_mapper: [],
execution_log: [],
created_by: user_id,
updated_at: new Date().toISOString(),
created_at: new Date().toISOString(),
isDeleted:false
isDeleted: false,
};

try {
Expand Down Expand Up @@ -353,7 +354,8 @@ const affixConfirmation = async (req: Request) => {

const updateFileFormat = async (req: Request) => {
const { orgId, projectId } = req.params;
const { token_payload, file_format,file_path,is_fileValid,awsDetails } = req.body;
const { token_payload, file_format, file_path, is_fileValid, awsDetails } =
req.body;
const srcFunc = "updateFileFormat";
const projectIndex = (await getProjectUtil(
projectId,
Expand Down Expand Up @@ -395,16 +397,19 @@ const updateFileFormat = async (req: Request) => {
// }

try {
ProjectModelLowdb.update((data: any) => {
ProjectModelLowdb.update((data: any) => {
data.projects[projectIndex].legacy_cms.file_format = file_format;
data.projects[projectIndex].legacy_cms.file_path = file_path;
data.projects[projectIndex].legacy_cms.is_fileValid = is_fileValid;
data.projects[projectIndex].current_step = STEPPER_STEPS.LEGACY_CMS;
data.projects[projectIndex].status = NEW_PROJECT_STATUS[0];
data.projects[projectIndex].updated_at = new Date().toISOString();
data.projects[projectIndex].legacy_cms.awsDetails.awsRegion = awsDetails.awsRegion;
data.projects[projectIndex].legacy_cms.awsDetails.bucketName = awsDetails.bucketName;
data.projects[projectIndex].legacy_cms.awsDetails.buketKey = awsDetails.buketKey;
data.projects[projectIndex].legacy_cms.awsDetails.awsRegion =
awsDetails.awsRegion;
data.projects[projectIndex].legacy_cms.awsDetails.bucketName =
awsDetails.bucketName;
data.projects[projectIndex].legacy_cms.awsDetails.buketKey =
awsDetails.buketKey;
});

logger.info(
Expand Down Expand Up @@ -644,7 +649,7 @@ const updateCurrentStep = async (req: Request) => {
ProjectModelLowdb.update((data: any) => {
data.projects[projectIndex].current_step =
STEPPER_STEPS.CONTENT_MAPPING;
// data.projects[projectIndex].status = NEW_PROJECT_STATUS[3];
// data.projects[projectIndex].status = NEW_PROJECT_STATUS[3];
data.projects[projectIndex].updated_at = new Date().toISOString();
});
break;
Expand Down Expand Up @@ -779,9 +784,9 @@ const revertProject = async (req: Request) => {
)) as number;

const projects = ProjectModelLowdb.data.projects[projectIndex];
if (!projects){
if (!projects) {
throw new NotFoundError(HTTP_TEXTS.PROJECT_NOT_FOUND);
} else{
} else {
ProjectModelLowdb.update((data: any) => {
data.projects[projectIndex].isDeleted = false;
});
Expand All @@ -796,11 +801,11 @@ const revertProject = async (req: Request) => {
status: HTTP_CODES.OK,
data: {
message: HTTP_TEXTS.PROJECT_REVERT,
Project:projects
Project: projects,
},
};
}
}
};
export const projectService = {
getAllProjects,
getProject,
Expand All @@ -814,5 +819,5 @@ export const projectService = {
updateDestinationStack,
updateCurrentStep,
deleteProject,
revertProject
revertProject,
};
Loading