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
7 changes: 7 additions & 0 deletions api/src/config/dev.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,11 @@ export const devConfig = {
EU: "https://stag-eu-api.csnonprod.com/v3",
AZURE_NA: "https://stag-azure-na-api.csnonprod.com/v3",
},
CS_URL: {
NA: "https://app.contentstack.com/#!",
EU: "https://eu-app.contentstack.com/#!",
AZURE_NA: "https://azure-na-app.contentstack.com/#!",
AZURE_EU: "https://azure-eu-app.contentstack.com/#!",
}

};
6 changes: 6 additions & 0 deletions api/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ export type ConfigType = {
AZURE_NA: string;
AZURE_EU?: string;
};
CS_URL: {
NA: string;
EU: string;
AZURE_NA: string;
AZURE_EU?: string;
};
};

export const config: ConfigType = {
Expand Down
7 changes: 7 additions & 0 deletions api/src/config/prod.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,11 @@ export const prodConfig = {
AZURE_NA: "https://azure-na-api.contentstack.com/v3",
AZURE_EU: "https://azure-eu-api.contentstack.com/v3",
},
CS_URL: {
NA: "https://app.contentstack.com/#!",
EU: "https://eu-app.contentstack.com/#!",
AZURE_NA: "https://azure-na-app.contentstack.com/#!",
AZURE_EU: "https://azure-eu-app.contentstack.com/#!",
}

};
5 changes: 3 additions & 2 deletions api/src/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ export const STEPPER_STEPS = {
LEGACY_CMS: 1,
DESTINATION_STACK: 2,
CONTENT_MAPPING: 3,
MIGRATION: 4,
TESTING : 4,
MIGRATION: 5,
};
export const PREDEFINED_STATUS = [
"Draft",
Expand All @@ -120,4 +121,4 @@ export const PREDEFINED_STATUS = [
"Failed",
"Success",
];
export const PREDEFINED_STEPS = [1, 2, 3, 4];
export const PREDEFINED_STEPS = [1, 2, 3, 4,5];
18 changes: 18 additions & 0 deletions api/src/controllers/migration.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Request, Response } from "express";
import { migrationService } from "../services/migration.service.js";

const createTestStack = async (req: Request, res: Response): Promise<void> => {
const resp = await migrationService.createTestStack(req);
res.status(200).json(resp);
};

const deleteTestStack = async (req: Request, res: Response): Promise<void> => {
const resp = await migrationService.deleteTestStack(req);
res.status(200).json(resp);
};


