<commit_before>let Docker = require('dockerode'),
    through2 = require('through2'),
    inquirer = require('inquirer'),
    path = require('path'),
    mkdirp = require('mkdirp'),
    log = require('npmlog');

let DockerImages = require('./docker-images');
let DockerNetwork = require('./docker-network');
let Utils = require('./utils');

let docker = new Docker();

const LOG_PREFIX = 'eth-devnet/docker-ps';
const CONTAINER_PREFIX = 'eth-devnet_';

const CLIENTS = [ 'parity' ];

const DEFAULTS = {
    nodes: 3,
    miners: 1,
    client: 'parity'
};

module.exports = class DockerPs {

    static getLogs(container) {
        const stream = require('stream');

        let cont = docker.getContainer(container.Id);

        return new Promise((resolve, reject) => {
            cont.logs({ stdout: 1, stderr: 1, timestamps: 1 }, (err, response) => {
                if (err) return reject(err);

                var stdout = new stream.PassThrough();
                var stderr = new stream.PassThrough();
                cont.modem.demuxStream(response, stdout, stderr);

                let logs = {
                    stdout: '',
                    stderr: ''
                };

                stdout
                    .on('data', chunk => {
                        logs.stdout += chunk;
                    });

                stderr
                    .on('data', chunk => {
                        logs.stderr += chunk;
                    });

                response
                    .on('end', () => {
                        let regex = /^([0-9\-]+T[0-9:\.]+Z) (.+)$/i;

                        let out = logs.stdout
                            .split('\n')
                            .filter(l => regex.test(l))
                            .map(l => {
                                let regres = regex.exec(l);

                                return {
                                    time: new Date(regres[1]),
                                    log: regres[2],
                                    from: 'stdout'
                                };
                            });

                        let err = logs.stderr
                            .split('\n')
                            .filter(l => regex.test(l))
                            .map(l => {
                                let regres = regex.exec(l);

                                return {
                                    time: new Date(regres[1]),
                                    log: regres[2],
                                    from: 'stderr'
                                };
                            });

                        let sorted = []
                            .concat(out, err)
                            .sort((a, b) => a.time - b.time);

                        resolve(sorted);
                    });
            });
        });
    }

    static start(config) {
        let nodes = config.nodes !== undefined ? config.nodes : DEFAULTS.nodes,
            miners = config.miners !== undefined ? config.miners : DEFAULTS.miners,
            client = config.client !== undefined ? config.client : DEFAULTS.client;

        if (!(nodes >= 1 && nodes <= 7)) {
            log.error(LOG_PREFIX, 'The number of nodes must be between 1 and 7' `(${nodes} given)`);
            process.exit(1);
        }

        if (!(miners >= 1 && miners <= 5)) {
            log.error(LOG_PREFIX, 'The number of miners must be between 1 and 5', `(${miners} given)`);
            process.exit(1);
        }

        if (CLIENTS.indexOf(client) === -1) {
            log.error(LOG_PREFIX, 'The client should be one of this list: ' + CLIENTS.join(', '), `("${client}" given)`);
            process.exit(1);
        }

        let images = DockerImages.getImages();
        let nodeImage = images.find(i => i.name === client);
        let minerImage = images.find(i => i.name === 'ethminer');

        let nodeCmd = nodeImage.meta.Cmd || [];

        let ips = [];
        let nodeUris = [];

        let parityDir = path.resolve(Utils.appDir + '/.parity');
        let ethashDir = path.resolve(Utils.appDir + '/.ethash');

        mkdirp.sync(parityDir);
        mkdirp.sync(ethashDir);

        // Start first Node after CleanUp
        return DockerPs
            .cleanUp()
            .then(() => (require('./accounts')).list())
            .then(accounts => {
                return inquirer.prompt({
                    type: 'list',
                    name: 'address',
                    message: 'Choose an author address for mining',
                    choices: accounts
                });
            })
            .then(answer => {
                nodeCmd = [].concat(nodeCmd, [ '--author', answer.address ]);
            })
            .then(() => DockerNetwork.getIpAddress())
            .then(ip => {
                log.info(LOG_PREFIX, 'starting the first node with ip ' + ip);

                ips.push(ip);

                return DockerPs
                    .startContainer(ip, {
                        Image: nodeImage.tag,
                        Cmd: [].concat(
                            nodeCmd,
                            [
                                '-d', '/parity',
                                '--jsonrpc-interface', `${ip}`
                            ]
                        ),
                        HostConfig: {
                            Binds: [ `${parityDir}:/parity` ]
                        },
                        name: CONTAINER_PREFIX + nodeImage.name + '.0'
                    });
            })
            .then(container => {
                let p = Promise.resolve(container);

                // Start all nodes
                for (let i = 2; i <= nodes; i++) {
                    p = p
                        .then(container => DockerPs.getNodeURI(container))
                        .then(uri => nodeUris.push(uri))
                        .then(() => DockerNetwork.getIpAddress())
                        .then(ip => {
                            log.info(LOG_PREFIX, 'starting node #' + i);

                            ips.push(ip);

                            return DockerPs
                                .startContainer(ip, {
                                    Image: nodeImage.tag,
                                    Cmd: [].concat(
                                        nodeCmd,
                                        [
                                            '--jsonrpc-interface', `${ip}`,
                                            '--bootnodes', nodeUris.join(',')
                                        ]
                                    ),
                                    HostConfig: {
                                        Binds: []
                                    },
                                    name: CONTAINER_PREFIX + nodeImage.name + '.' + ( i-1 )
                                });
                        });
                }

                return p;
            })
            .then(() => {
                let p = Promise.resolve();

                // Start all miners
                for (let i = 1; i <= miners; i++) {
                    p = p
                        .then(() => DockerNetwork.getIpAddress())
                        .then(ip => {
                            // Start the miner
                            log.info(LOG_PREFIX, `starting the miner #${i}`);

                            let nodeIpIdx = Math.floor(Math.random() * ips.length);
                            let nodeIp = ips.splice(nodeIpIdx, 1)[0];

                            return DockerPs
                                .startContainer(ip, {
                                    Image: minerImage.tag,
                                    User: 'ubuntu',
                                    Cmd: [
                                        '-C', '-t', '1',
                                        '-F', nodeIp + ':8545'
                                    ],
                                    HostConfig: {
                                        CpuPeriod: 100000,
                                        CpuQuota: 25000,
                                        Binds: [ `${ethashDir}:/home/ubuntu/.ethash` ]
                                    },
                                    name: CONTAINER_PREFIX + minerImage.name + '.' + i
                                });
                        });
                }

                return p;
            });

    }

    static cleanUp() {
        log.info(LOG_PREFIX, 'cleaning-up docker containers');

        return new Promise((resolve, reject) => {
            docker.listContainers({ all: true }, (err, containers) => {
                if (err) return reject(err);

                let toRemove = [];
                let regex = new RegExp(CONTAINER_PREFIX, 'i');

                containers.forEach((info) => {
                    if (regex.test(info.Names[0])) {
                        toRemove.push(docker.getContainer(info.Id));
                    }
                });

                Promise
                    .all(toRemove.map(c => DockerPs.removeContainer(c)))
                    .then(resolve)
                    .catch(reject);
            });
        });
    }

    static removeContainer(container) {
        return new Promise((resolve, reject) => {
            container.stop(err => {
                // Error 304 = already stopped
                if (err && err.statusCode !== 304 && err.statusCode !== 404) {
                    return reject(err);
                }

                container.remove(err => {
                    // If the container doesn't exist, that's ok
                    if (err && err.statusCode !== 404) return reject(err);
                    return resolve();
                });
            });
        });
    }

    static startContainer(ip, config) {
        log.info(
            LOG_PREFIX,
            'starting container', config.name,
            'with params', config.Cmd.join(' ')
        );

        return new Promise((resolve, reject) => {
            let networkName = DockerNetwork.getName();

            let netobj = { EndpointsConfig: {} };

            netobj.EndpointsConfig[networkName] = {
                IPAMConfig: {
                    IPv4Address: ip
                }
            };

            config.NetworkingConfig = netobj;
            config.HostConfig.NetworkMode = networkName;

            docker.createContainer(config, (err, container) => {
                if (err) return reject(err);

                container.start(err => {
                    if (err) return reject(err);

                    resolve(container);
                });
            });
        });
    }

    /**
     * Get the running eth-devnet Docker containers
     *
     * @return {Promise}
     */
    static getContainers() {
        return new Promise((resolve, reject) => {
            docker.listContainers({ all: true }, (err, containers) => {
                if (err) return reject(err);

                let regex = new RegExp(CONTAINER_PREFIX, 'i');

                let cts = containers.filter(c => regex.test(c.Names[0]));

                let nodes = cts.filter(c => !/miner/i.test(c.Names[0]));
                let miners = cts.filter(c => /miner/i.test(c.Names[0]));

                return resolve({
                    nodes, miners
                });
            });
        });
    }

    static getNodeURI(container) {
        let regex = new RegExp('enode://[0-9a-zA-e]+@[0-9\.]+:[0-9]+', 'i');
        let foundURI = false;

        return new Promise((resolve, reject) => {
            container.logs({ stdout: 1, stderr: 1 }, (err, response) => {
                if (err) return reject(err);

                response
                    .pipe(through2((chunk, enc, cb) => {
                        let log = chunk.toString();

                        if (regex.test(log)) {
                            let uri = regex.exec(log)[0];
                            foundURI = true;
                            return resolve(uri);
                        }

                        cb();
                    }))
                    .on('finish', () => {
                        if (foundURI) return true;

                        // Schedule another log attempt in 500ms
                        setTimeout(() => {
                            DockerPs
                                .getNodeURI(container)
                                .then(resolve)
                                .catch(reject);
                        }, 500);
                    })
                    .on('error', err => {
                        return reject(err);
                    });
            });
        });
    }

};
<commit_msg>Miners a la suite<commit_after>let Docker = require('dockerode'),
    through2 = require('through2'),
    inquirer = require('inquirer'),
    path = require('path'),
    mkdirp = require('mkdirp'),
    log = require('npmlog');

