UNPKG

ring-websites-toolbelt

Version:

Ring Publishing Platform tool to work with Ring Websites

343 lines (296 loc) 14 kB
const fs = require('fs'); const prompts = require('prompts'); const homedir = require('os').homedir(); const ThemeScriptAbstract = require(`./../../ThemeScriptAbstract`); const ExternalApiProvider = require('../../providers/ExternalApiProvider'); class Setup extends ThemeScriptAbstract { constructor(options) { super(options); this.ucsConfig = {}; this.themesDeployed = []; } async execute() { this.validateThemeJson(); console.info('Setting up environment varriables'); await this.loadExistingConfig(); await this.chooseNamespace(); await this.setupConnectionParams(); await this.deployThemeIfNotYetDeployed(); await this.selectUcsVariant(); await this.setupS3Varriables(); await this.saveNamespaceConfigLocally(); console.info('Environment varriables successfuly set up! Use "website install" to download modules of your theme.'); } async loadExistingConfig() { if (fs.existsSync(this.paths.config)) { console.info('This theme has already been set up in your environment. Confirm or edit required variables:'); try { this.ucsConfig = JSON.parse(fs.readFileSync(this.paths.config, 'utf8')); } catch (ex) { throw new Error(`Invalid ${this.paths.config} content. Cannot parse file.`); } /** * START: TO REMOVE --- only to support backward compatibility with 1.6.x */ if (this.ucsConfig && Object.keys(this.ucsConfig).length && !this.ucsConfig['___all_websites_configs']) { const allWebsitesConfig = {}; Object.keys(this.ucsConfig).forEach((themeName) => { allWebsitesConfig[this.ucsConfig[themeName].namespaceId] = this.ucsConfig[themeName]; }); this.ucsConfig['___all_websites_configs'] = allWebsitesConfig; this.saveConfig(); } /** * END: TO REMOVE */ } } async chooseNamespace() { const validate = value => !!value; const defaultConfiguration = this.ucsConfig[this.themeJson.theme] || {}; const allNamespaces = this.ucsConfig['___all_websites_configs'] || {}; let typeNamespaceIdManually = true; if (Object.keys(allNamespaces).length) { const getNamespacesInfoPromisesArr = Object.keys(allNamespaces).map(namespaceId => { const simpleConfig = {namespaceId, publicKey: allNamespaces[namespaceId].publicKey, secretKey: allNamespaces[namespaceId].secretKey}; return (new ExternalApiProvider({}, simpleConfig)).getNamespace(); }); let namespacesInfo = []; try { namespacesInfo = await Promise.all(getNamespacesInfoPromisesArr); } catch (err) { console.error('Cannot load the names of the namespaces'); } const selectChoices = Object.keys(allNamespaces).map(namespaceId => { const namespaceData = namespacesInfo.filter(namespace => { return namespace.id === namespaceId })[0]; const title = namespaceData ? `${namespaceId} - ${namespaceData.name}` : namespaceId; return { title: title, value: namespaceId } }); selectChoices.push({ title: '[New namespace configuration]', value: '[new]' }); const currentNamespace = selectChoices.findIndex(choice => choice.value === defaultConfiguration.namespaceId); const selectedConfiguration = await prompts([{ type: 'select', name: 'namespaceId', message: 'What is namespaceId of your Ring Website? [namespaceId]', choices: selectChoices, initial: currentNamespace !== -1 ? currentNamespace : 0 }]); if (selectedConfiguration.namespaceId) { if (selectedConfiguration.namespaceId !== '[new]') { typeNamespaceIdManually = false; this.ucsConfig[this.themeJson.theme] = { ...this.ucsConfig[this.themeJson.theme], ...this.ucsConfig['___all_websites_configs'][selectedConfiguration.namespaceId] }; } } else { throw new Error(`Configuration is not fully set up. After you make required changes, please run "website setup" again.`); } } if (typeNamespaceIdManually) { const selectedConfiguration = await prompts([{ type: 'text', name: 'namespaceId', message: 'What is namespaceId of your Ring Website? [namespaceId]', initial: '', validate }]); if (selectedConfiguration.namespaceId) { if (!this.ucsConfig[this.themeJson.theme]) { this.ucsConfig[this.themeJson.theme] = {}; } this.ucsConfig[this.themeJson.theme].namespaceId = selectedConfiguration.namespaceId; this.ucsConfig[this.themeJson.theme].publicKey = ''; this.ucsConfig[this.themeJson.theme].secretKey = ''; } else { throw new Error(`Configuration is not fully set up. After you make required changes, please run "website setup" again.`); } } } async setupConnectionParams() { const validate = value => !!value; const defaultConfiguration = this.ucsConfig[this.themeJson.theme] || {}; const selectedConfiguration = await prompts([ { type: 'text', name: 'publicKey', message: 'What is your public key to Ring Websites API of that namespace? [publicKey]', initial: defaultConfiguration.publicKey || '', validate }, { type: 'text', name: 'secretKey', message: 'What is the secret key to that private key? [secretKey]', initial: defaultConfiguration.secretKey || '', validate } ]); if (selectedConfiguration.publicKey && selectedConfiguration.secretKey) { this.ucsConfig[this.themeJson.theme] = { ...this.ucsConfig[this.themeJson.theme], ...selectedConfiguration }; } else { throw new Error(`Configuration is not fully set up. After you make required changes, please run "website setup" again.`); } } async deployThemeIfNotYetDeployed() { let namespaceThemes; this.config = this.ucsConfig[this.themeJson.theme]; this.setUpProviders(); try { namespaceThemes = await this.api.getThemes(); } catch (error) { if (error.code === 403) { throw new Error(`Authorization failed. Check validity of selected namespace and its authorization keys.`); } else { throw error; } } // save config up to this point (namespaceId, publicKey and secretKey) as they are valid (request above succeded) this.saveConfig(); this.themesDeployed = namespaceThemes .filter(theme => theme.theme === this.themeJson.theme) .map(theme => theme.version); if (!this.themesDeployed.length) { console.warn(`Your theme is currently not deployed in any version.`); console.warn(`In order to create a development variant your theme has to be deployed at least once.`); const emptyThemeDeploy = await prompts([{ type: 'toggle', name: 'accept', message: `Do you want to deploy your theme "${this.themeJson.theme}" with version "0.0.0" and empty configuration?`, initial: true, active: 'yes', inactive: 'no' }]); if (emptyThemeDeploy.accept) { await this.api.deployEmptyTheme(); this.themesDeployed.push('0.0.0'); console.info(`Theme successfuly deployed: ${this.themeJson.theme}@0.0.0`); } else { throw new Error(`Configuration is not fully set up. After you make required changes, please run "website setup" again.`); } } } async selectUcsVariant() { const themeDevVariants = (await this.api.getVariants()).filter(variant => variant.theme === this.themeJson.theme && variant.dev_mode_enabled); const selectChoices = themeDevVariants.map(variant => ({ title: variant.variant_name, value: variant.variant_name })); selectChoices.push({ title: '[Create new variant]', value: '[new]' }); const validate = value => !!value; const defaultConfiguration = this.ucsConfig[this.themeJson.theme] || {}; const currentVariant = selectChoices.findIndex(choice => choice.value === defaultConfiguration.ucsVariant); const selectedConfiguration = await prompts([ { type: 'select', name: 'ucsVariant', message: 'Select Ring Website development variant you are going to develop on', choices: selectChoices, initial: currentVariant !== -1 ? currentVariant : 0 } ]); if (selectedConfiguration.ucsVariant) { if (selectedConfiguration.ucsVariant === '[new]') { await this.createNewVariant(); } else { this.ucsConfig[this.themeJson.theme] = { ...this.ucsConfig[this.themeJson.theme], ...selectedConfiguration }; } // save config up to this point (ucsVariant) as it was created here or selected this.saveConfig(); } else { throw new Error(`Configuration is not fully set up. After you make required changes, please run "website setup" again.`); } } async createNewVariant() { const validate = value => !!value; const themeVersionPrompt = this.themesDeployed.length <= 1 ? [] : [{ type: 'select', name: 'themeVersion', message: 'Select theme version for new variant', choices: this.themesDeployed.map(theme => ({ title: theme, value: theme })), initial: 0 }]; const selectedConfiguration = await prompts([ { type: 'text', name: 'ucsVariant', message: 'What will be the name of your variant?', initial: '', validate }, ...themeVersionPrompt ]); await this.api.createVariant({ variantName: selectedConfiguration.ucsVariant, version: this.themesDeployed.length <= 1 ? this.themesDeployed[0] : selectedConfiguration.themeVersion }); await this.api.updateVariant({ ucsVariant: selectedConfiguration.ucsVariant, devModeEnabled: true }); this.ucsConfig[this.themeJson.theme] = { ...this.ucsConfig[this.themeJson.theme], ...selectedConfiguration }; } async setupS3Varriables() { const validate = value => !!value; const defaultConfiguration = this.ucsConfig[this.themeJson.theme] || {}; const selectedConfiguration = await prompts([ { type: 'text', name: 's3BucketName', message: 'What is your S3 bucket name where we can store your static files? [s3BucketName]', initial: defaultConfiguration.s3BucketName || '', validate }, { type: 'text', name: 's3AccessKey', message: 'What is the access key to that bucket? [s3AccessKey]', initial: defaultConfiguration.s3AccessKey || '', validate }, { type: 'text', name: 's3SecretKey', message: 'What is the secret key to that access key? [s3SecretKey]', initial: defaultConfiguration.s3SecretKey || '', validate } ]); if (selectedConfiguration.s3BucketName && selectedConfiguration.s3AccessKey && selectedConfiguration.s3SecretKey) { this.ucsConfig[this.themeJson.theme] = { ...this.ucsConfig[this.themeJson.theme], ...selectedConfiguration }; this.saveConfig(); } else { throw new Error(`Configuration is not fully set up. After you make required changes, please run "website setup" again.`); } } async saveNamespaceConfigLocally() { const themeConfig = this.ucsConfig[this.themeJson.theme]; this.ucsConfig['___all_websites_configs'] = { ...this.ucsConfig['___all_websites_configs'], [themeConfig.namespaceId]: themeConfig }; this.saveConfig(); } saveConfig() { if (fs.existsSync(this.paths.config)) { fs.unlinkSync(this.paths.config); } fs.appendFileSync(this.paths.config, JSON.stringify(this.ucsConfig), 'utf8'); } } module.exports = Setup;