export const migrationController = {
createTestStack,
deleteTestStack
};
2 changes: 2 additions & 0 deletions api/src/models/project-lowdb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ interface Project {
status: string;
current_step: number;
destination_stack_id: string;
test_stacks: []
current_test_stack_id:string;
legacy_cms: LegacyCMS;
content_mapper: [];
execution_log: [ExecutionLog];
Expand Down
16 changes: 16 additions & 0 deletions api/src/routes/migration.routes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import express from "express";

import { asyncRouter } from "../utils/async-router.utils.js";
import { migrationController } from "../controllers/migration.controller.js";

const router = express.Router({ mergeParams: true });
// Create a new project route
router.post(
"/test-stack/:orgId/:projectId",
asyncRouter(migrationController.createTestStack)
);
router.post(
"/test-stack/:projectId",
asyncRouter(migrationController.deleteTestStack)
);
export default router;
2 changes: 2 additions & 0 deletions api/src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { requestHeadersMiddleware } from "./middlewares/req-headers.middleware.j
import { unmatchedRoutesMiddleware } from "./middlewares/unmatched-routes.middleware.js";
import logger from "./utils/logger.js";
import contentMapperRoutes from "./routes/contentMapper.routes.js";
import migrationRoutes from "./routes/migration.routes.js";

try {
const app = express();
Expand All @@ -36,6 +37,7 @@ try {
app.use("/v2/org/:orgId", authenticateUser, orgRoutes);
app.use("/v2/org/:orgId/project", authenticateUser, projectRoutes);
app.use("/v2/mapper", authenticateUser, contentMapperRoutes);
app.use("/v2/migration", authenticateUser, migrationRoutes);

//For unmatched route patterns
app.use(unmatchedRoutesMiddleware);
Expand Down
180 changes: 180 additions & 0 deletions api/src/services/migration.service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { Request } from "express";
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 getAuthtoken from "../utils/auth.utils.js";
import logger from "../utils/logger.js";
import { HTTP_TEXTS, HTTP_CODES } from "../constants/index.js";
import { ExceptionFunction } from "../utils/custom-errors.utils.js";
import ProjectModelLowdb from "../models/project-lowdb.js";

const createTestStack = async (req: Request): Promise<LoginServiceType> => {
const srcFun = "createTestStack";
const orgId = req?.params?.orgId;
const projectId = req?.params?.projectId;
const { token_payload, name, description, master_locale } = req.body;

try {
const authtoken = await getAuthtoken(
token_payload?.region,
token_payload?.user_id
);

await ProjectModelLowdb.read();
const projectData = ProjectModelLowdb.chain.get("projects").value();
const testStackCount = projectData[0].test_stacks.length + 1;
const newName = name + "-" + testStackCount;

const [err, res] = await safePromise(
https({
method: "POST",
url: `${config.CS_API[
token_payload?.region as keyof typeof config.CS_API
]!}/stacks`,
headers: {
organization_uid: orgId,
authtoken,
},
data: {
stack: {
name: newName,
description,
master_locale,
},
},
})
);

if (err) {
logger.error(
getLogMessage(
srcFun,
HTTP_TEXTS.CS_ERROR,
token_payload,
err.response.data
)
);

return {
data: err.response.data,
status: err.response.status,
};
}

const index = ProjectModelLowdb.chain
.get("projects")
.findIndex({ id: projectId })
.value();
console.log(index);
if (index > -1) {
ProjectModelLowdb.update((data: any) => {
data.projects[index].current_test_stack_id = res.data.stack.uid;
data.projects[index].test_stacks.push(res.data.stack.uid);
});
}
return {
data: {
data: res.data,
url: `${
config.CS_URL[token_payload?.region as keyof typeof config.CS_URL]
}/stack/${res.data.stack.api_key}/dashboard`,
},
status: res.status,
};
} catch (error: any) {
logger.error(
getLogMessage(
srcFun,
"Error while creating a stack",
token_payload,
error
)
);

throw new ExceptionFunction(
error?.message || HTTP_TEXTS.INTERNAL_ERROR,
error?.statusCode || error?.status || HTTP_CODES.SERVER_ERROR
);
}
};

const deleteTestStack = async (req: Request): Promise<LoginServiceType> => {
const srcFun = "deleteTestStack";
const projectId = req?.params?.projectId;
const { token_payload, stack_key } = req.body;

try {
const authtoken = await getAuthtoken(
token_payload?.region,
token_payload?.user_id
);

const [err, res] = await safePromise(
https({
method: "DELETE",
url: `${config.CS_API[
token_payload?.region as keyof typeof config.CS_API
]!}/stacks`,
headers: {
api_key: stack_key,
authtoken,
},
})
);

if (err) {
logger.error(
getLogMessage(
srcFun,
HTTP_TEXTS.CS_ERROR,
token_payload,
err.response.data
)
);

return {
data: err.response.data,
status: err.response.status,
};
}

const index = ProjectModelLowdb.chain
.get("projects")
.findIndex({ id: projectId })
.value();
console.log(index);
if (index > -1) {
ProjectModelLowdb.update((data: any) => {
data.projects[index].current_test_stack_id = "";
const stackIndex = data.projects[index].test_stacks.indexOf(stack_key);
if (stackIndex > -1) {
data.projects[index].test_stacks.splice(stackIndex, 1);
}
});
}
return {
data: res.data,
status: res.status,
};
} catch (error: any) {
logger.error(
getLogMessage(
srcFun,
"Error while creating a stack",
token_payload,
error
)
);

throw new ExceptionFunction(
error?.message || HTTP_TEXTS.INTERNAL_ERROR,
error?.statusCode || error?.status || HTTP_CODES.SERVER_ERROR
);
}
};

export const migrationService = {
createTestStack,
deleteTestStack,
};
2 changes: 2 additions & 0 deletions api/src/services/projects.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,8 @@ const createProject = async (req: Request) => {
status: PROJECT_STATUS.DRAFT,
current_step: STEPPER_STEPS.LEGACY_CMS,
destination_stack_id: "",
test_stacks: [],
current_test_stack_id: "",
legacy_cms: {},
content_mapper: [],
execution_log: [],
Expand Down