let DockerImages = require('./docker-images');
let DockerNetwork = require('./docker-network');
let Utils = require('./utils');

let docker = new Docker();

const LOG_PREFIX = 'eth-devnet/docker-ps';
const CONTAINER_PREFIX = 'eth-devnet_';

const CLIENTS = [ 'parity' ];

const DEFAULTS = {
    nodes: 3,
    miners: 1,
    client: 'parity'
};

module.exports = class DockerPs {

    static getLogs(container) {
        const stream = require('stream');

        let cont = docker.getContainer(container.Id);

        return new Promise((resolve, reject) => {
            cont.logs({ stdout: 1, stderr: 1, timestamps: 1 }, (err, response) => {
                if (err) return reject(err);

                var stdout = new stream.PassThrough();
                var stderr = new stream.PassThrough();
                cont.modem.demuxStream(response, stdout, stderr);

                let logs = {
                    stdout: '',
                    stderr: ''
                };

                stdout
                    .on('data', chunk => {
                        logs.stdout += chunk;
                    });

                stderr
                    .on('data', chunk => {
                        logs.stderr += chunk;
                    });

                response
                    .on('end', () => {
                        let regex = /^([0-9\-]+T[0-9:\.]+Z) (.+)$/i;

                        let out = logs.stdout
                            .split('\n')
                            .filter(l => regex.test(l))
                            .map(l => {
                                let regres = regex.exec(l);

                                return {
                                    time: new Date(regres[1]),
                                    log: regres[2],
                                    from: 'stdout'
                                };
                            });

                        let err = logs.stderr
                            .split('\n')
                            .filter(l => regex.test(l))
                            .map(l => {
                                let regres = regex.exec(l);

                                return {
                                    time: new Date(regres[1]),
                                    log: regres[2],
                                    from: 'stderr'
                                };
                            });

                        let sorted = []
                            .concat(out, err)
                            .sort((a, b) => a.time - b.time);

                        resolve(sorted);
                    });
            });
        });
    }

    static start(config) {
        let nodes = config.nodes !== undefined ? config.nodes : DEFAULTS.nodes,
            miners = config.miners !== undefined ? config.miners : DEFAULTS.miners,
            client = config.client !== undefined ? config.client : DEFAULTS.client;

        if (!(nodes >= 1 && nodes <= 7)) {
            log.error(LOG_PREFIX, 'The number of nodes must be between 1 and 7' `(${nodes} given)`);
            process.exit(1);
        }

        if (!(miners >= 1 && miners <= 5)) {
            log.error(LOG_PREFIX, 'The number of miners must be between 1 and 5', `(${miners} given)`);
            process.exit(1);
        }

        if (CLIENTS.indexOf(client) === -1) {
            log.error(LOG_PREFIX, 'The client should be one of this list: ' + CLIENTS.join(', '), `("${client}" given)`);
            process.exit(1);
        }

        let images = DockerImages.getImages();
        let nodeImage = images.find(i => i.name === client);
        let minerImage = images.find(i => i.name === 'ethminer');

        let nodeCmd = nodeImage.meta.Cmd || [];

        let ips = [];
        let nodeUris = [];

        let parityDir = path.resolve(Utils.appDir + '/.parity');
        let ethashDir = path.resolve(Utils.appDir + '/.ethash');

        mkdirp.sync(parityDir);
        mkdirp.sync(ethashDir);

        // Start first Node after CleanUp
        return DockerPs
            .cleanUp()
            .then(() => (require('./accounts')).list())
            .then(accounts => {
                return inquirer.prompt({
                    type: 'list',
                    name: 'address',
                    message: 'Choose an author address for mining',
                    choices: accounts
                });
            })
            .then(answer => {
                nodeCmd = [].concat(nodeCmd, [ '--author', answer.address ]);
            })
            .then(() => DockerNetwork.getIpAddress())
            .then(ip => {
                log.info(LOG_PREFIX, 'starting the first node with ip ' + ip);

                ips.push(ip);

                return DockerPs
                    .startContainer(ip, {
                        Image: nodeImage.tag,
                        Cmd: [].concat(
                            nodeCmd,
                            [
                                '-d', '/parity',
                                '--jsonrpc-interface', `${ip}`
                            ]
                        ),
                        HostConfig: {
                            Binds: [ `${parityDir}:/parity` ]
                        },
                        name: CONTAINER_PREFIX + nodeImage.name + '.0'
                    });
            })
            .then(container => {
                let p = Promise.resolve(container);

                // Start all nodes
                for (let i = 2; i <= nodes; i++) {
                    p = p
                        .then(container => DockerPs.getNodeURI(container))
                        .then(uri => nodeUris.push(uri))
                        .then(() => DockerNetwork.getIpAddress())
                        .then(ip => {
                            log.info(LOG_PREFIX, 'starting node #' + i);

                            ips.push(ip);

                            return DockerPs
                                .startContainer(ip, {
                                    Image: nodeImage.tag,
                                    Cmd: [].concat(
                                        nodeCmd,
                                        [
                                            '--jsonrpc-interface', `${ip}`,
                                            '--bootnodes', nodeUris.join(',')
                                        ]
                                    ),
                                    HostConfig: {
                                        Binds: []
                                    },
                                    name: CONTAINER_PREFIX + nodeImage.name + '.' + ( i-1 )
                                });
                        });
                }

                return p;
            })
            .then(() => {
                let p = Promise.resolve();

                // Start all miners
                for (let i = 1; i <= miners; i++) {
                    p = p
                        .then(() => DockerNetwork.getIpAddress())
                        .then(ip => {
                            // Start the miner
                            log.info(LOG_PREFIX, `starting the miner #${i}`);

                            let nodeIp = ips.splice(0, 1)[0];

                            return DockerPs
                                .startContainer(ip, {
                                    Image: minerImage.tag,
                                    User: 'ubuntu',
                                    Cmd: [
                                        '-C', '-t', '1',
                                        '-F', nodeIp + ':8545'
                                    ],
                                    HostConfig: {
                                        CpuPeriod: 100000,
                                        CpuQuota: 25000,
                                        Binds: [ `${ethashDir}:/home/ubuntu/.ethash` ]
                                    },
                                    name: CONTAINER_PREFIX + minerImage.name + '.' + i
                                });
                        });
                }

                return p;
            });

    }

    static cleanUp() {
        log.info(LOG_PREFIX, 'cleaning-up docker containers');

        return new Promise((resolve, reject) => {
            docker.listContainers({ all: true }, (err, containers) => {
                if (err) return reject(err);

                let toRemove = [];
                let regex = new RegExp(CONTAINER_PREFIX, 'i');

                containers.forEach((info) => {
                    if (regex.test(info.Names[0])) {
                        toRemove.push(docker.getContainer(info.Id));
                    }
                });

                Promise
                    .all(toRemove.map(c => DockerPs.removeContainer(c)))
                    .then(resolve)
                    .catch(reject);
            });
        });
    }

    static removeContainer(container) {
        return new Promise((resolve, reject) => {
            container.stop(err => {
                // Error 304 = already stopped
                if (err && err.statusCode !== 304 && err.statusCode !== 404) {
                    return reject(err);
                }

                container.remove(err => {
                    // If the container doesn't exist, that's ok
                    if (err && err.statusCode !== 404) return reject(err);
                    return resolve();
                });
            });
        });
    }

    static startContainer(ip, config) {
        log.info(
            LOG_PREFIX,
            'starting container', config.name,
            'with params', config.Cmd.join(' ')
        );

        return new Promise((resolve, reject) => {
            let networkName = DockerNetwork.getName();

            let netobj = { EndpointsConfig: {} };

            netobj.EndpointsConfig[networkName] = {
                IPAMConfig: {
                    IPv4Address: ip
                }
            };

            config.NetworkingConfig = netobj;
            config.HostConfig.NetworkMode = networkName;

            docker.createContainer(config, (err, container) => {
                if (err) return reject(err);

                container.start(err => {
                    if (err) return reject(err);

                    resolve(container);
                });
            });
        });
    }

    /**
     * Get the running eth-devnet Docker containers
     *
     * @return {Promise}
     */
    static getContainers() {
        return new Promise((resolve, reject) => {
            docker.listContainers({ all: true }, (err, containers) => {
                if (err) return reject(err);

                let regex = new RegExp(CONTAINER_PREFIX, 'i');

                let cts = containers.filter(c => regex.test(c.Names[0]));

                let nodes = cts.filter(c => !/miner/i.test(c.Names[0]));
                let miners = cts.filter(c => /miner/i.test(c.Names[0]));

                return resolve({
                    nodes, miners
                });
            });
        });
    }

    static getNodeURI(container) {
        let regex = new RegExp('enode://[0-9a-zA-e]+@[0-9\.]+:[0-9]+', 'i');
        let foundURI = false;

        return new Promise((resolve, reject) => {
            container.logs({ stdout: 1, stderr: 1 }, (err, response) => {
                if (err) return reject(err);

                response
                    .pipe(through2((chunk, enc, cb) => {
                        let log = chunk.toString();

                        if (regex.test(log)) {
                            let uri = regex.exec(log)[0];
                            foundURI = true;
                            return resolve(uri);
                        }

                        cb();
                    }))
                    .on('finish', () => {
                        if (foundURI) return true;

                        // Schedule another log attempt in 500ms
                        setTimeout(() => {
                            DockerPs
                                .getNodeURI(container)
                                .then(resolve)
                                .catch(reject);
                        }, 500);
                    })
                    .on('error', err => {
                        return reject(err);
                    });
            });
        });
    }

};
<|endoftext|>


