mirror of
https://github.com/kingomarnajjar/flex-template-web.git
synced 2026-07-26 06:47:17 +10:00
378 lines
11 KiB
JavaScript
378 lines
11 KiB
JavaScript
const inquirer = require('inquirer');
|
|
const fs = require('fs');
|
|
const readline = require('readline');
|
|
const chalk = require('chalk');
|
|
|
|
/**
|
|
* If config script is running with flag --check only check if .env file exists.
|
|
* Show error if .env file doesn't exist.
|
|
*
|
|
* When running the script without flag .env file is created.
|
|
* User can fill in environment variables needed for running the application.
|
|
*
|
|
* If .env file already exists user can edit the values configured in the file.
|
|
* Old values are used as default.
|
|
*
|
|
*/
|
|
|
|
const run = () => {
|
|
const hasEnvFile = fs.existsSync(`./.env`);
|
|
|
|
if (process.argv[2] && process.argv[2] === '--check') {
|
|
if (!hasEnvFile) {
|
|
process.on('exit', code => {
|
|
console.log(`
|
|
|
|
${chalk.bold.red(`You don't have required .env file!`)}
|
|
|
|
Some environment variables are required before starting Flex template for web. You can create the .env file and configure the variables by running ${chalk.cyan.bold(
|
|
'yarn run config'
|
|
)}
|
|
|
|
`);
|
|
});
|
|
process.exit(1);
|
|
}
|
|
} else if (hasEnvFile) {
|
|
console.log(`
|
|
${chalk.bold.green('.env file already exists!')}
|
|
Remember to restart the application after editing the environment variables! You can also edit environment variables by editing the .env file directly in your text editor.
|
|
`);
|
|
|
|
inquirer
|
|
.prompt([
|
|
{
|
|
type: 'confirm',
|
|
name: 'editEnvFile',
|
|
message: 'Do you want to edit the .env file?',
|
|
default: false,
|
|
},
|
|
])
|
|
.then(answers => {
|
|
if (answers.editEnvFile) {
|
|
const settings = findSavedValues();
|
|
askQuestions(settings);
|
|
}
|
|
});
|
|
} else {
|
|
inquirer
|
|
.prompt([
|
|
{
|
|
type: 'confirm',
|
|
name: 'createEmptyEnv',
|
|
message: `Do you want to configure required environment variables now?
|
|
${chalk.dim(
|
|
`If you don't set up variables now .env file is created based on .env-template file. The application will not work correctly without Flex client ID, Stripe publishable API key and MapBox acces token.
|
|
We recommend setting up the required variables before starting the application!`
|
|
)}`,
|
|
default: true,
|
|
},
|
|
])
|
|
.then(answers => {
|
|
createEnvFile();
|
|
if (answers.createEmptyEnv) {
|
|
askQuestions();
|
|
} else {
|
|
showSuccessMessage();
|
|
}
|
|
})
|
|
.catch(err => {
|
|
console.log(chalk.red(`An error occurred due to: ${err.message}`));
|
|
});
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Questions for mandatory variables.
|
|
*
|
|
* @param {*} settings - list of values used as default if user is editing the .env file
|
|
*
|
|
*/
|
|
const mandatoryVariables = settings => {
|
|
const clientIdDefaultMaybe =
|
|
settings &&
|
|
settings.REACT_APP_SHARETRIBE_SDK_CLIENT_ID !== '' &&
|
|
settings.REACT_APP_SHARETRIBE_SDK_CLIENT_ID !== 'change-me'
|
|
? { default: settings.REACT_APP_SHARETRIBE_SDK_CLIENT_ID }
|
|
: {};
|
|
const stripeDefaultMaybe =
|
|
settings && settings.REACT_APP_STRIPE_PUBLISHABLE_KEY !== ''
|
|
? { default: settings.REACT_APP_STRIPE_PUBLISHABLE_KEY }
|
|
: {};
|
|
const mapBoxDefaultMaybe =
|
|
settings && settings.REACT_APP_MAPBOX_ACCESS_TOKEN !== ''
|
|
? { default: settings.REACT_APP_MAPBOX_ACCESS_TOKEN }
|
|
: {};
|
|
const currencyDefault =
|
|
settings && settings.REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY !== ''
|
|
? settings.REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY
|
|
: 'USD';
|
|
|
|
return [
|
|
{
|
|
type: 'input',
|
|
name: 'REACT_APP_SHARETRIBE_SDK_CLIENT_ID',
|
|
message: `What is your Flex client ID?
|
|
${chalk.dim(
|
|
'Client ID is needed for connecting with Flex API. You can find your client ID from Flex Console.'
|
|
)}
|
|
`,
|
|
validate: function(value) {
|
|
if (value.match(/^[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}$/i)) {
|
|
return true;
|
|
}
|
|
return 'Please enter valid Flex Client ID. You can check it form Flex Console!';
|
|
},
|
|
...clientIdDefaultMaybe,
|
|
},
|
|
{
|
|
type: 'input',
|
|
name: 'REACT_APP_STRIPE_PUBLISHABLE_KEY',
|
|
message: `What is your Stripe publishable key?
|
|
${chalk.dim(
|
|
`Stripe publishable API key is for generating tokens with Stripe API. Use test key (prefix pk_test_) for development. Remember to also add the Stripe secret key to Console before testing the payments.
|
|
If you don't set the Stripe key, payments won't work in the application.`
|
|
)}
|
|
`,
|
|
validate: function(value) {
|
|
if (value.match(/^pk_/) || value === '') {
|
|
return true;
|
|
}
|
|
return 'Please enter Stripe publishable key with prefix pk_!';
|
|
},
|
|
...stripeDefaultMaybe,
|
|
},
|
|
{
|
|
type: 'input',
|
|
name: 'REACT_APP_MAPBOX_ACCESS_TOKEN',
|
|
message: `What is your Mapbox access token?
|
|
${chalk.dim(
|
|
`Mapbox is the default map provider of the application. Sign up for Mapbox and go the to account page. Then click Create access token. For more information see the: Integrating to map providers documentation.
|
|
If you don't set the Mapbox key, the map components won't work in the application.`
|
|
)}
|
|
`,
|
|
...mapBoxDefaultMaybe,
|
|
},
|
|
{
|
|
type: 'input',
|
|
name: 'REACT_APP_SHARETRIBE_MARKETPLACE_CURRENCY',
|
|
message: `What is your marketplace currency?
|
|
${chalk.dim(
|
|
'The currency used in the Marketplace must be in ISO 4217 currency code. For example USD, EUR, CAD, AUD, etc. The default value is USD.'
|
|
)}
|
|
`,
|
|
default: function() {
|
|
return currencyDefault;
|
|
},
|
|
validate: function(value) {
|
|
if (value.match(/^[a-zA-Z]{3}$/)) {
|
|
return true;
|
|
}
|
|
return 'Please enter currency in ISO 4217 format (e.g. USD, EUR, CAD...)';
|
|
},
|
|
},
|
|
];
|
|
};
|
|
|
|
/**
|
|
* Questions for advances variables. User can choose to edit these or not.
|
|
*
|
|
* @param {*} settings - list of values used as default if user is editing the .env file
|
|
*
|
|
*/
|
|
|
|
const advancedSettings = settings => {
|
|
const rootUrlDefault = settings ? settings.REACT_APP_CANONICAL_ROOT_URL : null;
|
|
const availabilityDefault = settings
|
|
? settings.REACT_APP_AVAILABILITY_ENABLED.toLowerCase() === 'true'
|
|
: true;
|
|
const searchesDefault = settings
|
|
? settings.REACT_APP_DEFAULT_SEARCHES_ENABLED.toLowerCase() === 'true'
|
|
: true;
|
|
|
|
return [
|
|
{
|
|
type: 'confirm',
|
|
name: 'showAdvancedSettings',
|
|
message: 'Do you want to edit advanced settings?',
|
|
default: false,
|
|
},
|
|
{
|
|
type: 'input',
|
|
name: 'REACT_APP_CANONICAL_ROOT_URL',
|
|
message: `What is your canonical root URL?
|
|
${chalk.dim(
|
|
'Canonical root URL of the marketplace is needed for social media sharing and SEO optimization. When developing the template application locally URL is usually http://localhost:3000'
|
|
)}
|
|
`,
|
|
default: function() {
|
|
return rootUrlDefault ? rootUrlDefault : 'http://localhost:3000';
|
|
},
|
|
when: function(answers) {
|
|
return answers.showAdvancedSettings;
|
|
},
|
|
},
|
|
{
|
|
type: 'confirm',
|
|
name: 'REACT_APP_AVAILABILITY_ENABLED',
|
|
message: `Do you want to enable availability calendar?
|
|
${chalk.dim(
|
|
'This setting enables the Availability Calendar for listings. The default value for this setting is true.'
|
|
)}
|
|
`,
|
|
default: availabilityDefault,
|
|
when: function(answers) {
|
|
return answers.showAdvancedSettings;
|
|
},
|
|
},
|
|
{
|
|
type: 'confirm',
|
|
name: 'REACT_APP_DEFAULT_SEARCHES_ENABLED',
|
|
message: `Do you want to enable default search suggestions?
|
|
${chalk.dim(
|
|
'This setting enables the Default Search Suggestions in location autocomplete search input. The default value for this setting is true.'
|
|
)}
|
|
`,
|
|
default: searchesDefault,
|
|
when: function(answers) {
|
|
return answers.showAdvancedSettings;
|
|
},
|
|
},
|
|
];
|
|
};
|
|
|
|
const askQuestions = settings => {
|
|
inquirer
|
|
.prompt(mandatoryVariables(settings))
|
|
.then(answers => {
|
|
return readLines(answers);
|
|
})
|
|
.then(values => {
|
|
const data = getData(values);
|
|
updateEnvFile(data);
|
|
|
|
console.log(chalk.yellow.bold(`Advanced settings:`));
|
|
inquirer
|
|
.prompt(advancedSettings(settings))
|
|
.then(answers => {
|
|
return readLines(answers);
|
|
})
|
|
.then(values => {
|
|
const data = getData(values);
|
|
updateEnvFile(data);
|
|
showSuccessMessage();
|
|
});
|
|
})
|
|
.catch(err => {
|
|
console.log(chalk.red(`An error occurred due to: ${err.message}`));
|
|
});
|
|
};
|
|
|
|
const showSuccessMessage = () => {
|
|
console.log(`
|
|
${chalk.green.bold('.env file saved succesfully!')}
|
|
|
|
Start the Flex template application by running ${chalk.bold.cyan('yarn run dev')}
|
|
|
|
Note that the .env file is a hidden file so it might not be visible directly in directory listing. If you want to update the environment variables run ${chalk.cyan.bold(
|
|
'yarn run config'
|
|
)} again or edit the .env file directly. Remember to restart the application after editing the environment variables!
|
|
`);
|
|
};
|
|
|
|
/**
|
|
* Create new .env file using .env-template
|
|
*/
|
|
const createEnvFile = () => {
|
|
fs.copyFileSync('./.env-template', './.env', err => {
|
|
if (err) throw err;
|
|
});
|
|
};
|
|
|
|
const findSavedValues = () => {
|
|
const savedEnvFile = fs.readFileSync('./.env').toString();
|
|
|
|
const settings = savedEnvFile.split('\n').reduce((obj, line) => {
|
|
const splits = line.split('=');
|
|
const key = splits[0].trim();
|
|
if (splits.length > 1) {
|
|
obj[key] = splits
|
|
.slice(1)
|
|
.join('=')
|
|
.trim();
|
|
}
|
|
return obj;
|
|
}, {});
|
|
|
|
return settings;
|
|
};
|
|
|
|
/**
|
|
* Read all lines from existing .env file to array.
|
|
* If line matches one of the keys in user's answers update add value to that line.
|
|
* Otherwise keep the original line.
|
|
*
|
|
* @param {object} answers object containing all the inputs user has given to questions
|
|
*
|
|
* @return returns a Promise that resolves with values object containing user input and read lines
|
|
*/
|
|
|
|
const readLines = answers => {
|
|
return new Promise((resolve, reject) => {
|
|
const rl = readline.createInterface({
|
|
input: fs.createReadStream('./.env'),
|
|
});
|
|
|
|
const lines = [];
|
|
rl.on('line', function(line) {
|
|
lines.push(line);
|
|
});
|
|
|
|
rl.on('close', () => {
|
|
const values = { answers, lines };
|
|
resolve(values);
|
|
});
|
|
});
|
|
};
|
|
|
|
const getData = values => {
|
|
const { lines, answers } = values;
|
|
|
|
const data = lines.map(line => {
|
|
const key = getKeyFromAnswers(answers, line);
|
|
if (key) {
|
|
const value = `${answers[key]}`;
|
|
return `${key}=${value.trim()}\n`;
|
|
} else {
|
|
return `${line}\n`;
|
|
}
|
|
});
|
|
|
|
return data;
|
|
};
|
|
|
|
const updateEnvFile = data => {
|
|
fs.writeFileSync('./.env', data.join(''));
|
|
};
|
|
|
|
/**
|
|
* Check if line contains the key from the user answers.
|
|
*
|
|
* @param {object} answers array of answers user has given to questions
|
|
* @param {string} line line from the existing .env file
|
|
*
|
|
* @returns key if the key matches to the one in the line
|
|
*/
|
|
const getKeyFromAnswers = (answers, line) => {
|
|
let foundKey;
|
|
if (answers) {
|
|
foundKey = Object.keys(answers).find(function(key) {
|
|
if (line.includes(key)) {
|
|
return key;
|
|
}
|
|
});
|
|
}
|
|
return foundKey;
|
|
};
|
|
|
|
run();
|