Skip to content

Commit c97295c

Browse files
authored
Merge pull request #994 from contentstack/feat/cmg-833
feat: add Drupal support with MySQL configuration and update docker-c…
2 parents 465e8b9 + 91467c6 commit c97295c

File tree

4 files changed

+261
-183
lines changed

4 files changed

+261
-183
lines changed

docker-compose.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ services:
1717
- CONTAINER_PATH=${CONTAINER_PATH}
1818
- CMS_DATA_PATH=${CMS_DATA_PATH}
1919
- AEM_TEMPLATES_DIR=${AEM_TEMPLATES_DIR:-templates}
20+
extra_hosts:
21+
- "host.docker.internal:host-gateway"
2022
networks:
2123
- migration-network
2224
security_opt:
@@ -39,6 +41,16 @@ services:
3941
- CMS_DATA_PATH=${CMS_DATA_PATH}
4042
- NODE_BACKEND_API=${NODE_BACKEND_API:-http://migration-api:5001}
4143
- AEM_TEMPLATES_DIR=${AEM_TEMPLATES_DIR:-templates}
44+
- CMS_LOCAL_PATH=${CMS_LOCAL_PATH:-}
45+
- MYSQL_HOST=${MYSQL_HOST:-}
46+
- MYSQL_USER=${MYSQL_USER:-}
47+
- MYSQL_PASSWORD=${MYSQL_PASSWORD:-}
48+
- MYSQL_DATABASE=${MYSQL_DATABASE:-}
49+
- MYSQL_PORT=${MYSQL_PORT:-3306}
50+
- DRUPAL_ASSETS_BASE_URL=${DRUPAL_ASSETS_BASE_URL:-}
51+
- DRUPAL_ASSETS_PUBLIC_PATH=${DRUPAL_ASSETS_PUBLIC_PATH:-}
52+
extra_hosts:
53+
- "host.docker.internal:host-gateway"
4254
networks:
4355
- migration-network
4456
security_opt:

fileUpdate.js

Lines changed: 93 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,12 @@
11
const fs = require('fs');
22
const path = require('path');
33
const { cliux, messageHandler } = require('@contentstack/cli-utilities');
4+
45
const isEmpty = (value) => value === null || value === undefined ||
56
(typeof value === 'object' && Object.keys(value).length === 0) ||
67
(typeof value === 'string' && value.trim().length === 0);
7-
const config = {
8-
plan: {
9-
dropdown: { optionLimit: 100 }
10-
},
11-
cmsType: null,
12-
isLocalPath: true,
13-
awsData: {
14-
awsRegion: 'us-east-2',
15-
awsAccessKeyId: '',
16-
awsSecretAccessKey: '',
17-
awsSessionToken: '',
18-
bucketName: '',
19-
bucketKey: ''
20-
},
21-
localPath: null
22-
};
238

24-
const configFilePath = path.resolve(path?.join?.('upload-api', 'src', 'config', 'index.ts'));
9+
const envFilePath = path.resolve(path.join('upload-api', '.env'));
2510

2611
const ensureDirectoryExists = (filePath) => {
2712
const dir = path.dirname(filePath);
@@ -31,6 +16,31 @@ const ensureDirectoryExists = (filePath) => {
3116
}
3217
};
3318

19+
const readEnvFile = () => {
20+
const vars = {};
21+
if (fs.existsSync(envFilePath)) {
22+
const content = fs.readFileSync(envFilePath, 'utf8');
23+
for (const line of content.split('\n')) {
24+
const trimmed = line.trim();
25+
if (trimmed && !trimmed.startsWith('#')) {
26+
const eqIndex = trimmed.indexOf('=');
27+
if (eqIndex > 0) {
28+
vars[trimmed.substring(0, eqIndex)] = trimmed.substring(eqIndex + 1);
29+
}
30+
}
31+
}
32+
}
33+
return vars;
34+
};
35+
36+
const writeEnvFile = (newVars) => {
37+
ensureDirectoryExists(envFilePath);
38+
const existing = readEnvFile();
39+
const merged = { ...existing, ...newVars };
40+
const lines = Object.entries(merged).map(([k, v]) => `${k}=${v}`);
41+
fs.writeFileSync(envFilePath, lines.join('\n') + '\n', 'utf8');
42+
};
43+
3444
const inquireRequireFieldValidation = (input) => {
3545
if (isEmpty(input)) {
3646
return messageHandler.parse('Please enter the path');
@@ -41,80 +51,83 @@ const inquireRequireFieldValidation = (input) => {
4151
return true;
4252
};
4353

44-
const typeSwitcher = async (type) => {
45-
switch (type) {
46-
case 'Aws S3': {
47-
const awsData = {
48-
awsRegion: await cliux.inquire({
49-
type: 'input',
50-
message: 'Enter AWS Region',
51-
name: 'awsRegion',
52-
validate: inquireRequireFieldValidation
53-
}),
54-
awsAccessKeyId: await cliux.inquire({
55-
type: 'input',
56-
message: 'Enter AWS Access Key Id',
57-
name: 'awsAccessKeyId',
58-
validate: inquireRequireFieldValidation
59-
}),
60-
awsSecretAccessKey: await cliux.inquire({
61-
type: 'input',
62-
message: 'Enter AWS Secret Access Key',
63-
name: 'awsSecretAccessKey',
64-
validate: inquireRequireFieldValidation
65-
}),
66-
};
67-
const isSessionToken = await cliux.inquire({
68-
choices: ['yes', 'no'],
69-
type: 'list',
70-
name: 'isSessionToken',
71-
message: 'Do you have a Session Token?'
72-
});
73-
if (isSessionToken === 'yes') {
74-
awsData.awsSessionToken = await cliux.inquire({
75-
type: 'input',
76-
message: 'Enter AWS Session Token',
77-
name: 'awsSessionToken',
78-
validate: inquireRequireFieldValidation
79-
});
80-
}
81-
return awsData;
82-
}
83-
case 'Locale Path': {
84-
return await cliux.inquire({
85-
type: 'input',
86-
message: 'Enter file path',
87-
name: 'filePath',
88-
validate: inquireRequireFieldValidation
89-
});
90-
}
91-
default:
92-
console.log('⚠️ Invalid type provided');
93-
return;
94-
}
95-
};
96-
9754
const XMLMigration = async () => {
9855
const typeOfcms = await cliux.inquire({
99-
choices: ['sitecore', 'contentful', 'wordpress', 'aem'],
56+
choices: ['sitecore', 'contentful', 'wordpress', 'aem', 'drupal'],
10057
type: 'list',
10158
name: 'value',
10259
message: 'Choose the option to proceed with your legacy CMS:'
10360
});
10461

105-
const data = await typeSwitcher('Locale Path');
106-
if (typeof typeOfcms === 'string') {
107-
config.cmsType = typeOfcms;
108-
} else {
62+
if (typeof typeOfcms !== 'string') {
10963
console.log('⚠️ Error: Expected a string for typeOfcms but got an object.');
64+
return;
11065
}
111-
if (typeof data === 'string') {
112-
config.localPath = data;
66+
67+
const envVars = { CMS_TYPE: typeOfcms };
68+
69+
if (typeOfcms === 'drupal') {
70+
console.log('\nDrupal uses a MySQL database connection. Please provide your database details:');
71+
72+
envVars.MYSQL_HOST = await cliux.inquire({
73+
type: 'input',
74+
message: 'Enter MySQL Host',
75+
name: 'mysqlHost',
76+
validate: (input) => isEmpty(input) ? 'Please enter the MySQL host' : true
77+
});
78+
envVars.MYSQL_USER = await cliux.inquire({
79+
type: 'input',
80+
message: 'Enter MySQL User',
81+
name: 'mysqlUser',
82+
validate: (input) => isEmpty(input) ? 'Please enter the MySQL user' : true
83+
});
84+
envVars.MYSQL_PASSWORD = await cliux.inquire({
85+
type: 'password',
86+
message: 'Enter MySQL Password (can be empty)',
87+
name: 'mysqlPassword'
88+
});
89+
envVars.MYSQL_DATABASE = await cliux.inquire({
90+
type: 'input',
91+
message: 'Enter MySQL Database Name',
92+
name: 'mysqlDatabase',
93+
validate: (input) => isEmpty(input) ? 'Please enter the MySQL database name' : true
94+
});
95+
const portInput = await cliux.inquire({
96+
type: 'input',
97+
message: 'Enter MySQL Port [3306]',
98+
name: 'mysqlPort'
99+
});
100+
envVars.MYSQL_PORT = portInput || '3306';
101+
102+
envVars.DRUPAL_ASSETS_BASE_URL = await cliux.inquire({
103+
type: 'input',
104+
message: 'Enter Drupal Assets Base URL (e.g. https://example.com)',
105+
name: 'assetsBaseUrl'
106+
});
107+
envVars.DRUPAL_ASSETS_PUBLIC_PATH = await cliux.inquire({
108+
type: 'input',
109+
message: 'Enter Drupal Assets Public Path (e.g. sites/default/files)',
110+
name: 'assetsPublicPath'
111+
});
112+
113+
envVars.CMS_LOCAL_PATH = 'sql';
113114
} else {
114-
console.log('⚠️ Error: Expected a string for localPath but got an object.');
115+
const localPath = await cliux.inquire({
116+
type: 'input',
117+
message: 'Enter file path',
118+
name: 'filePath',
119+
validate: inquireRequireFieldValidation
120+
});
121+
if (typeof localPath === 'string') {
122+
envVars.CMS_LOCAL_PATH = localPath;
123+
} else {
124+
console.log('⚠️ Error: Expected a string for localPath but got an object.');
125+
return;
126+
}
115127
}
116-
ensureDirectoryExists(configFilePath);
117-
fs.writeFileSync(configFilePath, `export default ${JSON.stringify(config, null, 2)};`, 'utf8');
128+
129+
writeEnvFile(envVars);
130+
console.log(`✅ Configuration written to ${envFilePath}`);
118131
};
119132

120133
XMLMigration();

0 commit comments

Comments
 (0)