<commit_before>const moment = require('moment');
const uuid = require('uuid');
const Boom = require('boom');
const _ = require('lodash');

module.exports = {
    parse: parse
};

function parse(req, err) {
    let error;
    let statusCode = 500;
    let message = null;
    let data = {};

    // todo: 401 errors are handled differently from other errors, will need to cater for that specific case

    if (err instanceof Error) {
        if (!err.isBoom) {
            error = Boom.wrap(err, statusCode, message);
            error.stack = err.stack;
        } else {
            error = err;
        }

        if (typeof error.data === 'object') {
            data = error.data;
        } else if (typeof error.data === 'string') {
            data = {
                message: error.data
            };
        }
    } else {
        if (typeof err === 'object' && (_.has(err, 'statusCode') || _.has(err, 'status')) && _.has(err, 'message')) {
            statusCode = err.statusCode || err.status;
            message = err.message;
            if (_.has(err, 'data')) {
                if (typeof err.data === 'object') {
                    data = err.data;
                } else if (typeof err.data === 'string') {
                    data = {
                        message: err.data
                    };
                }
            }
        } else {
            data = err;
        }

        error = Boom.create(statusCode, message, data);

        if (typeof err === 'object' && _.has(err, 'stack')) {
            error.stack = err.stack;
        } else {
            error.stack = null;
        }
    }

    // todo: Added more information to the error object. (eg. url, user)

    const output = {
        statusCode: error.output.payload.statusCode,
        error: error.output.payload.error,
        message: error.output.payload.message,
        timestamp: moment.utc().toISOString(),
        data: data,
        stack: null,
        request: {
            reference: req.reference || uuid.v4(),
            method: req.method,
            url: req.originalUrl,
            query: req.query,
            body: req.body
        }
    };

    if (error.hasOwnProperty('stack')) {
        if (!req.hasOwnProperty('error')) {
            output.stack = error.stack;
        } else if (req.hasOwnProperty('error') && req.error.includeStack === true) {
            output.stack = error.stack;
        }
    }

    return output;
}
<commit_msg>Updated error handling for 401 responses<commit_after>const moment = require('moment');
const uuid = require('uuid');
const Boom = require('boom');
const _ = require('lodash');

module.exports = {
    parse: parse
};

function parse(req, err) {
    let error = {};
    let statusCode = 500;
    let message = null;
    let data = {};

    // todo: 401 errors are handled differently from other errors, will need to cater for that specific case
    // todo: add a "code" field onto the error object to differentiate errors with the same status

    if (err instanceof Error) {
        if (!err.isBoom) {
            if (_.has(err, 'statusCode') || _.has(err, 'status')) {
                statusCode = err.statusCode || err.status;
            }
            if (_.has(err, 'message') && typeof err.message === 'string') {
                message = err.message;
            }

            if (statusCode === 401) {
                error = Boom.unauthorized(message);
            } else {
                error = Boom.wrap(err, statusCode, message);
            }
            error.stack = err.stack;
        } else {
            error = err;
        }

        if (typeof error.data === 'object') {
            data = error.data;
        } else if (typeof error.data === 'string') {
            data = {
                message: error.data
            };
        }
    } else {
        if (typeof err === 'object' && (_.has(err, 'statusCode') || _.has(err, 'status')) && _.has(err, 'message')) {
            statusCode = err.statusCode || err.status;
            message = err.message;
            if (_.has(err, 'data')) {
                if (typeof err.data === 'object') {
                    data = err.data;
                } else if (typeof err.data === 'string') {
                    data = {
                        message: err.data
                    };
                }
            }
        } else {
            data = err;
        }

        error = Boom.create(statusCode, message, data);

        if (typeof err === 'object' && _.has(err, 'stack')) {
            error.stack = err.stack;
        } else {
            error.stack = null;
        }
    }

    // todo: Added more information to the error object. (eg. url, user)

    const output = {
        statusCode: error.output.payload.statusCode,
        error: error.output.payload.error,
        message: error.output.payload.message,
        timestamp: moment.utc().toISOString(),
        data: data,
        stack: null,
        request: {
            reference: req.reference || uuid.v4(),
            method: req.method,
            url: req.originalUrl,
            query: req.query,
            body: req.body
        }
    };

    if (error.hasOwnProperty('stack')) {
        if (!req.hasOwnProperty('error')) {
            output.stack = error.stack;
        } else if (req.hasOwnProperty('error') && req.error.includeStack === true) {
            output.stack = error.stack;
        }
    }

    return output;
}
<|endoftext|>


<commit_before>function duplicate(listName, query, keystone, user, parent) {
  return new Promise(function(resolve, reject) {
    var list = keystone.list(listName);
    list.model.find(query, function (error, items) {
      if (error) {
        reject(error);
      } else {
        if (!items) resolve();
        let itemPromises = [];
        items.forEach(function(item) {
          itemPromises.push(new Promise(function(_resolve, _reject) {
            var duplicated = new list.model();
            if (item.name) {
              item.name = item.name + " duplicate";
            }
            if (item.slug) {
              item.slug = item.slug + "-duplicate";
            }
            if (item.uuid) {
              item.uuid = null;
            }
            if (parent) {
              item[parent.name] = parent.id
            }
            list.updateItem(duplicated, item, {
              ignoreNoEdit: true,
              user: user,
            }, function (error) {
              if (error) {
                _reject(error);
              } else {
                let obj = list.getData(duplicated);

                let relPromises = [];
                Object.values(list.relationships).forEach(function (rel) {
                  let parent = {
                    name: rel.refPath,
                    id: obj.id
                  }
                  relPromises.push(duplicate(rel.ref, {[rel.refPath]: item.id}, keystone, user, parent))
                });

                Promise.all(relPromises).then(function(result) {
                  _resolve(obj);
                }).catch(function(error) {
                  _reject(error);
                });
              }
            });
          }));
        });
        Promise.all(itemPromises).then(function(object) {
          resolve(object[0]);
        }).catch((function(error) {
          reject(error);
        }));
      }
    });
  });
}

module.exports = function (req, res) {
  var keystone = req.keystone;
  if (!keystone.security.csrf.validate(req)) {
    return res.apiError(403, 'invalid csrf');
  }

  duplicate(req.list.model.modelName, {'_id': req.params.id}, req.keystone, req.user, null).then(function(result) {
    res.json(result);
  }).catch(function(error) {
    var status = error.error === 'validation errors' ? 400 : 500;
    var error = error.error === 'database error' ? error.detail : error;
    res.apiError(status, error);
  });
};
<commit_msg>default isMonetized to false in duplicate button<commit_after>function duplicate(listName, query, keystone, user, parent) {
  return new Promise(function(resolve, reject) {
    var list = keystone.list(listName);
    list.model.find(query, function (error, items) {
      if (error) {
        reject(error);
      } else {
        if (!items) resolve();
        let itemPromises = [];
        items.forEach(function(item) {
          itemPromises.push(new Promise(function(_resolve, _reject) {
            var duplicated = new list.model();
            if (item.name) {
              item.name = item.name + " duplicate";
            }
            if (item.slug) {
              item.slug = item.slug + "-duplicate";
            }
            if (item.uuid) {
              item.uuid = null;
            }
            if (item.isMonetized) {
              item.isMonetized = false;
            }
            if (parent) {
              item[parent.name] = parent.id
            }
            list.updateItem(duplicated, item, {
              ignoreNoEdit: true,
              user: user,
            }, function (error) {
              if (error) {
                _reject(error);
              } else {
                let obj = list.getData(duplicated);

                let relPromises = [];
                Object.values(list.relationships).forEach(function (rel) {
                  let parent = {
                    name: rel.refPath,
                    id: obj.id
                  }
                  relPromises.push(duplicate(rel.ref, {[rel.refPath]: item.id}, keystone, user, parent))
                });

                Promise.all(relPromises).then(function(result) {
                  _resolve(obj);
                }).catch(function(error) {
                  _reject(error);
                });
              }
            });
          }));
        });
        Promise.all(itemPromises).then(function(object) {
          resolve(object[0]);
        }).catch((function(error) {
          reject(error);
        }));
      }
    });
  });
}

