Example #1
0
 constructor(config) {
     super(config);
     this.port = _.get(Webiny.getConfig(), 'browserSync.port', 3000);
     this.domain = _.get(Webiny.getConfig(), 'browserSync.domain', 'http://localhost');
     this.webpackCallback = config.webpackCallback || null;
     this.progressCallback = config.progressCallback || null;
 }
Example #2
0
        return inquirer.prompt(questions).then(function (answers) {
            answers.domain = _.trimEnd(answers.domain, '/');

            const configs = {
                dockerCompose: Webiny.projectRoot('docker-compose.yaml'),
                environments: Webiny.projectRoot('Configs/Environments.yaml'),
                base: {
                    application: Webiny.projectRoot('Configs/Base/Webiny.yaml'),
                    database: Webiny.projectRoot('Configs/Base/Database.yaml'),
                    security: Webiny.projectRoot('Configs/Base/Security.yaml')
                },
                local: {
                    application: Webiny.projectRoot('Configs/Local/Webiny.yaml')
                }
            };

            try {
                // Populate Environments.yaml
                let config = yaml.safeLoad(Webiny.readFile(configs.environments));
                config.Environments.Local = answers.domain;
                Webiny.writeFile(configs.environments, yaml.safeDump(config, {indent: 4}));

                // Populate Base/Webiny.yaml
                config = yaml.safeLoad(Webiny.readFile(configs.base.application));
                config.Webiny.Acl.Token = generatePassword(40, false, /[\dA-Za-z#_\$]/);
                Webiny.writeFile(configs.base.application, yaml.safeDump(config, {indent: 4}));

                // Populate Base/Database.yaml
                config = yaml.safeLoad(Webiny.readFile(configs.base.database));
                config.Mongo.Services.Webiny.Calls[0][1] = [answers.database];
                if (docker) {
                    config.Mongo.Services.Webiny.Arguments.Uri = 'mongodb:27017';
                }
                Webiny.writeFile(configs.base.database, yaml.safeDump(config, {indent: 4, flowLevel: 5}));

                // Populate Base/Security.yaml
                config = yaml.safeLoad(Webiny.readFile(configs.base.security));
                config.Security.Tokens.Webiny.SecurityKey = generatePassword(30, false, /[\dA-Za-z#_\$:\?#]/);
                config.Security.TwoFactorAuth.Key = generatePassword(30, false, /[\dA-Za-z#_\$:\?#]/);
                Webiny.writeFile(configs.base.security, yaml.safeDump(config, {indent: 4, flowLevel: 5}));

                // Populate Local/Webiny.yaml
                config = yaml.safeLoad(Webiny.readFile(configs.local.application));
                config.Webiny.WebUrl = answers.domain;
                config.Webiny.ApiUrl = answers.domain + '/api';
                Webiny.writeFile(configs.local.application, yaml.safeDump(config, {indent: 4}));

                // Populate docker-compose.yaml
                if (docker) {
                    config = yaml.safeLoad(Webiny.readFile(configs.dockerCompose));
                    config.services.nginx.ports.push(nginxPort + ':80');

                    let alias = answers.domain;
                    alias = alias.replace('http://', '').replace('https://', '').split(':')[0];
                    config.services.nginx.networks.default.aliases.push(alias);

                    config.services.php.extra_hosts.push('dockerhost:' + answers.hostIp);
                    config.services.php.environment.XDEBUG_CONFIG = `remote_enable=0 remote_host=${answers.hostIp}`;
                    config.services.mongodb.ports.push(answers.databasePort + ':27017');

                    Webiny.writeFile(configs.dockerCompose, yaml.safeDump(config, {indent: 4}));
                    setupDockerVirtualHost(answers);
                }

                Webiny.success('Configuration files written successfully!');

                // We need to store the env if the project is run using docker
                if (docker) {
                    const wConfig = Webiny.getConfig();
                    wConfig.env = 'docker';
                    // Set default browserSync port for Docker only
                    wConfig.browserSync = {port: 3010};
                    Webiny.saveConfig(wConfig);
                }
            } catch (err) {
                Webiny.failure(err.message, err);
                return;
            }

            if (docker) {
                Webiny.info('Initializing Docker containers...');
                // Run Docker containers so we can execute install scripts.
                Webiny.shellExecute('docker-compose up -d');
            }

            const php = docker ? 'docker-compose run php php' : 'php';

            // Run Webiny installation procedure
            Webiny.info('Running Webiny app installation...');
            Webiny.shellExecute(`${php} Apps/Webiny/Php/Cli/install.php Local Webiny`);

            // Create admin user
            const params = [answers.user, answers.password].join(' ');
            try {
                let output = Webiny.shellExecute(`${php} Apps/Webiny/Php/Cli/admin.php Local ${params}`, {stdio: 'pipe'});
                output = JSON.parse(output);
                if (output.status === 'created') {
                    Webiny.success('Admin user created successfully!');
                }

                if (output.status === 'failed') {
                    Webiny.exclamation(output.message);
                }
            } catch (err) {
                Webiny.failure(err.message);
            }

            // If Docker - we do not run nginx setup wizard
            if (docker) {
                return answers;
            }

            // Optionally create nginx config
            try {
                // Virtual host wizard
                const hostAnswers = {
                    domain: answers.domain
                };

                Webiny.shellExecute('nginx -v', {stdio: 'pipe'});
                return inquirer.prompt({
                    type: 'confirm',
                    name: 'createHost',
                    message: 'Would you like us to create a new nginx virtual host for you?',
                    default: true
                }).then(a => {
                    if (a.createHost) {
                        hostAnswers.createHost = true;
                        return inquirer.prompt({
                            type: 'input',
                            name: 'errorLogFile',
                            message: 'Where do you want to place your error log file (including file name)?',
                            default: function () {
                                const server = answers.domain.replace('http://', '').replace('https://', '').split(':')[0];
                                return '/var/log/nginx/' + server + '-error.log';
                            }
                        }).then(a => {
                            hostAnswers.errorLogFile = a.errorLogFile;
                            return setupVirtualHost(hostAnswers);
                        });
                    }
                    return answers;
                });
            } catch (err) {
                // Skip host prompts
            }
        });
Example #3
0
    runWizard({env}) {
        const docker = env === 'docker';
        const inquirer = require('inquirer');
        const yaml = require('js-yaml');
        const _ = require('lodash');
        const generatePassword = require('password-generator');
        const interfaces = require('./interfaces');

        // Save env as it needs to be available as soon as possible for conditional execution
        const wConfig = Webiny.getConfig();
        wConfig.env = env;
        Webiny.saveConfig(wConfig);

        Webiny.log("\nNow we need to create a platform configuration and your first user:\n");

        // Need this later in setup
        let nginxPort = null;

        // Define wizard questions
        const questions = [
            {
                type: 'input',
                name: 'domain',
                message: 'What\'s your local domain (e.g. http://domain.app:8000)?',
                validate: url => {
                    let valid = Webiny.validate.domain(url);
                    // Check if URL contains port which is mandatory for Docker setup
                    if (valid === true && docker) {
                        const message = 'Docker requires a port to be provided. Please add a port number to the URL.';
                        nginxPort = parseInt(_.get(url.split(':'), 2));
                        if (_.isNaN(nginxPort)) {
                            return message;
                        }
                    }
                    return valid;
                }
            },
            {
                type: 'list',
                choices: interfaces(),
                name: 'hostIp',
                message: 'Select your host IP address:',
                when: docker
            },
            {
                type: 'input',
                name: 'database',
                message: 'What\'s your database name?',
                default: () => {
                    return 'webiny';
                }
            },
            {
                type: 'input',
                name: 'databasePort',
                when: docker,
                message: 'What\'s your mongodb service port?',
                default: ({domain}) => {
                    try {
                        return parseInt(domain.split(':')[2]) + 1;
                    } catch (e) {
                        return '';
                    }
                }
            },
            {
                type: 'input',
                name: 'user',
                message: 'Enter your admin user email:',
                validate: Webiny.validate.email
            },
            {
                type: 'password',
                name: 'password',
                message: 'Enter your admin user password:'******'dev' && value !== 'admin' && value.length < 8) {
                        return 'Please enter at least 8 characters!';
                    }

                    return true;
                }
            }
        ];

        return inquirer.prompt(questions).then(function (answers) {
            answers.domain = _.trimEnd(answers.domain, '/');

            const configs = {
                dockerCompose: Webiny.projectRoot('docker-compose.yaml'),
                environments: Webiny.projectRoot('Configs/Environments.yaml'),
                base: {
                    application: Webiny.projectRoot('Configs/Base/Webiny.yaml'),
                    database: Webiny.projectRoot('Configs/Base/Database.yaml'),
                    security: Webiny.projectRoot('Configs/Base/Security.yaml')
                },
                local: {
                    application: Webiny.projectRoot('Configs/Local/Webiny.yaml')
                }
            };

            try {
                // Populate Environments.yaml
                let config = yaml.safeLoad(Webiny.readFile(configs.environments));
                config.Environments.Local = answers.domain;
                Webiny.writeFile(configs.environments, yaml.safeDump(config, {indent: 4}));

                // Populate Base/Webiny.yaml
                config = yaml.safeLoad(Webiny.readFile(configs.base.application));
                config.Webiny.Acl.Token = generatePassword(40, false, /[\dA-Za-z#_\$]/);
                Webiny.writeFile(configs.base.application, yaml.safeDump(config, {indent: 4}));

                // Populate Base/Database.yaml
                config = yaml.safeLoad(Webiny.readFile(configs.base.database));
                config.Mongo.Services.Webiny.Calls[0][1] = [answers.database];
                if (docker) {
                    config.Mongo.Services.Webiny.Arguments.Uri = 'mongodb:27017';
                }
                Webiny.writeFile(configs.base.database, yaml.safeDump(config, {indent: 4, flowLevel: 5}));

                // Populate Base/Security.yaml
                config = yaml.safeLoad(Webiny.readFile(configs.base.security));
                config.Security.Tokens.Webiny.SecurityKey = generatePassword(30, false, /[\dA-Za-z#_\$:\?#]/);
                config.Security.TwoFactorAuth.Key = generatePassword(30, false, /[\dA-Za-z#_\$:\?#]/);
                Webiny.writeFile(configs.base.security, yaml.safeDump(config, {indent: 4, flowLevel: 5}));

                // Populate Local/Webiny.yaml
                config = yaml.safeLoad(Webiny.readFile(configs.local.application));
                config.Webiny.WebUrl = answers.domain;
                config.Webiny.ApiUrl = answers.domain + '/api';
                Webiny.writeFile(configs.local.application, yaml.safeDump(config, {indent: 4}));

                // Populate docker-compose.yaml
                if (docker) {
                    config = yaml.safeLoad(Webiny.readFile(configs.dockerCompose));
                    config.services.nginx.ports.push(nginxPort + ':80');

                    let alias = answers.domain;
                    alias = alias.replace('http://', '').replace('https://', '').split(':')[0];
                    config.services.nginx.networks.default.aliases.push(alias);

                    config.services.php.extra_hosts.push('dockerhost:' + answers.hostIp);
                    config.services.php.environment.XDEBUG_CONFIG = `remote_enable=0 remote_host=${answers.hostIp}`;
                    config.services.mongodb.ports.push(answers.databasePort + ':27017');

                    Webiny.writeFile(configs.dockerCompose, yaml.safeDump(config, {indent: 4}));
                    setupDockerVirtualHost(answers);
                }

                Webiny.success('Configuration files written successfully!');

                // We need to store the env if the project is run using docker
                if (docker) {
                    const wConfig = Webiny.getConfig();
                    wConfig.env = 'docker';
                    // Set default browserSync port for Docker only
                    wConfig.browserSync = {port: 3010};
                    Webiny.saveConfig(wConfig);
                }
            } catch (err) {
                Webiny.failure(err.message, err);
                return;
            }

            if (docker) {
                Webiny.info('Initializing Docker containers...');
                // Run Docker containers so we can execute install scripts.
                Webiny.shellExecute('docker-compose up -d');
            }

            const php = docker ? 'docker-compose run php php' : 'php';

            // Run Webiny installation procedure
            Webiny.info('Running Webiny app installation...');
            Webiny.shellExecute(`${php} Apps/Webiny/Php/Cli/install.php Local Webiny`);

            // Create admin user
            const params = [answers.user, answers.password].join(' ');
            try {
                let output = Webiny.shellExecute(`${php} Apps/Webiny/Php/Cli/admin.php Local ${params}`, {stdio: 'pipe'});
                output = JSON.parse(output);
                if (output.status === 'created') {
                    Webiny.success('Admin user created successfully!');
                }

                if (output.status === 'failed') {
                    Webiny.exclamation(output.message);
                }
            } catch (err) {
                Webiny.failure(err.message);
            }

            // If Docker - we do not run nginx setup wizard
            if (docker) {
                return answers;
            }

            // Optionally create nginx config
            try {
                // Virtual host wizard
                const hostAnswers = {
                    domain: answers.domain
                };

                Webiny.shellExecute('nginx -v', {stdio: 'pipe'});
                return inquirer.prompt({
                    type: 'confirm',
                    name: 'createHost',
                    message: 'Would you like us to create a new nginx virtual host for you?',
                    default: true
                }).then(a => {
                    if (a.createHost) {
                        hostAnswers.createHost = true;
                        return inquirer.prompt({
                            type: 'input',
                            name: 'errorLogFile',
                            message: 'Where do you want to place your error log file (including file name)?',
                            default: function () {
                                const server = answers.domain.replace('http://', '').replace('https://', '').split(':')[0];
                                return '/var/log/nginx/' + server + '-error.log';
                            }
                        }).then(a => {
                            hostAnswers.errorLogFile = a.errorLogFile;
                            return setupVirtualHost(hostAnswers);
                        });
                    }
                    return answers;
                });
            } catch (err) {
                // Skip host prompts
            }
        });
    }
Example #4
0
module.exports = function (app) {
    // Construct URL for hot-reload and assets
    const port = _.get(Webiny.getConfig(), 'browserSync.port', 3000);
    const domain = _.get(Webiny.getConfig(), 'browserSync.domain', 'http://localhost');
    const url = domain + ':' + port;

    const name = app.getName();
    const context = Webiny.projectRoot(app.getSourceDir());
    const outputPath = path.resolve(Webiny.projectRoot(), 'public_html/build/development', app.getPath());
    const publicPath = url + '/build/development/' + app.getPath() + '/';

    const plugins = [
        new webpack.NamedModulesPlugin(),
        new ModuleIdsPlugin(),
        new ChunkIdsPlugin(),
        new webpack.NoEmitOnErrorsPlugin(),
        new webpack.DefinePlugin({
            'DEVELOPMENT': true,
            'PRODUCTION': false,
            'process.env': {
                'NODE_ENV': JSON.stringify(process.env.NODE_ENV)
            }
        }),
        new webpack.HotModuleReplacementPlugin(),
        new ExtractTextPlugin('app.css'),
        // Generate meta.json to use for app bootstrap based on generated assets
        new AssetsPlugin({
            manifestVariable: 'window["webinyConfig"]["Meta"]["' + name + '"].chunks'
        }),
        new Visualizer({filename: 'stats.html'})
    ];

    // Check if app has vendor DLL defined
    const dllPath = path.resolve(Webiny.projectRoot(), 'public_html/build/development', app.getPath(), 'vendor.manifest.json');
    if (Webiny.fileExists(dllPath)) {
        plugins.push(
            new webpack.DllReferencePlugin({
                context,
                manifest: require(dllPath)
            })
        );
    }

    if (name !== 'Webiny.Core') {
        plugins.push(
            new webpack.DllReferencePlugin({
                context: Webiny.projectRoot('Apps/Webiny/Js/Core'),
                manifest: Webiny.projectRoot('public_html/build/development') + '/Webiny_Core/vendor.manifest.json'
            })
        );
    }

    const fileExtensionRegex = /\.(png|jpg|gif|jpeg|mp4|mp3|woff2?|ttf|otf|eot|svg|ico)$/;

    return {
        name,
        cache: true,
        watch: false,
        context,
        entry: {
            app: [
                'react-hot-loader/patch',
                'webpack-hot-middleware/client?name=' + name + '&path=' + url + '/__webpack_hmr&quiet=false&noInfo=true&warn=false&overlay=true&reload=false',
                'webpack/hot/only-dev-server',
                './App.js'
            ]
        },
        output: {
            path: outputPath,
            filename: '[name].js',
            chunkFilename: 'chunks/[name].js',
            jsonpFunction: 'webpackJsonp' + app.getName().replace('.', ''),
            publicPath
        },
        plugins,
        externals: name === 'Webiny.Core' ? {} : require('./externals'),
        module: {
            rules: [
                {
                    test: /\.(js|jsx)$/,
                    exclude: /node_modules/,
                    use: [
                        {
                            loader: 'babel-loader',
                            options: {
                                presets: [
                                    [require.resolve('babel-preset-es2015')],
                                    require.resolve('babel-preset-react')
                                ],
                                plugins: [
                                    require.resolve('react-hot-loader/babel'),
                                    require.resolve('babel-plugin-transform-async-to-generator'),
                                    [require.resolve('babel-plugin-transform-object-rest-spread'), {'useBuiltIns': true}],
                                    [require.resolve('babel-plugin-syntax-dynamic-import')],
                                    [require.resolve('babel-plugin-lodash')],
                                    [require.resolve('babel-plugin-transform-builtin-extend'), {globals: ['Error']}],
                                    // This plugin is required to force all css/scss imports to have a resourceQuery
                                    [require.resolve('babel-plugin-transform-rename-import'), {
                                        original: '^(.*?\.s?css)$', replacement: '$1?',
                                    }]
                                ]
                            }
                        },
                        'hot-accept-loader'
                    ]
                },
                {
                    test: /\.(js|jsx)$/,
                    exclude: /node_modules/,
                    include: Webiny.projectRoot(),
                    use: 'i18n-loader'
                },
                require('./styles')(app),
                {
                    test: /node_modules/,
                    include: fileExtensionRegex,
                    loader: 'file-loader',
                    options: {
                        context: path.resolve(Webiny.projectRoot(), 'Apps', app.getAppName(), 'node_modules'),
                        name: 'external/[path][name].[ext]'
                    }
                },
                {
                    test: fileExtensionRegex,
                    exclude: /node_modules/,
                    loader: 'file-loader',
                    options: {
                        context: path.resolve(Webiny.projectRoot(), app.getSourceDir(), 'Assets'),
                        name: '[path][name].[ext]',
                        outputPath: (file) => {
                            if (file.startsWith('_/')) {
                                const parts = file.replace(/_\//g, '').split('/Assets/');
                                file = path.join('external', parts[0], parts[1]);
                            }
                            return file;
                        }
                    }
                }
            ]
        },
        resolve: require('./resolve')(app),
        resolveLoader: {
            modules: [
                __dirname + '/loaders', 'node_modules',
                path.resolve(Webiny.projectRoot(), 'Apps/Webiny/node_modules'),
                path.resolve(Webiny.projectRoot(), 'Apps/' + app.getAppName() + '/node_modules')
            ]
        }
    }
};