module.exports = function (req, res) {
  var keystone = req.keystone;
  if (!keystone.security.csrf.validate(req)) {
    return res.apiError(403, 'invalid csrf');
  }

  duplicate(req.list.model.modelName, {'_id': req.params.id}, req.keystone, req.user, null).then(function(result) {
    res.json(result);
  }).catch(function(error) {
    var status = error.error === 'validation errors' ? 400 : 500;
    var error = error.error === 'database error' ? error.detail : error;
    res.apiError(status, error);
  });
};
<|endoftext|>


<commit_before>var fs = require('fs'),
    path = require('path'),
    nssocket = require('nssocket'),
    forever = require('../forever');

function findSocket(sockPath, startAt, callback) {
  if (typeof startAt == "function") {
    callback = startAt;
    startAt = null;
  }

  startAt || (startAt = 0);
  var sock = path.join(sockPath, 'worker.' + startAt + '.sock');
  fs.stat(sock, function (err, stat) {
    if (err) {
      if (err.code == 'ENOENT') {
        return callback(null, sock)
      }
      return callback(err);
    }
    return findSocket(sockPath, ++startAt, callback);
  });
}

var Worker = exports.Worker = function (options) {
  options || (options = {});

  this.monitor  = options.monitor;
  this.sockPath = options.sockPath || forever.config.get('sockPath');

  this._socket = null;
};

Worker.prototype.start = function (cb) {
  var self = this;

  if (this._socket) throw new Error("Can't start already started worker");

  self._socket = nssocket.createServer(function (socket) {
    socket.data(['ping'], function () {
      socket.send(['pong']);
    });

    socket.data(['data'], function () {
      socket.send(['data'], self.monitor.data);
    });
  });

  findSocket(self.sockPath, function (err, sock) {
    if (err) {
      return cb && cb(err);
    }
    self._socket.listen(sock, function () {
      //
      // `listening` listener doesn't take error as the first parameter
      //
      cb && cb(null, sock);

      //
      // If we're a fork, notify master that server is set up and waiting for
      // commands.
      //
      process.send && process.send('listening', sock);
    });
  });
};

<commit_msg>[api] Worker `spawn` command<commit_after>var fs = require('fs'),
    path = require('path'),
    nssocket = require('nssocket'),
    forever = require('../forever');

function findSocket(sockPath, startAt, callback) {
  if (typeof startAt == "function") {
    callback = startAt;
    startAt = null;
  }

  startAt || (startAt = 0);
  var sock = path.join(sockPath, 'worker.' + startAt + '.sock');
  fs.stat(sock, function (err, stat) {
    if (err) {
      if (err.code == 'ENOENT') {
        return callback(null, sock)
      }
      return callback(err);
    }
    return findSocket(sockPath, ++startAt, callback);
  });
}

var Worker = exports.Worker = function (options) {
  options || (options = {});

  this.monitor  = options.monitor;
  this.sockPath = options.sockPath || forever.config.get('sockPath');

  this._socket = null;
};

Worker.prototype.start = function (cb) {
  var self = this;

  if (this._socket) throw new Error("Can't start already started worker");

  self._socket = nssocket.createServer(function (socket) {
    socket.data(['ping'], function () {
      socket.send(['pong']);
    });

    socket.data(['data'], function () {
      socket.send(['data'], self.monitor.data);
    });

    socket.data(['spawn'], function (data) {
      if (!data.script) {
        return socket.send(['spawn', 'error'], { error: new Error('No script given') });
      }

      if (this.monitor) {
        return socket.send(['spawn', 'error'], { error: new Error("Already running") });
      }

      var monitor = new (forever.Monitor)(data.script, data.options);
      monitor.start();

      monitor.on('start', function () {
        socket.send(['spawn', 'start']);
      });
    });
  });

  findSocket(self.sockPath, function (err, sock) {
    if (err) {
      return cb && cb(err);
    }
    self._socket.listen(sock, function () {
      //
      // `listening` listener doesn't take error as the first parameter
      //
      cb && cb(null, sock);

      //
      // If we're a fork, notify master that server is set up and waiting for
      // commands.
      //
      process.send && process.send('listening', sock);
    });
  });
};

<|endoftext|>


<commit_before>import {
  FrontSide,
  BackSide,
  DoubleSide,

  SmoothShading,
  FlatShading,

  NoBlending,
  NormalBlending,
  AdditiveBlending,
  SubtractiveBlending,
  MultiplyBlending,
  CustomBlending,

  NeverDepth,
  AlwaysDepth,
  LessDepth,
  LessEqualDepth,
  GreaterEqualDepth,
  GreaterDepth,
  NotEqualDepth
} from 'three';

export default {
  any: {
    side: {FrontSide, BackSide, DoubleSide},
    shading: {SmoothShading, FlatShading},
    blending: {
      NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending
    },
    depthFunc: {
      NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth
    }
  },
  MeshBasicMaterial: {
    color: 'color',
    lights: 'boolean'
  },
  MeshLambertMaterial: {
    color: 'color'
  }
  // To be continued...
}
<commit_msg>Extend changable material properties<commit_after>import {
  FrontSide,
  BackSide,
  DoubleSide,

  SmoothShading,
  FlatShading,

  NoBlending,
  NormalBlending,
  AdditiveBlending,
  SubtractiveBlending,
  MultiplyBlending,
  CustomBlending,

  NeverDepth,
  AlwaysDepth,
  LessDepth,
  LessEqualDepth,
  GreaterEqualDepth,
  GreaterDepth,
  NotEqualDepth
} from 'three';

const additional = {
  wireframe: {
    wireframe: 'boolean',
    wireframeLinecap: ['butt', 'round', 'square'],
    wireframeLinejoin: ['round', 'bevel', 'miter'],
    wireframeLinewidth: 'number'
  },

  refr: {
    reflectivity: 'number',
    refractionRatio: 'number'
  },

  light: {
    lightMap: 'texture',
    lightMapIntensity: 'number'
  },

  displacement: {
    displacementScale: 'number',
    displacementBias: 'number',
    displacementMap: 'texture'
  },

  emissive: {
    emissive: 'color',
    emissiveMap: 'texture',
    emissiveIntensity: 'number'
  }
}

const add = (origin, ...addv) => {
  console.log(addv.map(value => additional[value]));
  return Object.assign(origin, ...addv.map(value => additional[value]))
}

export default {
  any: add({
    side: {FrontSide, BackSide, DoubleSide},
    shading: {SmoothShading, FlatShading},
    blending: {
      NoBlending, NormalBlending, AdditiveBlending, SubtractiveBlending, MultiplyBlending, CustomBlending
    },
    depthFunc: {
      NeverDepth, AlwaysDepth, LessDepth, LessEqualDepth, GreaterEqualDepth, GreaterDepth, NotEqualDepth
    }
  }, 'wireframe'),

  MeshBasicMaterial: {
    color: 'color',
    lights: 'boolean',
    linewidth: 'number',
    linecap: ['butt', 'round', 'square'],
    linejoin: ['round', 'bevel', 'miter']
  },

  MeshLambertMaterial: add({
    color: 'color'
  }, 'emissive', 'refr', 'light'),

  MeshPhongMaterial: add({

  }, 'displacement', 'emissive'),

  MeshDepthMaterial: {

  }
  // To be continued...
}
<|endoftext|>


<commit_before>/* global describe, before, beforeEach, after, it, browser */

import KeysAsserts from '../../KeysAsserts';
import KeysPageObject from '../../utils/KeysPageObject';
import selectors from '../../selectors/keySelectors';

describe('partition key', () => {
  const keysPageObject = new KeysPageObject(browser);
  const keysAsserts = new KeysAsserts(keysPageObject, browser);

  const testFolder = KeysPageObject.TEST_KEYS_FOLDER;
  const partitionsTestFolder = '@partitions';

  beforeEach(() => {
    browser.refresh();
    browser.acceptAlertIfPresent();
    keysPageObject.waitForKeyToLoad()
  });

  describe('add partition', () => {
    before(() => {
      browser.windowHandleMaximize();
    });

    describe('invalid partitions', () => {
      const emptyRulesKeyFullPath = `${testFolder}/${partitionsTestFolder}/empty_partition`;
      before(() => {
        keysPageObject.goToKey(emptyRulesKeyFullPath);
      });

      it('should not allow invalid properties', () => {
        keysPageObject.addPartitionFromProperty('someInvalidValue');
        browser.waitForVisible(selectors.ALERT_OK_BUTTON, 1000);
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000, true);
      });

      it('should not allow duplicate properties', () => {
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.waitForVisible(selectors.ALERT_OK_BUTTON, 1000, true);
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.waitForVisible(selectors.ALERT_OK_BUTTON, 1000);
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000, true);
      });
    });

    describe('valid partitions', () => {
      const addPartitionKeyFullPath = `${testFolder}/${partitionsTestFolder}/add_partition`;
      before(() => {
        keysPageObject.goToKey(addPartitionKeyFullPath);
      });

      it('should not partition if canceled', () => {
        const keySource = keysPageObject.getKeySource();
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000);
        browser.click(selectors.ALERT_CANCEL_BUTTON);
        keysAsserts.assertKeySource(keySource);
      });

      it('should auto-partition correctly if auto-partition was selected', () => {
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.clickWhenVisible(selectors.AUTO_PARTITION_BUTTON, 1000);
        keysAsserts.assertKeySource({
          partitions: ["user.FavoriteFruit"],
          valueType: "string",
          rules: {
            "*": [
              {
                Matcher: {
                  "user.AgentVersion": {
                    "$ge": "0.12.3",
                    "$compare": "version"
                  }
                },
                Value: "agentValue",
                Type: "SingleVariant"
              },
              {
                Matcher: {"user.Gender": "female"},
                Value: "femaleValue",
                Type: "SingleVariant"
              },
              {
                Matcher: {},
                Value: "defaultValue",
                Type: "SingleVariant"
              }
            ],
            "Apple": [
              {
                Matcher: {},
                Value: "appleValue",
                Type: "SingleVariant"
              }
            ]
          }
        });
      });

      it('should not allow auto-partition if matcher is invalid', () => {
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000);
        browser.waitForVisible(selectors.AUTO_PARTITION_BUTTON, 1000, false);

        browser.waitForVisible(selectors.RESET_PARTITIONS_BUTTON, 1000);
        browser.click(selectors.RESET_PARTITIONS_BUTTON);
        keysAsserts.assertKeySource({
          partitions: ["user.FavoriteFruit"],
          valueType: "string",
          rules: {}
        });
      });
    });
  });

  describe('delete partition', () => {
    const deletePartitionKeyFullPath = `${testFolder}/${partitionsTestFolder}/delete_partition`;
    before(() => {
      keysPageObject.goToKey(deletePartitionKeyFullPath);
    });

    it('should clear rules after partition is deleted', () => {
      browser.click(selectors.partitionDeleteButton(1));
      browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000);
      keysPageObject.acceptRodalIfRaised();
      keysAsserts.assertKeySource({
        partitions: [],
        valueType: "string",
        rules: []
      });
    });
  });

  describe('partition groups', () => {
    describe('add', () => {
      const addPartitionGroupFullPath = `${testFolder}/${partitionsTestFolder}/add_partition_group`;
      before(() => {
        keysPageObject.goToKey(addPartitionGroupFullPath);
      });

      it('should add new partition group', () => {
        const newPartitionGroups = [['Banana'], ['Orange', 'Rick'], [false, 'Morty']];
        newPartitionGroups.forEach((group) => {
          group.forEach((value, i) => {
            if (value) browser.setValue(selectors.newPartitionGroupInput(i + 1), value);
          });
          browser.click(selectors.ADD_PARTITION_GROUP_BUTTON);
        });
        keysAsserts.assertKeySource({
          partitions: ["user.FavoriteFruit", "user.FatherName"],
          valueType: "string",
          rules: {
            "Banana": {
              "*": []
            },
            "Orange": {
              "Rick": []
            },
            "*": {
              "Morty": []
            }
          }
        });
      });
    });

    describe('delete', () => {
      const deletePartitionKeyFullPath = `${testFolder}/${partitionsTestFolder}/partition_groups`;
      before(() => {
        keysPageObject.goToKey(deletePartitionKeyFullPath);
      });

      it('should delete group rules when deleting partition group', () => {
        browser.click(selectors.partitionGroupDeleteButton(2));
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000);
        keysPageObject.acceptRodalIfRaised();
        keysAsserts.assertKeySource({
          partitions: ["user.FavoriteFruit", "user.Gender"],
          valueType: "string",
          rules: {
            "Banana": {
              "male": [
                {
                  Matcher: {},
                  Value: "someValue",
                  Type: "SingleVariant"
                }
              ]
            },
            "*": {
              "*": [
                {
                  Matcher: {},
                  Value: "otherDefaultValue",
                  Type: "SingleVariant"
                }
              ]
            }
          }
        })
      });
    });
  });
});<commit_msg>reorganize e2e tests<commit_after>/* global describe, before, beforeEach, after, it, browser */

import KeysAsserts from '../../KeysAsserts';
import KeysPageObject from '../../utils/KeysPageObject';
import selectors from '../../selectors/keySelectors';

describe('partition key', () => {
  const keysPageObject = new KeysPageObject(browser);
  const keysAsserts = new KeysAsserts(keysPageObject, browser);

  const testFolder = KeysPageObject.TEST_KEYS_FOLDER;
  const partitionsTestFolder = '@partitions';

  beforeEach(() => {
    browser.refresh();
    browser.acceptAlertIfPresent();
    keysPageObject.waitForKeyToLoad()
  });

  describe('add partition', () => {
    before(() => {
      browser.windowHandleMaximize();
    });

    describe('invalid partitions', () => {
      const emptyRulesKeyFullPath = `${testFolder}/${partitionsTestFolder}/empty_partition`;
      before(() => {
        keysPageObject.goToKey(emptyRulesKeyFullPath);
      });

      it('should not allow invalid properties', () => {
        keysPageObject.addPartitionFromProperty('someInvalidValue');
        browser.waitForVisible(selectors.ALERT_OK_BUTTON, 1000);
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000, true);
      });

      it('should not allow duplicate properties', () => {
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.waitForVisible(selectors.ALERT_OK_BUTTON, 1000, true);
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.waitForVisible(selectors.ALERT_OK_BUTTON, 1000);
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000, true);
      });
    });

    describe('valid partitions', () => {
      const addPartitionKeyFullPath = `${testFolder}/${partitionsTestFolder}/add_partition`;
      before(() => {
        keysPageObject.goToKey(addPartitionKeyFullPath);
      });

      it('should not partition if canceled', () => {
        const keySource = keysPageObject.getKeySource();
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000);
        browser.click(selectors.ALERT_CANCEL_BUTTON);
        keysAsserts.assertKeySource(keySource);
      });

      it('should auto-partition correctly if auto-partition was selected', () => {
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.clickWhenVisible(selectors.AUTO_PARTITION_BUTTON, 1000);
        keysAsserts.assertKeySource({
          partitions: ["user.FavoriteFruit"],
          valueType: "string",
          rules: {
            "*": [
              {
                Matcher: {
                  "user.AgentVersion": {
                    "$ge": "0.12.3",
                    "$compare": "version"
                  }
                },
                Value: "agentValue",
                Type: "SingleVariant"
              },
              {
                Matcher: {"user.Gender": "female"},
                Value: "femaleValue",
                Type: "SingleVariant"
              },
              {
                Matcher: {},
                Value: "defaultValue",
                Type: "SingleVariant"
              }
            ],
            "Apple": [
              {
                Matcher: {},
                Value: "appleValue",
                Type: "SingleVariant"
              }
            ]
          }
        });
      });

      it('should not allow auto-partition if matcher is invalid', () => {
        keysPageObject.addPartitionFromProperty('user.FavoriteFruit');
        browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000);
        browser.waitForVisible(selectors.AUTO_PARTITION_BUTTON, 1000, false);

        browser.waitForVisible(selectors.RESET_PARTITIONS_BUTTON, 1000);
        browser.click(selectors.RESET_PARTITIONS_BUTTON);
        keysAsserts.assertKeySource({
          partitions: ["user.FavoriteFruit"],
          valueType: "string",
          rules: {}
        });
      });
    });
  });

  describe('delete partition', () => {
    const deletePartitionKeyFullPath = `${testFolder}/${partitionsTestFolder}/delete_partition`;
    before(() => {
      keysPageObject.goToKey(deletePartitionKeyFullPath);
    });

    it('should clear rules after partition is deleted', () => {
      browser.click(selectors.partitionDeleteButton(1));
      browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000);
      keysPageObject.acceptRodalIfRaised();
      keysAsserts.assertKeySource({
        partitions: [],
        valueType: "string",
        rules: []
      });
    });
  });

  describe('partition groups', () => {
    it('should add new partition group', () => {
      keysPageObject.goToKey(`${testFolder}/${partitionsTestFolder}/add_partition_group`);
      const newPartitionGroups = [['Banana'], ['Orange', 'Rick'], [false, 'Morty']];
      newPartitionGroups.forEach((group) => {
        group.forEach((value, i) => {
          if (value) browser.setValue(selectors.newPartitionGroupInput(i + 1), value);
        });
        browser.click(selectors.ADD_PARTITION_GROUP_BUTTON);
      });
      keysAsserts.assertKeySource({
        partitions: ["user.FavoriteFruit", "user.FatherName"],
        valueType: "string",
        rules: {
          "Banana": {
            "*": []
          },
          "Orange": {
            "Rick": []
          },
          "*": {
            "Morty": []
          }
        }
      });
    });

    it('should delete group rules when deleting partition group', () => {
      keysPageObject.goToKey(`${testFolder}/${partitionsTestFolder}/partition_groups`);
      browser.click(selectors.partitionGroupDeleteButton(2));
      browser.waitForVisible(selectors.ALERT_CANCEL_BUTTON, 1000);
      keysPageObject.acceptRodalIfRaised();
      keysAsserts.assertKeySource({
        partitions: ["user.FavoriteFruit", "user.Gender"],
        valueType: "string",
        rules: {
          "Banana": {
            "male": [
              {
                Matcher: {},
                Value: "someValue",
                Type: "SingleVariant"
              }
            ]
          },
          "*": {
            "*": [
              {
                Matcher: {},
                Value: "otherDefaultValue",
                Type: "SingleVariant"
              }
            ]
          }
        }
      })
    });
  });
});<|endoftext|>


<commit_before>import React, { Component } from 'react';
import GraphiQL from 'graphiql';
import {
  print,
  parse
} from 'graphql';
import styles from './styles';
import { autobind } from 'core-decorators';
import JSON2_MOD from '../helpers/json2-mod';

const basicTypesDefaultValues = {
  Float: 0.0,
  ID: '',
  Int: 0,
  String: '',
  Boolean: false,
};

export default class GenerateMutation extends Component {
  constructor(props) {
    super(props);

    this.state = {
      showMutationsPopup: false,
      mutationSearchText: '',
      mutationSearchInputFocused: false
    };
  }

  isScalar(x) {
    return x === 'GraphQLScalarType';
  }

  isEnum(x) {
    return x === 'GraphQLEnumType';
  }

  isList(x) {
    return x === 'GraphQLList';
  }

  isNonNull(x) {
    return x === 'GraphQLNonNull';
  }

  isObjectType(x) {
    return x === 'GraphQLInputObjectType' || x === 'GraphQLObjectType';
  }

  isUnionType(x) {
    return x === 'GraphQLUnionType';
  }

  generateInputObject(graphqlObject) {
    const type = graphqlObject.type;
    const typeConstructorName = type.constructor.name;
    const ofType = type.ofType;
    const ofTypeConstructorName = ofType ? ofType.constructor.name : '';

    if (this.isScalar(typeConstructorName)) {
      return basicTypesDefaultValues[type.name];
    }

    if (this.isScalar(ofTypeConstructorName)) {
      if (this.isList(typeConstructorName)) {
        return [basicTypesDefaultValues[ofType.name]];
      }
      return basicTypesDefaultValues[ofType.name];
    }

    if (this.isEnum(typeConstructorName)) {
      return type.getValues()[0].value;
    }

    if (this.isEnum(ofTypeConstructorName)) {
      if (this.isList(typeConstructorName)) {
        return [ofType.getValues()[0].value];
      }
      return ofType.getValues()[0].value;
    }

    if (this.isObjectType(ofTypeConstructorName) || this.isObjectType(typeConstructorName)) {
      const fields = ofType ? ofType.getFields() : type.getFields();
      const fieldsInputObject = {};
      Object.keys(fields).forEach(fieldKey => (fieldsInputObject[fieldKey] = this.generateInputObject(fields[fieldKey])));
      if (this.isList(typeConstructorName)) {
        return [fieldsInputObject];
      }
      return fieldsInputObject;
    }

    return '';
  }

  getSubSelectionString(graphqlObject) {
    const type = graphqlObject.type;
    const typeConstructorName = type.constructor.name;
    const ofType = type.ofType;
    const ofTypeConstructorName = ofType ? ofType.constructor.name : '';

    if (this.isScalar(typeConstructorName) || this.isScalar(ofTypeConstructorName)) {
      return '';
    }

    if (this.isObjectType(ofTypeConstructorName) || this.isObjectType(typeConstructorName)) {
      const fields = ofType ? ofType.getFields() : type.getFields();
      if (Object.keys(fields).includes('id')) {
        return '{ id }';
      }

      const scalarKey = Object.keys(fields).find((fieldKey) => {
        const fieldType = fields[fieldKey].type;
        const fieldTypeConstructorName = fieldType.constructor.name;
        const fieldOfType = fieldType.ofType;
        const fieldOfTypeConstructorName = fieldOfType ? fieldOfType.constructor.name : '';
        return this.isScalar(fieldTypeConstructorName) || this.isScalar(fieldOfTypeConstructorName);
      });
      if (scalarKey) {
        return `{ ${scalarKey} }`;
      }

      const complexFieldKey = Object.keys(fields).sort()[0];
      const complexField = fields[complexFieldKey];
      return `{ ${this.generateOutputObjectString(complexField)} }`;
    }

    if (this.isUnionType(typeConstructorName) || this.isUnionType(ofTypeConstructorName)) {
      const unionTypes = type.getTypes();
      const subSelectionStringArray = unionTypes.map(item => {
        const wrapperObject = { type: item };
        const itemSubSelectionString = this.getSubSelectionString(wrapperObject);
        const unionTypeName = item.name;
        return `... on ${unionTypeName} ${itemSubSelectionString}`;
      });
      return `{ ${subSelectionStringArray.join('\n')} }`;
    }

    return '';
  }

  generateOutputObjectString(graphqlObject) {
    const args = graphqlObject.args;
    const argsStringArray = args.map((item) => {
      const type = item.type;
      const typeConstructorName = type.constructor.name;
      const ofType = type.ofType;
      const ofTypeConstructorName = ofType ? ofType.constructor.name : '';

      const isBasicType = this.isScalar(typeConstructorName) || this.isScalar(ofTypeConstructorName);

      const valueObject = this.generateInputObject(item);
      const valueObjectString = isBasicType ? valueObject : JSON2_MOD.stringify(valueObject, null, '', true);
      return `${item.name}: ${valueObjectString}`;
    });
    let argsString = argsStringArray.join(',');
    if (argsString) {
      argsString = `(${argsString})`;
    }

    const subSelectionString = this.getSubSelectionString(graphqlObject);

    return `${graphqlObject.name} ${argsString} ${subSelectionString}`;
  }

  @autobind
  mutationPressed(mutationName) {
    const mutationFields = this.props.schema.getMutationType().getFields();
    const mutation = mutationFields[mutationName];
    const mutationArgs = mutation.args;

    const queryVariables = [];

    const inputs = mutationArgs.map((mutationArg, index) => {
      const type = mutationArg.type;
      const typeConstructorName = type.constructor.name;
      const ofType = type.ofType;
      const ofTypeConstructorName = ofType ? ofType.constructor.name : '';

      const isBasicType = this.isScalar(typeConstructorName) || this.isScalar(ofTypeConstructorName);

      const valueObject = this.generateInputObject(mutationArg);

      if (!isBasicType) {
        queryVariables.push({
          name: '$input_' + index,
          type: ofType ? ofType.name : type.name,
          value: valueObject
        });
      }

      const valueObjectString = isBasicType ? valueObject : ('$input_' + index);
      return `${mutationArg.name}: ${valueObjectString}`;
    });
    let inputString = inputs.join(',');
    if (inputString) {
      inputString = `(${inputString})`;
    }

    let mutationInputString = queryVariables.map(item => (`${item.name}: ${item.type}!`)).join(',');
    if (mutationInputString) {
      mutationInputString = `(${mutationInputString})`;
    }

    const queryVariablesObject = queryVariables.reduce((previousValue, currentValue) => {
      previousValue[currentValue.name.slice(1)] = currentValue.value;
      return previousValue;
    }, {});

    const outputFields = mutation.type.getFields();
    const outputStrings = Object.keys(outputFields).map((fieldKey) => {
      const outputField = outputFields[fieldKey];
      return `${this.generateOutputObjectString(outputField)}`;
    });
    const outputString = outputStrings.join(',');

    const queryString = `
      mutation ${mutationName}Mutation${mutationInputString} {
        ${mutationName}${inputString} {
          ${outputString}
        }
      }
    `;
    const prettyQuery = print(parse(queryString));
    const queryVariablesString = JSON.stringify(queryVariablesObject, null, '  ');

    this.setState({
      showMutationsPopup: false,
      mutationSearchText: '',
    });
    this.props.updateQueryVariablesResponse && this.props.updateQueryVariablesResponse(prettyQuery, queryVariablesString);
  }

  @autobind
  generateMutationPressed() {
    this.setState({
      showMutationsPopup: !this.state.showMutationsPopup
    });
  }

  renderMutations() {
    if (!this.state.showMutationsPopup) {
      return null;
    }

    const mutation = this.props.schema.getMutationType();
    const mutationFields = mutation.getFields();

    const mutationSearchInputStyle = this.state.mutationSearchInputFocused ? styles.searchInputFocused : null;
    const mutationSearchText = (this.state.mutationSearchText || '').toLowerCase();

    return (

        <input
          onChange={event => this.setState({ mutationSearchText: event.target.value })}
          style={Object.assign({}, styles.searchInput, mutationSearchInputStyle)}
          type={'text'}
          placeholder={'Find mutation...'}
          onFocus={() => this.setState({ mutationSearchInputFocused: true })}
          onBlur={() => this.setState({ mutationSearchInputFocused: false })}
          autoFocus={true}
        />
        {Object.keys(mutationFields)
          .sort()
          .filter(value => value.toLowerCase().includes(mutationSearchText))
          .map(mutationName => (

 this.mutationPressed(mutationName)}
            >
              {mutationName}

        ))}

    );
  }

  render() {
    const showGenerateMutation = this.props.schema && this.props.schema.getMutationType();
    if (!showGenerateMutation) {
      return null;
    }

    return (

        {this.renderMutations()}
        <GraphiQL.ToolbarButton
          title={'Generate mutation query'}
          label={'Generate Mutation'}
          onClick={this.generateMutationPressed}
        />

    );
  }
}
<commit_msg>Fixed bug where unsupported scalar values are using in mutation input<commit_after>import React, { Component } from 'react';
import GraphiQL from 'graphiql';
import {
  print,
  parse
} from 'graphql';
import styles from './styles';
import { autobind } from 'core-decorators';
import JSON2_MOD from '../helpers/json2-mod';

const basicTypesDefaultValues = {
  Float: 0.0,
  ID: '',
  Int: 0,
  String: '',
  Boolean: false,
};

export default class GenerateMutation extends Component {
  constructor(props) {
    super(props);

    this.state = {
      showMutationsPopup: false,
      mutationSearchText: '',
      mutationSearchInputFocused: false
    };
  }

  isScalar(x) {
    return x === 'GraphQLScalarType';
  }

  isEnum(x) {
    return x === 'GraphQLEnumType';
  }

  isList(x) {
    return x === 'GraphQLList';
  }

  isNonNull(x) {
    return x === 'GraphQLNonNull';
  }

  isObjectType(x) {
    return x === 'GraphQLInputObjectType' || x === 'GraphQLObjectType';
  }

  isUnionType(x) {
    return x === 'GraphQLUnionType';
  }

  generateInputObject(graphqlObject) {
    const type = graphqlObject.type;
    const typeConstructorName = type.constructor.name;
    const ofType = type.ofType;
    const ofTypeConstructorName = ofType ? ofType.constructor.name : '';

    if (this.isScalar(typeConstructorName)) {
      const defaultValue = basicTypesDefaultValues[type.name];
      return defaultValue === undefined ? null : defaultValue;
    }

    if (this.isScalar(ofTypeConstructorName)) {
      const defaultValue = basicTypesDefaultValues[ofType.name];
      if (this.isList(typeConstructorName)) {
        return [defaultValue === undefined ? null : defaultValue];
      }
      return defaultValue === undefined ? null : defaultValue;
    }

    if (this.isEnum(typeConstructorName)) {
      return type.getValues()[0].value;
    }

    if (this.isEnum(ofTypeConstructorName)) {
      if (this.isList(typeConstructorName)) {
        return [ofType.getValues()[0].value];
      }
      return ofType.getValues()[0].value;
    }

    if (this.isObjectType(ofTypeConstructorName) || this.isObjectType(typeConstructorName)) {
      const fields = ofType ? ofType.getFields() : type.getFields();
      const fieldsInputObject = {};
      Object.keys(fields).forEach(fieldKey => (fieldsInputObject[fieldKey] = this.generateInputObject(fields[fieldKey])));
      if (this.isList(typeConstructorName)) {
        return [fieldsInputObject];
      }
      return fieldsInputObject;
    }

    return '';
  }

  getSubSelectionString(graphqlObject) {
    const type = graphqlObject.type;
    const typeConstructorName = type.constructor.name;
    const ofType = type.ofType;
    const ofTypeConstructorName = ofType ? ofType.constructor.name : '';

    if (this.isScalar(typeConstructorName) || this.isScalar(ofTypeConstructorName)) {
      return '';
    }

    if (this.isObjectType(ofTypeConstructorName) || this.isObjectType(typeConstructorName)) {
      const fields = ofType ? ofType.getFields() : type.getFields();
      if (Object.keys(fields).includes('id')) {
        return '{ id }';
      }

      const scalarKey = Object.keys(fields).find((fieldKey) => {
        const fieldType = fields[fieldKey].type;
        const fieldTypeConstructorName = fieldType.constructor.name;
        const fieldOfType = fieldType.ofType;
        const fieldOfTypeConstructorName = fieldOfType ? fieldOfType.constructor.name : '';
        return this.isScalar(fieldTypeConstructorName) || this.isScalar(fieldOfTypeConstructorName);
      });
      if (scalarKey) {
        return `{ ${scalarKey} }`;
      }

      const complexFieldKey = Object.keys(fields).sort()[0];
      const complexField = fields[complexFieldKey];
      return `{ ${this.generateOutputObjectString(complexField)} }`;
    }

    if (this.isUnionType(typeConstructorName) || this.isUnionType(ofTypeConstructorName)) {
      const unionTypes = type.getTypes();
      const subSelectionStringArray = unionTypes.map(item => {
        const wrapperObject = { type: item };
        const itemSubSelectionString = this.getSubSelectionString(wrapperObject);
        const unionTypeName = item.name;
        return `... on ${unionTypeName} ${itemSubSelectionString}`;
      });
      return `{ ${subSelectionStringArray.join('\n')} }`;
    }

    return '';
  }

  generateOutputObjectString(graphqlObject) {
    const args = graphqlObject.args;
    const argsStringArray = args.map((item) => {
      const type = item.type;
      const typeConstructorName = type.constructor.name;
      const ofType = type.ofType;
      const ofTypeConstructorName = ofType ? ofType.constructor.name : '';

      const isBasicType = this.isScalar(typeConstructorName) || this.isScalar(ofTypeConstructorName);

      const valueObject = this.generateInputObject(item);
      const valueObjectString = isBasicType ? valueObject : JSON2_MOD.stringify(valueObject, null, '', true);
      return `${item.name}: ${valueObjectString}`;
    });
    let argsString = argsStringArray.join(',');
    if (argsString) {
      argsString = `(${argsString})`;
    }

    const subSelectionString = this.getSubSelectionString(graphqlObject);

    return `${graphqlObject.name} ${argsString} ${subSelectionString}`;
  }

  @autobind
  mutationPressed(mutationName) {
    const mutationFields = this.props.schema.getMutationType().getFields();
    const mutation = mutationFields[mutationName];
    const mutationArgs = mutation.args;

    const queryVariables = [];

    const inputs = mutationArgs.map((mutationArg, index) => {
      const type = mutationArg.type;
      const typeConstructorName = type.constructor.name;
      const ofType = type.ofType;
      const ofTypeConstructorName = ofType ? ofType.constructor.name : '';

      const isBasicType = this.isScalar(typeConstructorName) || this.isScalar(ofTypeConstructorName);

      const valueObject = this.generateInputObject(mutationArg);

      if (!isBasicType) {
        queryVariables.push({
          name: '$input_' + index,
          type: ofType ? ofType.name : type.name,
          value: valueObject
        });
      }

      const valueObjectString = isBasicType ? valueObject : ('$input_' + index);
      return `${mutationArg.name}: ${valueObjectString}`;
    });
    let inputString = inputs.join(',');
    if (inputString) {
      inputString = `(${inputString})`;
    }

    let mutationInputString = queryVariables.map(item => (`${item.name}: ${item.type}!`)).join(',');
    if (mutationInputString) {
      mutationInputString = `(${mutationInputString})`;
    }

    const queryVariablesObject = queryVariables.reduce((previousValue, currentValue) => {
      previousValue[currentValue.name.slice(1)] = currentValue.value;
      return previousValue;
    }, {});

    const outputFields = mutation.type.getFields();
    const outputStrings = Object.keys(outputFields).map((fieldKey) => {
      const outputField = outputFields[fieldKey];
      return `${this.generateOutputObjectString(outputField)}`;
    });
    const outputString = outputStrings.join(',');

    const queryString = `
      mutation ${mutationName}Mutation${mutationInputString} {
        ${mutationName}${inputString} {
          ${outputString}
        }
      }
    `;
    const prettyQuery = print(parse(queryString));
    const queryVariablesString = JSON.stringify(queryVariablesObject, null, '  ');

    this.setState({
      showMutationsPopup: false,
      mutationSearchText: '',
    });
    this.props.updateQueryVariablesResponse && this.props.updateQueryVariablesResponse(prettyQuery, queryVariablesString);
  }

  @autobind
  generateMutationPressed() {
    this.setState({
      showMutationsPopup: !this.state.showMutationsPopup
    });
  }

  renderMutations() {
    if (!this.state.showMutationsPopup) {
      return null;
    }

    const mutation = this.props.schema.getMutationType();
    const mutationFields = mutation.getFields();

    const mutationSearchInputStyle = this.state.mutationSearchInputFocused ? styles.searchInputFocused : null;
    const mutationSearchText = (this.state.mutationSearchText || '').toLowerCase();

    return (

        <input
          onChange={event => this.setState({ mutationSearchText: event.target.value })}
          style={Object.assign({}, styles.searchInput, mutationSearchInputStyle)}
          type={'text'}
          placeholder={'Find mutation...'}
          onFocus={() => this.setState({ mutationSearchInputFocused: true })}
          onBlur={() => this.setState({ mutationSearchInputFocused: false })}
          autoFocus={true}
        />
        {Object.keys(mutationFields)
          .sort()
          .filter(value => value.toLowerCase().includes(mutationSearchText))
          .map(mutationName => (

 this.mutationPressed(mutationName)}
            >
              {mutationName}

        ))}

    );
  }

  render() {
    const showGenerateMutation = this.props.schema && this.props.schema.getMutationType();
    if (!showGenerateMutation) {
      return null;
    }

    return (

        {this.renderMutations()}
        <GraphiQL.ToolbarButton
          title={'Generate mutation query'}
          label={'Generate Mutation'}
          onClick={this.generateMutationPressed}
        />

    );
  }
}
<|endoftext|>


<commit_before>import getElement from './-get-element';
import fireEvent from './fire-event';
import settled from '../settled';
import isFocusable from './-is-focusable';
import { nextTickPromise } from '../-utils';

/**
  @private
  @method __blur__
  @param {Element} element
*/
export function __blur__(element) {
  let browserIsNotFocused = document.hasFocus && !document.hasFocus();

  // makes `document.activeElement` be `body`.
  // If the browser is focused, it also fires a blur event
  element.blur();

  // Chrome/Firefox does not trigger the `blur` event if the window
  // does not have focus. If the document does not have focus then
  // fire `blur` event via native event.
  if (browserIsNotFocused) {
    fireEvent(element, 'blur', { bubbles: false });
    fireEvent(element, 'focusout');
  }
}

/**
  @method blur
  @param {String|Element} [target=document.activeElement] the element to blur
  @return {Promise<void>}
  @public
*/
export default function blur(target = document.activeElement) {
  return nextTickPromise().then(() => {
    let element = getElement(target);
    if (!element) {
      throw new Error(`Element not found when calling \`blur('${target}')\`.`);
    }

    if (!isFocusable(element)) {
      throw new Error(`${target} is not focusable`);
    }

    __blur__(element);

    return settled();
  });
}
<commit_msg>Docs: flesh out blur documentation<commit_after>import getElement from './-get-element';
import fireEvent from './fire-event';
import settled from '../settled';
import isFocusable from './-is-focusable';
import { nextTickPromise } from '../-utils';

export function __blur__(element) {
  let browserIsNotFocused = document.hasFocus && !document.hasFocus();

  // makes `document.activeElement` be `body`.
  // If the browser is focused, it also fires a blur event
  element.blur();

  // Chrome/Firefox does not trigger the `blur` event if the window
  // does not have focus. If the document does not have focus then
  // fire `blur` event via native event.
  if (browserIsNotFocused) {
    fireEvent(element, 'blur', { bubbles: false });
    fireEvent(element, 'focusout');
  }
}

/**
  Unfocus the specified selector.

  @public
  @method blur
  @param {String|Element} [target=document.activeElement] the element or selector to unfocus
  @return {Promise<void>} resolves when the application is settled
*/
export default function blur(target = document.activeElement) {
  return nextTickPromise().then(() => {
    let element = getElement(target);
    if (!element) {
      throw new Error(`Element not found when calling \`blur('${target}')\`.`);
    }

    if (!isFocusable(element)) {
      throw new Error(`${target} is not focusable`);
    }

    __blur__(element);

    return settled();
  });
}
<|endoftext|>


<commit_before>/* jshint strict: true, undef: true, unused: true */
/* global define */

define('dom/class', [
    'pastry'
], function(
    pastry
) {
    'use strict';
    /*
     * @author      : 绝云（wensen.lws）
     * @description : dom classList related
     */
    var classList;

    return pastry.domClass = classList;
});

<commit_msg>dom/class<commit_after>/* jshint strict: true, undef: true, unused: true */
/* global define */

define('dom/class', [
    'pastry',
    'dom/utils',
    'dom/query'
], function(
    pastry,
    domUtils,
    domQuery
) {
    'use strict';
    /*
     * @author      : 绝云（wensen.lws）
     * @description : dom classList related
     * @note        : if ClassList is supported, use ClassList
     */
    var RE_spaces    = /\s+/,
        className    = 'className',
        spaceStr     = ' ',
        hasClassList = domUtils.hasClassList,
        tmpArray     = [''],
        domClass;

    function str2array (str) {
        if (pastry.isString(str)) {
            if (str && !RE_spaces.test(str)) {
                tmpArray[0] = str;
                return tmpArray;
            }
            var arr = str.split(RE_spaces);
            if (arr.length && !arr[0]) {
                arr.shift();
            }
            if (arr.length && !arr[arr.length - 1]) {
                arr.pop();
            }
            return arr;
        }
        if (!str) {
            return [];
        }
        return pastry.filter(str, function (x) {
            return x;
        });
    }
    function fillSpace (str) {
        return spaceStr + str + spaceStr;
    }

    return pastry.domClass = domClass = {
        contains: function (node, classStr) {
            node     = domQuery.one(node);
            classStr = pastry.trim(classStr);
            if (hasClassList) {
                return node.classList.contains(classStr);
            }
            return fillSpace(node[className]).indexOf(fillSpace(classStr)) >= 0;
        },
        add: function (node, classStr) {
            node     = domQuery.one(node);
            classStr = str2array(classStr);
            if (hasClassList) {
                pastry.each(classStr, function (c) {
                    node.classList.add(c);
                });
            } else {
                var oldClassName = node[className],
                    oldLen, newLen;
                oldClassName = oldClassName ? fillSpace(oldClassName) : spaceStr;
                oldLen = oldClassName.length;
                pastry.each(classStr, function (c) {
                    if (c && oldClassName.indexOf(fillSpace(c)) < 0) {
                        oldClassName += c + spaceStr;
                    }
                });
                newLen = oldClassName.length;
                if (oldLen < newLen) {
                    node[className] = oldClassName.substr(1, newLen - 2);
                }
            }
        },
        remove: function (node, classStr) {
            node     = domQuery.one(node);
            classStr = str2array(classStr);
            if (hasClassList) {
                pastry.each(classStr, function (c) {
                    node.classList.remove(c);
                });
            } else {
                var cls = fillSpace(node[className]);
                pastry.each(classStr, function (c) {
                    cls = cls.replace(fillSpace(c), spaceStr);
                });
                cls = pastry.trim(cls);
                if (node[className] !== cls) {
                    node[className] = cls;
                }
            }
        },
        clear: function (node) {
            node = domQuery.one(node);
            node[className] = '';
        },
        toggle: function (node, classStr) {
            node     = domQuery.one(node);
            classStr = str2array(classStr);
            if (hasClassList) {
                pastry.each(classStr, function (c) {
                    node.classList.toggle(c);
                });
            } else {
                pastry.each(classStr, function (c) {
                    domClass[domClass.contains(node, c) ? 'remove' : 'add'](node, c);
                });
            }
        }
    };
});

<|endoftext|>


<commit_before>const assert = require('assert');

const DashInsert = str => {
  const arr = str.split('');
  for (let i = 0; i < str.length - 1; i += 1) {
    if (arr[i] % 2 !== 0 && arr[i + 1] % 2 !== 0) {
      arr[i] = `${arr[i]}-`;
    }
  }

  // console.log('123');
  console.log(str);

  return arr.join('');
};

const in1 = '1234567'; // input
const expect1 = '1234567'; // output
const test1 = DashInsert(in1);
assert.strictEqual(test1, expect1, `should be ${expect1}`);
// console.log('works');
<commit_msg>fix prettier error, comment out console.log<commit_after>const assert = require('assert');

const DashInsert = (str) => {
  const arr = str.split('');
  for (let i = 0; i < str.length - 1; i += 1) {
    if (arr[i] % 2 !== 0 && arr[i + 1] % 2 !== 0) {
      arr[i] = `${arr[i]}-`;
    }
  }
  // console.log(str);
  return arr.join('');
};

const in1 = '1234567'; // input
const expect1 = '1234567'; // output
const test1 = DashInsert(in1);
assert.strictEqual(test1, expect1, `should be ${expect1}`);
// console.log('works');
<|endoftext|>