<commit_before>// # Ghost Head Helper
// Usage: `{{ghost_head}}`
//
// Outputs scripts and other assets at the top of a Ghost theme
const {metaData, escapeExpression, SafeString, logging, settingsCache, config, blogIcon, urlUtils} = require('../services/proxy');
const _ = require('lodash');
const debug = require('ghost-ignition').debug('ghost_head');
const templateStyles = require('./tpl/styles');

const getMetaData = metaData.get;

function writeMetaTag(property, content, type) {
    type = type || property.substring(0, 7) === 'twitter' ? 'name' : 'property';
    return '<meta ' + type + '="' + property + '" content="' + content + '" />';
}

function finaliseStructuredData(meta) {
    const head = [];

    _.each(meta.structuredData, function (content, property) {
        if (property === 'article:tag') {
            _.each(meta.keywords, function (keyword) {
                if (keyword !== '') {
                    keyword = escapeExpression(keyword);
                    head.push(writeMetaTag(property,
                        escapeExpression(keyword)));
                }
            });
            head.push('');
        } else if (content !== null && content !== undefined) {
            head.push(writeMetaTag(property,
                escapeExpression(content)));
        }
    });

    return head;
}

function getMembersHelper() {
    const stripeDirectSecretKey = settingsCache.get('stripe_secret_key');
    const stripeDirectPublishableKey = settingsCache.get('stripe_publishable_key');
    const stripeConnectAccountId = settingsCache.get('stripe_connect_account_id');
    const portalUrl = config.get('portal:url');
    let membersHelper = `<script defer src="${portalUrl}" data-ghost="${urlUtils.getSiteUrl()}"></script>`;
    membersHelper += (`<style> ${templateStyles}</style>`);
    if ((!!stripeDirectSecretKey && !!stripeDirectPublishableKey) || !!stripeConnectAccountId) {
        membersHelper += '<script async src="https://js.stripe.com/v3/"></script>';
    }
    return membersHelper;
}

/**
 * **NOTE**
 * Express adds `_locals`, see https://github.com/expressjs/express/blob/4.15.4/lib/response.js#L962.
 * But `options.data.root.context` is available next to `root._locals.context`, because
 * Express creates a `renderOptions` object, see https://github.com/expressjs/express/blob/4.15.4/lib/application.js#L554
 * and merges all locals to the root of the object. Very confusing, because the data is available in different layers.
 *
 * Express forwards the data like this to the hbs engine:
 * {
 *   post: {},             - res.render('view', databaseResponse)
 *   context: ['post'],    - from res.locals
 *   safeVersion: '1.x',   - from res.locals
 *   _locals: {
 *     context: ['post'],
 *     safeVersion: '1.x'
 *   }
 * }
 *
 * hbs forwards the data to any hbs helper like this
 * {
 *   data: {
 *     site: {},
 *     labs: {},
 *     config: {},
 *     root: {
 *       post: {},
 *       context: ['post'],
 *       locals: {...}
 *     }
 *  }
 *
 * `site`, `labs` and `config` are the templateOptions, search for `hbs.updateTemplateOptions` in the code base.
 *  Also see how the root object gets created, https://github.com/wycats/handlebars.js/blob/v4.0.6/lib/handlebars/runtime.js#L259
 */
// We use the name ghost_head to match the helper for consistency:
module.exports = function ghost_head(options) { // eslint-disable-line camelcase
    debug('begin');

    // if server error page do nothing
    if (options.data.root.statusCode >= 500) {
        return;
    }

    const head = [];
    const dataRoot = options.data.root;
    const context = dataRoot._locals.context ? dataRoot._locals.context : null;
    const safeVersion = dataRoot._locals.safeVersion;
    const postCodeInjection = dataRoot && dataRoot.post ? dataRoot.post.codeinjection_head : null;
    const tagCodeInjection = dataRoot && dataRoot.tag ? dataRoot.tag.codeinjection_head : null;
    const globalCodeinjection = settingsCache.get('codeinjection_head');
    const useStructuredData = !config.isPrivacyDisabled('useStructuredData');
    const referrerPolicy = config.get('referrerPolicy') ? config.get('referrerPolicy') : 'no-referrer-when-downgrade';
    const favicon = blogIcon.getIconUrl();
    const iconType = blogIcon.getIconType(favicon);

    debug('preparation complete, begin fetch');

    /**
     * @TODO:
     *   - getMetaData(dataRoot, dataRoot) -> yes that looks confusing!
     *   - there is a very mixed usage of `data.context` vs. `root.context` vs `root._locals.context` vs. `this.context`
     *   - NOTE: getMetaData won't live here anymore soon, see https://github.com/TryGhost/Ghost/issues/8995
     *   - therefor we get rid of using `getMetaData(this, dataRoot)`
     *   - dataRoot has access to *ALL* locals, see function description
     *   - it should not break anything
     */
    return getMetaData(dataRoot, dataRoot)
        .then(function handleMetaData(meta) {
            debug('end fetch');

            if (context) {
                // head is our main array that holds our meta data
                if (meta.metaDescription && meta.metaDescription.length > 0) {
                    head.push('<meta name="description" content="' + escapeExpression(meta.metaDescription) + '" />');
                }

                // no output in head if a publication icon is not set
                if (settingsCache.get('icon')) {
                    head.push('<link rel="icon" href="' + favicon + '" type="image/' + iconType + '" />');
                }

                head.push('<link rel="canonical" href="' +
                    escapeExpression(meta.canonicalUrl) + '" />');
                head.push('<meta name="referrer" content="' + referrerPolicy + '" />');

                // don't allow indexing of preview URLs!
                if (_.includes(context, 'preview')) {
                    head.push(writeMetaTag('robots', 'noindex,nofollow', 'name'));
                }

                // show amp link in post when 1. we are not on the amp page and 2. amp is enabled
                if (_.includes(context, 'post') && !_.includes(context, 'amp') && settingsCache.get('amp')) {
                    head.push('<link rel="amphtml" href="' +
                        escapeExpression(meta.ampUrl) + '" />');
                }

                if (meta.previousUrl) {
                    head.push('<link rel="prev" href="' +
                        escapeExpression(meta.previousUrl) + '" />');
                }

                if (meta.nextUrl) {
                    head.push('<link rel="next" href="' +
                        escapeExpression(meta.nextUrl) + '" />');
                }

                if (!_.includes(context, 'paged') && useStructuredData) {
                    head.push('');
                    head.push.apply(head, finaliseStructuredData(meta));
                    head.push('');

                    if (meta.schema) {
                        head.push('<script type="application/ld+json">\n' +
                            JSON.stringify(meta.schema, null, '    ') +
                            '\n    </script>\n');
                    }
                }

                if (!_.includes(context, 'amp')) {
                    head.push(getMembersHelper());
                }
            }

            head.push('<meta name="generator" content="Ghost ' +
                escapeExpression(safeVersion) + '" />');

            head.push('<link rel="alternate" type="application/rss+xml" title="' +
                escapeExpression(meta.site.title) + '" href="' +
                escapeExpression(meta.rssUrl) + '" />');

            // no code injection for amp context!!!
            if (!_.includes(context, 'amp')) {
                if (!_.isEmpty(globalCodeinjection)) {
                    head.push(globalCodeinjection);
                }

                if (!_.isEmpty(postCodeInjection)) {
                    head.push(postCodeInjection);
                }

                if (!_.isEmpty(tagCodeInjection)) {
                    head.push(tagCodeInjection);
                }
            }
            debug('end');
            return new SafeString(head.join('\n    ').trim());
        })
        .catch(function handleError(err) {
            logging.error(err);

            // Return what we have so far (currently nothing)
            return new SafeString(head.join('\n    ').trim());
        });
};
<commit_msg>Updated portal to include accent color in preview mode<commit_after>// # Ghost Head Helper
// Usage: `{{ghost_head}}`
//
// Outputs scripts and other assets at the top of a Ghost theme
const {metaData, escapeExpression, SafeString, logging, settingsCache, config, blogIcon, urlUtils} = require('../services/proxy');
const _ = require('lodash');
const debug = require('ghost-ignition').debug('ghost_head');
const templateStyles = require('./tpl/styles');

const getMetaData = metaData.get;

function writeMetaTag(property, content, type) {
    type = type || property.substring(0, 7) === 'twitter' ? 'name' : 'property';
    return '<meta ' + type + '="' + property + '" content="' + content + '" />';
}

function finaliseStructuredData(meta) {
    const head = [];

    _.each(meta.structuredData, function (content, property) {
        if (property === 'article:tag') {
            _.each(meta.keywords, function (keyword) {
                if (keyword !== '') {
                    keyword = escapeExpression(keyword);
                    head.push(writeMetaTag(property,
                        escapeExpression(keyword)));
                }
            });
            head.push('');
        } else if (content !== null && content !== undefined) {
            head.push(writeMetaTag(property,
                escapeExpression(content)));
        }
    });

    return head;
}

function getMembersHelper(data) {
    const stripeDirectSecretKey = settingsCache.get('stripe_secret_key');
    const stripeDirectPublishableKey = settingsCache.get('stripe_publishable_key');
    const stripeConnectAccountId = settingsCache.get('stripe_connect_account_id');
    const colorString = _.has(data, 'site._preview') && data.site.accent_color ? ` data-accent-color="${data.site.accent_color}"` : '';
    const portalUrl = config.get('portal:url');
    let membersHelper = `<script defer src="${portalUrl}" data-ghost="${urlUtils.getSiteUrl()}"${colorString}></script>`;
    membersHelper += (`<style> ${templateStyles}</style>`);
    if ((!!stripeDirectSecretKey && !!stripeDirectPublishableKey) || !!stripeConnectAccountId) {
        membersHelper += '<script async src="https://js.stripe.com/v3/"></script>';
    }
    return membersHelper;
}

/**
 * **NOTE**
 * Express adds `_locals`, see https://github.com/expressjs/express/blob/4.15.4/lib/response.js#L962.
 * But `options.data.root.context` is available next to `root._locals.context`, because
 * Express creates a `renderOptions` object, see https://github.com/expressjs/express/blob/4.15.4/lib/application.js#L554
 * and merges all locals to the root of the object. Very confusing, because the data is available in different layers.
 *
 * Express forwards the data like this to the hbs engine:
 * {
 *   post: {},             - res.render('view', databaseResponse)
 *   context: ['post'],    - from res.locals
 *   safeVersion: '1.x',   - from res.locals
 *   _locals: {
 *     context: ['post'],
 *     safeVersion: '1.x'
 *   }
 * }
 *
 * hbs forwards the data to any hbs helper like this
 * {
 *   data: {
 *     site: {},
 *     labs: {},
 *     config: {},
 *     root: {
 *       post: {},
 *       context: ['post'],
 *       locals: {...}
 *     }
 *  }
 *
 * `site`, `labs` and `config` are the templateOptions, search for `hbs.updateTemplateOptions` in the code base.
 *  Also see how the root object gets created, https://github.com/wycats/handlebars.js/blob/v4.0.6/lib/handlebars/runtime.js#L259
 */
// We use the name ghost_head to match the helper for consistency:
module.exports = function ghost_head(options) { // eslint-disable-line camelcase
    debug('begin');

    // if server error page do nothing
    if (options.data.root.statusCode >= 500) {
        return;
    }

    const head = [];
    const dataRoot = options.data.root;
    const context = dataRoot._locals.context ? dataRoot._locals.context : null;
    const safeVersion = dataRoot._locals.safeVersion;
    const postCodeInjection = dataRoot && dataRoot.post ? dataRoot.post.codeinjection_head : null;
    const tagCodeInjection = dataRoot && dataRoot.tag ? dataRoot.tag.codeinjection_head : null;
    const globalCodeinjection = settingsCache.get('codeinjection_head');
    const useStructuredData = !config.isPrivacyDisabled('useStructuredData');
    const referrerPolicy = config.get('referrerPolicy') ? config.get('referrerPolicy') : 'no-referrer-when-downgrade';
    const favicon = blogIcon.getIconUrl();
    const iconType = blogIcon.getIconType(favicon);

    debug('preparation complete, begin fetch');

    /**
     * @TODO:
     *   - getMetaData(dataRoot, dataRoot) -> yes that looks confusing!
     *   - there is a very mixed usage of `data.context` vs. `root.context` vs `root._locals.context` vs. `this.context`
     *   - NOTE: getMetaData won't live here anymore soon, see https://github.com/TryGhost/Ghost/issues/8995
     *   - therefor we get rid of using `getMetaData(this, dataRoot)`
     *   - dataRoot has access to *ALL* locals, see function description
     *   - it should not break anything
     */
    return getMetaData(dataRoot, dataRoot)
        .then(function handleMetaData(meta) {
            debug('end fetch');

            if (context) {
                // head is our main array that holds our meta data
                if (meta.metaDescription && meta.metaDescription.length > 0) {
                    head.push('<meta name="description" content="' + escapeExpression(meta.metaDescription) + '" />');
                }

                // no output in head if a publication icon is not set
                if (settingsCache.get('icon')) {
                    head.push('<link rel="icon" href="' + favicon + '" type="image/' + iconType + '" />');
                }

                head.push('<link rel="canonical" href="' +
                    escapeExpression(meta.canonicalUrl) + '" />');
                head.push('<meta name="referrer" content="' + referrerPolicy + '" />');

                // don't allow indexing of preview URLs!
                if (_.includes(context, 'preview')) {
                    head.push(writeMetaTag('robots', 'noindex,nofollow', 'name'));
                }

                // show amp link in post when 1. we are not on the amp page and 2. amp is enabled
                if (_.includes(context, 'post') && !_.includes(context, 'amp') && settingsCache.get('amp')) {
                    head.push('<link rel="amphtml" href="' +
                        escapeExpression(meta.ampUrl) + '" />');
                }

                if (meta.previousUrl) {
                    head.push('<link rel="prev" href="' +
                        escapeExpression(meta.previousUrl) + '" />');
                }

                if (meta.nextUrl) {
                    head.push('<link rel="next" href="' +
                        escapeExpression(meta.nextUrl) + '" />');
                }

                if (!_.includes(context, 'paged') && useStructuredData) {
                    head.push('');
                    head.push.apply(head, finaliseStructuredData(meta));
                    head.push('');

                    if (meta.schema) {
                        head.push('<script type="application/ld+json">\n' +
                            JSON.stringify(meta.schema, null, '    ') +
                            '\n    </script>\n');
                    }
                }

                if (!_.includes(context, 'amp')) {
                    head.push(getMembersHelper(options.data));
                }
            }

            head.push('<meta name="generator" content="Ghost ' +
                escapeExpression(safeVersion) + '" />');

            head.push('<link rel="alternate" type="application/rss+xml" title="' +
                escapeExpression(meta.site.title) + '" href="' +
                escapeExpression(meta.rssUrl) + '" />');

            // no code injection for amp context!!!
            if (!_.includes(context, 'amp')) {
                if (!_.isEmpty(globalCodeinjection)) {
                    head.push(globalCodeinjection);
                }

                if (!_.isEmpty(postCodeInjection)) {
                    head.push(postCodeInjection);
                }

                if (!_.isEmpty(tagCodeInjection)) {
                    head.push(tagCodeInjection);
                }
            }
            debug('end');
            return new SafeString(head.join('\n    ').trim());
        })
        .catch(function handleError(err) {
            logging.error(err);

            // Return what we have so far (currently nothing)
            return new SafeString(head.join('\n    ').trim());
        });
};
<|endoftext|>


<commit_before>var gulp        = require('gulp'),
    source      = require('vinyl-source-stream'),
    clean       = require('gulp-clean'),
    stylus      = require('gulp-stylus'),
    nib         = require('nib'),
    jshint      = require('gulp-jshint'),
    rename      = require('gulp-rename'),
    concat      = require('gulp-concat'),
    stylish     = require('jshint-stylish'),
    preprocess  = require('gulp-preprocess'),
    minifyCSS   = require('gulp-minify-css'),
    browserify  = require('browserify');
    uglify      = require('gulp-uglify')
    seq         = require('run-sequence'),
    streamqueue = require('streamqueue'),
    react       = require('gulp-react'),
    reactify    = require('reactify');
    exec        = require('child_process').exec,
    NwBuilder   = require('node-webkit-builder'),
    gutil       = require('gulp-util'),
    Notifier    = new require('node-notifier')();

var bases = {
 root: '.',
 src: 'app/',
 target: 'target/',
 appTarget: 'target/app/',
 packageTarget: 'target/package/'
};

var paths = {
  all: "**",
  jsx: 'js/**/*.jsx',
  js: 'js/**/*.js',
  styl: "css/**/*.styl",
  rootStyl: 'css/index.styl',
  destStyl: 'css/index.css',
  rootJS: 'js/index.js',
  rootHtml: 'index.html',
  html: '**/*.html',
  md: '**/*.md',
  css: 'css/*/**'
};

var isDevEnvironment = false;

gulp.task('setDevEnv', function() {
    isDevEnvironment = true;
});

gulp.task('clean-target', function() {
  return gulp.src(bases.target, {read: false})
             .pipe(clean({force: true}));
});

gulp.task('copy', function() {
  return gulp.src(paths.all, {cwd: bases.src})
             .pipe(gulp.dest(bases.appTarget));
});

gulp.task('stylus', ['copy'], function () {
  return gulp.src(paths.rootStyl, {cwd: bases.appTarget})
            .pipe(stylus({errors: true, /*linenos: true,*/ use: [nib()]}))
            .pipe(isDevEnvironment ? gutil.noop() : minifyCSS({keepBreaks:true}))
            .pipe(rename(paths.destStyl))
            .pipe(gulp.dest(bases.appTarget));
});

gulp.task('scripts', ['copy'], function() {
  //var stream = streamqueue({objectMode: true});
  //var stream2 = streamqueue({objectMode: true});

  // js, jsx scripts
  /*stream.queue(gulp.src([paths.js, paths.jsx, paths.rootJS], {cwd: bases.appTarget})
                  .pipe(react())
                  .pipe(jshint('./.jshintrc'))
                  .pipe(jshint.reporter(stylish)))
                  .pipe(isDevEnvironment ? gutil.noop() : uglify());

  // copy to dest
  return stream.done()
               .pipe(gulp.dest(bases.appTarget + "/js"));*/

  return browserify({
                      entries: ['./app/index.js'],
                      extensions: ['.jsx', '.js'],
                      paths: ['./node_modules', './app/node_modules','./app/js/'],
                      noparse: ['q', 'lodash', 'react', 'flux', 'moment']
                  })
                .transform(reactify)
                .bundle({ debug: isDevEnvironment })
                .pipe(source('client.js'))
                .pipe(gulp.dest(bases.appTarget));
});

gulp.task('post-build-cleanup', ['stylus', 'scripts'], function() {
  // delete unnecessary files in target
  return gulp.src([paths.md, paths.styl, paths.jsx, paths.css], {read: false, cwd: bases.appTarget})
             .pipe(clean({force: true}));
});

gulp.task('post-process-files', ['post-build-cleanup'], function () {
    return gulp.src(paths.rootHtml, {cwd: bases.appTarget})
                .pipe(preprocess({
                    inline: true,
                    context: {
                        AutoReload: isDevEnvironment
                    }
                }))
                .pipe(gulp.dest(bases.appTarget));
});

gulp.task('notify', ['post-build-cleanup'], function() {
  Notifier.notify({
        title: 'Build Completed',
        message: 'Refresh the app to see the updates!'
    });
})

gulp.task('watch', ['post-build-cleanup'], function() {
  gutil.log(gutil.colors.cyan('watching for changes...'));
  return gulp.watch([bases.src + paths.all,
                     "!" + bases.src + "node_modules/**"],
                    ['build']);
});

gulp.task('open', ['build'], function (cb) {
  exec('node_modules/.bin/nodewebkit target/app --remote-debugging-port=9222', {
    cwd: paths.root
  }, function (err, stdout, stderr) {
      //upon complete
  });
});

// https://github.com/mllrsohn/node-webkit-builder
gulp.task('package-app', ['build'], function () {
    var nw = new NwBuilder({
        version: '0.10.4',
        files: [ bases.appTarget + "**"],
        platforms: ['osx'],
        appName: "FinCharts",
        appVersion: "0.0.1",
        buildDir: bases.packageTarget,
        cacheDir: bases.target + "cache"
    });

    nw.on('log', function (msg) {
        gutil.log('node-webkit-builder', msg);
    });

     // return promise
    return nw.build().catch(function (err) {
        gutil.log('node-webkit-builder', err);
    });
});

gulp.task('build', ['copy', 'stylus', 'scripts', 'post-build-cleanup', 'post-process-files']);

gulp.task('default', function () {
  seq('clean-target', ['build', 'open']);
});

// dev task - enables watchers and autoreload
gulp.task('dev', function () {
  seq('setDevEnv', 'clean-target', ['build', 'watch', 'open', 'notify']);
});

gulp.task('package', function () {
  seq('clean-target', 'package-app');
});

<commit_msg>remove build node_modules path<commit_after>var gulp        = require('gulp'),
    source      = require('vinyl-source-stream'),
    clean       = require('gulp-clean'),
    stylus      = require('gulp-stylus'),
    nib         = require('nib'),
    jshint      = require('gulp-jshint'),
    rename      = require('gulp-rename'),
    concat      = require('gulp-concat'),
    stylish     = require('jshint-stylish'),
    preprocess  = require('gulp-preprocess'),
    minifyCSS   = require('gulp-minify-css'),
    browserify  = require('browserify');
    uglify      = require('gulp-uglify')
    seq         = require('run-sequence'),
    streamqueue = require('streamqueue'),
    react       = require('gulp-react'),
    reactify    = require('reactify');
    exec        = require('child_process').exec,
    NwBuilder   = require('node-webkit-builder'),
    gutil       = require('gulp-util'),
    Notifier    = new require('node-notifier')();

var bases = {
 root: '.',
 src: 'app/',
 target: 'target/',
 appTarget: 'target/app/',
 packageTarget: 'target/package/'
};

var paths = {
  all: "**",
  jsx: 'js/**/*.jsx',
  js: 'js/**/*.js',
  styl: "css/**/*.styl",
  rootStyl: 'css/index.styl',
  destStyl: 'css/index.css',
  rootJS: 'js/index.js',
  rootHtml: 'index.html',
  html: '**/*.html',
  md: '**/*.md',
  css: 'css/*/**'
};

var isDevEnvironment = false;

gulp.task('setDevEnv', function() {
    isDevEnvironment = true;
});

gulp.task('clean-target', function() {
  return gulp.src(bases.target, {read: false})
             .pipe(clean({force: true}));
});

gulp.task('copy', function() {
  return gulp.src(paths.all, {cwd: bases.src})
             .pipe(gulp.dest(bases.appTarget));
});

gulp.task('stylus', ['copy'], function () {
  return gulp.src(paths.rootStyl, {cwd: bases.appTarget})
            .pipe(stylus({errors: true, /*linenos: true,*/ use: [nib()]}))
            .pipe(isDevEnvironment ? gutil.noop() : minifyCSS({keepBreaks:true}))
            .pipe(rename(paths.destStyl))
            .pipe(gulp.dest(bases.appTarget));
});

gulp.task('scripts', ['copy'], function() {
  //var stream = streamqueue({objectMode: true});
  //var stream2 = streamqueue({objectMode: true});

  // js, jsx scripts
  /*stream.queue(gulp.src([paths.js, paths.jsx, paths.rootJS], {cwd: bases.appTarget})
                  .pipe(react())
                  .pipe(jshint('./.jshintrc'))
                  .pipe(jshint.reporter(stylish)))
                  .pipe(isDevEnvironment ? gutil.noop() : uglify());

  // copy to dest
  return stream.done()
               .pipe(gulp.dest(bases.appTarget + "/js"));*/

  return browserify({
                      entries: ['./app/index.js'],
                      extensions: ['.jsx', '.js'],
                      paths: ['./app/node_modules','./app/js/'],
                      noparse: ['q', 'lodash', 'react', 'flux', 'moment']
                  })
                .transform(reactify)
                .bundle({ debug: isDevEnvironment })
                .pipe(source('client.js'))
                .pipe(gulp.dest(bases.appTarget));
});

gulp.task('post-build-cleanup', ['stylus', 'scripts'], function() {
  // delete unnecessary files in target
  return gulp.src([paths.md, paths.styl, paths.jsx, paths.css], {read: false, cwd: bases.appTarget})
             .pipe(clean({force: true}));
});

gulp.task('post-process-files', ['post-build-cleanup'], function () {
    return gulp.src(paths.rootHtml, {cwd: bases.appTarget})
                .pipe(preprocess({
                    inline: true,
                    context: {
                        AutoReload: isDevEnvironment
                    }
                }))
                .pipe(gulp.dest(bases.appTarget));
});

gulp.task('notify', ['post-build-cleanup'], function() {
  Notifier.notify({
        title: 'Build Completed',
        message: 'Refresh the app to see the updates!'
    });
})

gulp.task('watch', ['post-build-cleanup'], function() {
  gutil.log(gutil.colors.cyan('watching for changes...'));
  return gulp.watch([bases.src + paths.all,
                     "!" + bases.src + "node_modules/**"],
                    ['build']);
});

gulp.task('open', ['build'], function (cb) {
  exec('node_modules/.bin/nodewebkit target/app --remote-debugging-port=9222', {
    cwd: paths.root
  }, function (err, stdout, stderr) {
      //upon complete
  });
});

// https://github.com/mllrsohn/node-webkit-builder
gulp.task('package-app', ['build'], function () {
    var nw = new NwBuilder({
        version: '0.10.4',
        files: [ bases.appTarget + "**"],
        platforms: ['osx'],
        appName: "FinCharts",
        appVersion: "0.0.1",
        buildDir: bases.packageTarget,
        cacheDir: bases.target + "cache"
    });

    nw.on('log', function (msg) {
        gutil.log('node-webkit-builder', msg);
    });

     // return promise
    return nw.build().catch(function (err) {
        gutil.log('node-webkit-builder', err);
    });
});

gulp.task('build', ['copy', 'stylus', 'scripts', 'post-build-cleanup', 'post-process-files']);

gulp.task('default', function () {
  seq('clean-target', ['build', 'open']);
});

// dev task - enables watchers and autoreload
gulp.task('dev', function () {
  seq('setDevEnv', 'clean-target', ['build', 'watch', 'open', 'notify']);
});

gulp.task('package', function () {
  seq('clean-target', 'package-app');
});

<|endoftext|>


<commit_before>/*
 * This program was produced for the U.S. Agency for International Development. It was prepared by the USAID | DELIVER PROJECT, Task Order 4. It is part of a project which utilizes code originally licensed under the terms of the Mozilla Public License (MPL) v2 and therefore is licensed under MPL v2 or later.
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the Mozilla Public License as published by the Mozilla Foundation, either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public License for more details.
 *
 * You should have received a copy of the Mozilla Public License along with this program. If not, see http://www.mozilla.org/MPL/
 */

function CreateEquipmentInventoryController($scope, $location, $routeParams, EquipmentInventory, Donors ,Equipments, SaveEquipmentInventory, Facility, EquipmentOperationalStatus, messageService, EquipmentTypesByProgram) {

  $scope.$parent.message = $scope.$parent.error = '';

  $scope.max_year = new Date().getFullYear();
  $scope.submitted = false;
  $scope.showError = false;

  Equipments.get(function (data) {
    $scope.equipments = data.equipments;
  });

  EquipmentTypesByProgram.get({programId: $routeParams.program}, function (data) {
    for (var i = 0; i < data.equipment_types.length; i++) {
      if (data.equipment_types[i].id.toString() === $routeParams.equipmentType) {
        $scope.equipmentType = data.equipment_types[i];
      }
    }
  }, {});

  if ($routeParams.id === undefined) {
    $scope.screenType = 'create';
    $scope.inventory = {};
    $scope.inventory.programId = $routeParams.program;
    $scope.inventory.facilityId = $routeParams.facility;

    Facility.get({id: $routeParams.facility}, function(data){
      $scope.facility = data.facility;
    });

    // set default of checkboxes so the submission does not become null and hence an error.
    $scope.inventory.replacementRecommended = false;
    $scope.inventory.dateLastAssessed = Date.now();
    $scope.inventory.isActive = true;

  } else {
    $scope.screenType = 'edit';
    EquipmentInventory.get({
      id: $routeParams.id
    }, function (data) {
      $scope.inventory = data.inventory;
      $scope.inventory.dateLastAssessed = $scope.inventory.dateLastAssessedString ;
      $scope.inventory.dateDecommissioned = $scope.inventory.dateDecommissionedString;
      Facility.get({ id: $scope.inventory.facilityId }, function(data){
        $scope.facility = data.facility;
      });
    });
  }

  EquipmentOperationalStatus.get(function(data){
     $scope.operationalStatusList = data.status;
  });

  Donors.get(function(data){
    $scope.donors = data.donors;
  });

  $scope.saveEquipment = function () {
    $scope.error = '';
    $scope.showError = true;
    if(!$scope.inventoryForm.$invalid ){
      SaveEquipmentInventory.save($scope.inventory, function (data) {
        $scope.$parent.message = messageService.get(data.success);
        $scope.$parent.selectedProgram = {id: $scope.inventory.programId};
        console.info($scope.$parent.selectedProgram);
        $location.path('/' + $routeParams.from + '/' + $scope.inventory.facilityId + '/' + $scope.inventory.programId + '/' + $routeParams.equipmentType);
      }, function (data) {
        $scope.error = data.error;
      });
    }else{
      $scope.submitted = true;
      $scope.error = messageService.get('message.equipment.inventory.data.invalid');
    }
  };

  $scope.cancelCreateEquipment = function () {
    $location.path('');
  };
}<commit_msg>Fix function calls to match calls in HTML UI<commit_after>/*
 * This program was produced for the U.S. Agency for International Development. It was prepared by the USAID | DELIVER PROJECT, Task Order 4. It is part of a project which utilizes code originally licensed under the terms of the Mozilla Public License (MPL) v2 and therefore is licensed under MPL v2 or later.
 *
 * This program is free software: you can redistribute it and/or modify it under the terms of the Mozilla Public License as published by the Mozilla Foundation, either version 2 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Mozilla Public License for more details.
 *
 * You should have received a copy of the Mozilla Public License along with this program. If not, see http://www.mozilla.org/MPL/
 */

function CreateEquipmentInventoryController($scope, $location, $routeParams, EquipmentInventory, Donors ,Equipments, SaveEquipmentInventory, Facility, EquipmentOperationalStatus, messageService, EquipmentTypesByProgram) {

  $scope.$parent.message = $scope.$parent.error = '';

  $scope.max_year = new Date().getFullYear();
  $scope.submitted = false;
  $scope.showError = false;

  Equipments.get(function (data) {
    $scope.equipments = data.equipments;
  });

  EquipmentTypesByProgram.get({programId: $routeParams.program}, function (data) {
    for (var i = 0; i < data.equipment_types.length; i++) {
      if (data.equipment_types[i].id.toString() === $routeParams.equipmentType) {
        $scope.equipmentType = data.equipment_types[i];
      }
    }
  }, {});

  if ($routeParams.id === undefined) {
    $scope.screenType = 'create';
    $scope.inventory = {};
    $scope.inventory.programId = $routeParams.program;
    $scope.inventory.facilityId = $routeParams.facility;

    Facility.get({id: $routeParams.facility}, function(data){
      $scope.facility = data.facility;
    });

    // set default of checkboxes so the submission does not become null and hence an error.
    $scope.inventory.replacementRecommended = false;
    $scope.inventory.dateLastAssessed = Date.now();
    $scope.inventory.isActive = true;

  } else {
    $scope.screenType = 'edit';
    EquipmentInventory.get({
      id: $routeParams.id
    }, function (data) {
      $scope.inventory = data.inventory;
      $scope.inventory.dateLastAssessed = $scope.inventory.dateLastAssessedString ;
      $scope.inventory.dateDecommissioned = $scope.inventory.dateDecommissionedString;
      Facility.get({ id: $scope.inventory.facilityId }, function(data){
        $scope.facility = data.facility;
      });
    });
  }

  EquipmentOperationalStatus.get(function(data){
     $scope.operationalStatusList = data.status;
  });

  Donors.get(function(data){
    $scope.donors = data.donors;
  });

  $scope.saveInventory = function () {
    $scope.error = '';
    $scope.showError = true;
    if(!$scope.inventoryForm.$invalid ){
      SaveEquipmentInventory.save($scope.inventory, function (data) {
        $scope.$parent.message = messageService.get(data.success);
        $scope.$parent.selectedProgram = {id: $scope.inventory.programId};
        console.info($scope.$parent.selectedProgram);
        $location.path('/' + $routeParams.from + '/' + $scope.inventory.facilityId + '/' + $scope.inventory.programId + '/' + $routeParams.equipmentType);
      }, function (data) {
        $scope.error = data.error;
      });
    }else{
      $scope.submitted = true;
      $scope.error = messageService.get('message.equipment.inventory.data.invalid');
    }
  };

  $scope.cancelCreateInventory = function () {
    $location.path('');
  };
}<|endoftext|>


<commit_before>var notifier        = require('node-notifier');
var dot             = require('dot-object');
var async           = require('async');
var fs              = require('fs');
var _               = require('lodash');
var gulp            = require('gulp');
var gulpConcat      = require('gulp-concat');
var gulpMinifyCss   = require('gulp-minify-css');
var gulpSourceMaps  = require('gulp-sourcemaps');
var gulpSass        = require('gulp-sass');
var gulpIf          = require('gulp-if');
var gulpEjs         = require('gulp-ejs');

var dirLib          = require('./lib/dir');
var Config          = require('./lib/config');
var Theme           = Config.get('theme');

console.log("Building theme", Theme );

var tplData = {};
var development = true;
var tasks = ['theme-sass', 'theme-fonts', 'images', 'theme-images', 'theme-views'];

gulp.task('theme-images', function(){
    gulp.src('./theme/'+Theme+'/img/**/*{png,gif,jpg,jpeg}').pipe( gulp.dest( __dirname+'/build/img') );
});

gulp.task('images', function(){
    gulp.src('./information/img/**/*{png,gif,jpg,jpeg}').pipe( gulp.dest( __dirname+'/build/images') );
});

gulp.task('theme-fonts', function(){
    gulp.src('./theme/'+Theme+'/fonts/**/*{ttf,woff,eof,svg}').pipe( gulp.dest( __dirname+'/build/fonts') );
});

gulp.task('theme-sass', function () {
    var startTime = Date.now();

    var stream = gulp.src('./theme/'+Theme+'/sass/app.scss')
        .pipe( gulpIf( development, gulpSourceMaps.init( __dirname+'/build/stylesheets' ) ))
        .pipe( gulpSass().on( 'error', gulpSass.logError) )
        .pipe( gulpIf( development, gulpSourceMaps.write() ) )
		.pipe( gulp.dest( __dirname+'/build/stylesheets' ) );

		stream.on("end", function(){
            var endTime = Date.now() - startTime;
            notifier.notify({
                title: 'SASS',
                message: endTime+'ms'
            });
		});
});

gulp.task('tplData', function(next){
    tplData = dirLib.mapTree( './information', "information");
});

gulp.task('theme-views', ['tplData'], function(next){

    gulp.src('./theme/'+Theme+'/view/*.ejs')
    	.pipe( gulpEjs( tplData, {
            ext: '.html'
        }))
    	.pipe( gulp.dest(__dirname+'/build/') );

    next();
});

gulp.task('watch', tasks, function(){
    gulp.watch('./theme/'+Theme+'/sass/**/*.scss', ['theme-sass']);
    gulp.watch('./theme/'+Theme+'/view/**/*.ejs', ['theme-views']);
    gulp.watch('./theme/'+Theme+'/img/**/*.{png,gif,jpg,jpeg}', ['theme-images']);
    gulp.watch('./theme/'+Theme+'/fonts/**/*.{ttf,woff,eof,svg}', ['theme-fonts']);
    gulp.watch('./information/**/*.*', ['theme-views']);
    gulp.watch('./information/**/*.{png,gif,jpg,jpeg}', ['images']);
});

gulp.task('default', tasks);
<commit_msg>In development output tplData in build folder as json file<commit_after>var notifier        = require('node-notifier');
var dot             = require('dot-object');
var async           = require('async');
var fs              = require('fs');
var _               = require('lodash');
var gulp            = require('gulp');
var gulpConcat      = require('gulp-concat');
var gulpMinifyCss   = require('gulp-minify-css');
var gulpSourceMaps  = require('gulp-sourcemaps');
var gulpSass        = require('gulp-sass');
var gulpIf          = require('gulp-if');
var gulpEjs         = require('gulp-ejs');

var dirLib          = require('./lib/dir');
var Config          = require('./lib/config');
var Theme           = Config.get('theme');

console.log("Building theme", Theme );

var tplData = {};
var development = true;
var tasks = ['theme-sass', 'theme-fonts', 'images', 'theme-images', 'theme-views'];

gulp.task('theme-images', function(){
    gulp.src('./theme/'+Theme+'/img/**/*{png,gif,jpg,jpeg}').pipe( gulp.dest( __dirname+'/build/img') );
});

gulp.task('images', function(){
    gulp.src('./information/img/**/*{png,gif,jpg,jpeg}').pipe( gulp.dest( __dirname+'/build/images') );
});

gulp.task('theme-fonts', function(){
    gulp.src('./theme/'+Theme+'/fonts/**/*{ttf,woff,eof,svg}').pipe( gulp.dest( __dirname+'/build/fonts') );
});

gulp.task('theme-sass', function () {
    var startTime = Date.now();

    var stream = gulp.src('./theme/'+Theme+'/sass/app.scss')
        .pipe( gulpIf( development, gulpSourceMaps.init( __dirname+'/build/stylesheets' ) ))
        .pipe( gulpSass().on( 'error', gulpSass.logError) )
        .pipe( gulpIf( development, gulpSourceMaps.write() ) )
		.pipe( gulp.dest( __dirname+'/build/stylesheets' ) );

		stream.on("end", function(){
            var endTime = Date.now() - startTime;
            notifier.notify({
                title: 'SASS',
                message: endTime+'ms'
            });
		});
});

gulp.task('tplData', function(next){
    tplData = dirLib.mapTree( './information', "information");
    if( development )
    {
        fs.writeFileSync( './build/tplData.json', JSON.stringify(tplData, null, " ") );
    }
});

gulp.task('theme-views', ['tplData'], function(next){

    gulp.src('./theme/'+Theme+'/view/*.ejs')
    	.pipe( gulpEjs( tplData, {
            ext: '.html'
        }))
    	.pipe( gulp.dest(__dirname+'/build/') );

    next();
});

gulp.task('watch', tasks, function(){
    gulp.watch('./theme/'+Theme+'/sass/**/*.scss', ['theme-sass']);
    gulp.watch('./theme/'+Theme+'/view/**/*.ejs', ['theme-views']);
    gulp.watch('./theme/'+Theme+'/img/**/*.{png,gif,jpg,jpeg}', ['theme-images']);
    gulp.watch('./theme/'+Theme+'/fonts/**/*.{ttf,woff,eof,svg}', ['theme-fonts']);
    gulp.watch('./information/**/*.*', ['theme-views']);
    gulp.watch('./information/**/*.{png,gif,jpg,jpeg}', ['images']);
});

gulp.task('default', tasks);
<|endoftext|>


<commit_before>var gulp = require('gulp');
var chug = require('gulp-chug');
var argv = require('yargs').argv;

config = [
    '--rootPath',
    argv.rootPath || '../../../web/assets/',
    '--nodeModulesPath',
    argv.nodeModulesPath || '../../../node_modules/',
    '--vendorPath',
    argv.vendorPath || '../../../vendor/'
];

gulp.task('admin', function() {
    gulp.src('web/assets/backend/Gulpfile.js', { read: false })
        .pipe(chug({ args: config }))
    ;
});

gulp.task('admin-watch', function() {
    gulp.src('web/assets/backend/Gulpfile.js', { read: false })
        .pipe(chug({ args: config, tasks: 'watch' }))
    ;
});

gulp.task('app', function() {
    gulp.src('web/assets/frontend/Gulpfile.js', { read: false })
        .pipe(chug({ args: config }))
    ;
});

gulp.task('app-watch', function() {
    gulp.src('web/assets/frontend/Gulpfile.js', { read: false })
        .pipe(chug({ args: config, tasks: 'watch' }))
    ;
});

gulp.task('default', ['admin', 'shop']);
<commit_msg>fix main gulpfile<commit_after>var gulp = require('gulp');
var chug = require('gulp-chug');
var argv = require('yargs').argv;

config = [
    '--rootPath',
    argv.rootPath || '../../../web/assets/',
    '--nodeModulesPath',
    argv.nodeModulesPath || '../../../node_modules/',
    '--vendorPath',
    argv.vendorPath || '../../../vendor/'
];

gulp.task('admin', function() {
    gulp.src('web/assets/backend/Gulpfile.js', { read: false })
        .pipe(chug({ args: config }))
    ;
});

gulp.task('admin-watch', function() {
    gulp.src('web/assets/backend/Gulpfile.js', { read: false })
        .pipe(chug({ args: config, tasks: 'watch' }))
    ;
});

gulp.task('app', function() {
    gulp.src('web/assets/frontend/Gulpfile.js', { read: false })
        .pipe(chug({ args: config }))
    ;
});

gulp.task('app-watch', function() {
    gulp.src('web/assets/frontend/Gulpfile.js', { read: false })
        .pipe(chug({ args: config, tasks: 'watch' }))
    ;
});

gulp.task('default', ['admin', 'app']);
<|endoftext|>


<commit_before>var gulp = require('gulp')
var spawn = require('child_process').spawn
var mocha = require('mocha')

gulp.task('test', function (cb) {
    spawn('cmd', ['/c', 'node_modules\\.bin\\mocha.cmd', '-R', 'spec'], {stdio: 'inherit'})
        .on('close', function() {
            cb()
        })
})

gulp.task('default', function() {
    gulp.run('test')

    gulp.watch(['index.js', 'lib/**/*', 'test/**/*'], function() {
        gulp.run('test')
    })
})<commit_msg>code style in gulpfile<commit_after>var gulp = require('gulp')
var spawn = require('child_process').spawn
var mocha = require('mocha')

gulp.task('test', function(cb) {
    spawn('cmd', ['/c', 'node_modules\\.bin\\mocha.cmd', '-R', 'spec'], {stdio: 'inherit'})
        .on('close', function() {
            cb()
        })
})

gulp.task('default', function() {
    gulp.run('test')

    gulp.watch(['index.js', 'lib/**/*', 'test/**/*'], function() {
        gulp.run('test')
    })
})<|endoftext|>


<commit_before>/**
 * Define Gulp Objects
 */
var gulp            = require('gulp'),
    autoprefixer    = require('gulp-autoprefixer'),
    coffee          = require('gulp-coffee'),
    concat          = require('gulp-concat'),
    files           = require('main-bower-files'),
    filter          = require('gulp-filter'),
    fs              = require('fs'),
    flatten         = require('gulp-flatten'),
    include         = require('gulp-include'),
    minifyCss       = require('gulp-minify-css'),
    ngAnnotate      = require('gulp-ng-annotate'),
    ngClassify      = require('gulp-ng-classify'),
    plumber         = require('gulp-plumber'),
    sass            = require('gulp-sass'),
    uglify          = require('gulp-uglify'),
    watch           = require('gulp-watch'),
    yaml            = require('js-yaml');

// ----------------------------------------------------------------------------

/**
 * Define Configuration object
 */
var config = yaml.load(fs.readFileSync('gulp_config.yaml', 'utf-8'));

// ----------------------------------------------------------------------------

/**
 * Compile SASS into CSS
 */
gulp.task('compile-css', function () {
    gulp.src(config.src.sass)
        .pipe(plumber())
        .pipe(sass())
        .pipe(autoprefixer("> 1%"))
        .pipe(gulp.dest(config.dest.css))
        .pipe(minifyCss())
        .pipe(gulp.dest(config.dest.css));
});

// ----------------------------------------------------------------------------

/**
 * Compile CoffeeScript and Angular Code into JS
 */
gulp.task('compile-js', function () {
    gulp.src(config.src.coffee.base)
        .pipe(plumber())
        .pipe(include())
        .pipe(ngClassify())
        .pipe(coffee({bare: true}))
        .pipe(ngAnnotate())
        .pipe(gulp.dest(config.dest.js));
});

gulp.task('test', function() {
    console.log(config);
});

// ----------------------------------------------------------------------------

/**
 * Create Watch Scripts
 */
gulp.task('default', function () {
    var jsFilter        = filter('*.js'),
        cssFilter       = filter('*.css'),
        fontFilter      = filter(['*.eot', '*.woff', '*.svg', '*.ttf']),
        bower_files     = files();

    // If you have additional files defined, add them in
    if (config.additional) {
        var bower_files = files().concat(config.additional);
    }

    watch({glob: config.src.coffee.all, emitOnGlob: false}, ['compile-js']);
    watch({glob: config.src.sass, emitOnGlob: false}, ['compile-css']);

    gulp.src(bower_files)
        // Combine all JS Files
        .pipe(jsFilter)
        .pipe(uglify())
        .pipe(concat('dependencies.min.js'))
        .pipe(gulp.dest(config.dest.js))
        .pipe(jsFilter.restore())

        // Combine all CSS files
        .pipe(cssFilter)
        .pipe(minifyCss())
        .pipe(concat('dependencies.min.css'))
        .pipe(gulp.dest(config.dest.css))
        .pipe(cssFilter.restore())

        // Flatten fonts
        .pipe(fontFilter)
        .pipe(flatten())
        .pipe(gulp.dest(config.dest.fonts));
});
<commit_msg>Remove emit on glob<commit_after>/**
 * Define Gulp Objects
 */
var gulp            = require('gulp'),
    autoprefixer    = require('gulp-autoprefixer'),
    coffee          = require('gulp-coffee'),
    concat          = require('gulp-concat'),
    files           = require('main-bower-files'),
    filter          = require('gulp-filter'),
    fs              = require('fs'),
    flatten         = require('gulp-flatten'),
    include         = require('gulp-include'),
    minifyCss       = require('gulp-minify-css'),
    ngAnnotate      = require('gulp-ng-annotate'),
    ngClassify      = require('gulp-ng-classify'),
    plumber         = require('gulp-plumber'),
    sass            = require('gulp-sass'),
    uglify          = require('gulp-uglify'),
    watch           = require('gulp-watch'),
    yaml            = require('js-yaml');

// ----------------------------------------------------------------------------

/**
 * Define Configuration object
 */
var config = yaml.load(fs.readFileSync('gulp_config.yaml', 'utf-8'));

// ----------------------------------------------------------------------------

/**
 * Compile SASS into CSS
 */
gulp.task('compile-css', function () {
    gulp.src(config.src.sass)
        .pipe(plumber())
        .pipe(sass())
        .pipe(autoprefixer("> 1%"))
        .pipe(gulp.dest(config.dest.css))
        .pipe(minifyCss())
        .pipe(gulp.dest(config.dest.css));
});

// ----------------------------------------------------------------------------

/**
 * Compile CoffeeScript and Angular Code into JS
 */
gulp.task('compile-js', function () {
    gulp.src(config.src.coffee.base)
        .pipe(plumber())
        .pipe(include())
        .pipe(ngClassify())
        .pipe(coffee({bare: true}))
        .pipe(ngAnnotate())
        .pipe(gulp.dest(config.dest.js));
});

gulp.task('test', function() {
    console.log(config);
});

// ----------------------------------------------------------------------------

/**
 * Create Watch Scripts
 */
gulp.task('default', function () {
    var jsFilter        = filter('*.js'),
        cssFilter       = filter('*.css'),
        fontFilter      = filter(['*.eot', '*.woff', '*.svg', '*.ttf']),
        bower_files     = files();

    // If you have additional files defined, add them in
    if (config.additional) {
        var bower_files = files().concat(config.additional);
    }

    watch({glob: config.src.coffee.all}, ['compile-js']);
    watch({glob: config.src.sass}, ['compile-css']);

    gulp.src(bower_files)
        // Combine all JS Files
        .pipe(jsFilter)
        .pipe(uglify())
        .pipe(concat('dependencies.min.js'))
        .pipe(gulp.dest(config.dest.js))
        .pipe(jsFilter.restore())

        // Combine all CSS files
        .pipe(cssFilter)
        .pipe(minifyCss())
        .pipe(concat('dependencies.min.css'))
        .pipe(gulp.dest(config.dest.css))
        .pipe(cssFilter.restore())

        // Flatten fonts
        .pipe(fontFilter)
        .pipe(flatten())
        .pipe(gulp.dest(config.dest.fonts));
});
<|endoftext|>


<commit_before>var browserify = require('browserify');
var gulp   = require('gulp');
var babel  = require('gulp-babel');
var concat = require('gulp-concat');
var del    = require('del');
var rename = require('gulp-rename');
var templ  = require('gulp-template');
var data   = require('gulp-data');
var runseq = require('run-sequence');
var rjs    = require('requirejs');
var merge  = require('merge-stream');
var zip    = require('gulp-zip');
var mkdirp = require('mkdirp');
var source = require('vinyl-source-stream');
var fs     = require('fs');
var packg  = require('./package.json');

gulp.task('babel', function () {
  return gulp.src('src/**/*.js')
    .pipe(babel({ modules: 'ignore' }))
    .pipe(gulp.dest('lib/'));
});

gulp.task('clean-lib', function (cb) {
  del('lib', cb);
});

var nodelib = function (entry, standalone, name) {
  name = name || standalone + '.js';

  var opts = {
    entries: './node_modules/' + entry
  };
  if (standalone) opts.standalone = standalone;

  return function () {
    return browserify(opts)
      .bundle()
      .pipe(source(name))
      .pipe(gulp.dest('build/_deps/'));
  };
};

gulp.task('lib-debug', nodelib('debug/browser.js', 'debug'));
gulp.task('lib-semvercmp', nodelib('semver-compare/index.js', 'semvercmp'));
gulp.task('lib-symbol', nodelib('es6-symbol/implement.js', false, 'es6-symbol.js'));
gulp.task('lib-regexp-quote', nodelib('regexp-quote/regexp-quote.js', 'regexp-quote'));
gulp.task('lib-sistyl', nodelib('sistyl/lib/sistyl.js', 'sistyl'));

gulp.task('dependencies', [
  'lib-debug',
  'lib-semvercmp',
  'lib-sistyl',
  'lib-symbol',
  'lib-regexp-quote'
]);

gulp.task('rjs', function (done) {
  var npm = 'node_modules/';
  packg.builtAt = Date.now();
  var packgString = JSON.stringify(packg, null, 2);
  delete packg.builtAt;
  rjs.optimize({
    baseUrl: './',
    name: 'extplug/main',
    include: [ 'extplug/ExtPlug' ],
    paths: {
      // plug-modules defines, these are defined at runtime
      // so the r.js optimizer can't find them
      plug: 'empty:',
      lang: 'empty:',
      backbone: 'empty:',
      jquery: 'empty:',
      underscore: 'empty:',
      meld: npm + 'meld/meld',
      sistyl: 'build/_deps/sistyl',
      extplug: 'lib',
      'plug-modules': npm + 'plug-modules/plug-modules',
      'debug': 'build/_deps/debug',
      'regexp-quote': 'build/_deps/regexp-quote',
      'semver-compare': 'build/_deps/semvercmp'
    },
    rawText: {
      'extplug/package': 'define(' + packgString + ')'
    },
    insertRequire: [ 'extplug/main' ],
    optimize: 'none',
    out: function (text) {
      mkdirp('build', function (e) {
        if (e) {
          done(e);
        }
        else {
          fs.writeFile('build/build.rjs.js', text, done);
        }
      });
    }
  });
});

gulp.task('concat', function () {
  return gulp.src([ 'build/_deps/es6-symbol.js', 'build/build.rjs.js' ])
    .pipe(concat('extplug.code.js'))
    .pipe(gulp.dest('build/'));
});

gulp.task('build', [ 'concat' ], function () {
  return gulp.src('src/loader.js.template')
    .pipe(data(function (file, cb) {
      fs.readFile('build/extplug.code.js', 'utf8', function (e, c) {
        if (e) cb(e);
        else cb(null, { code: c });
      });
    }))
    .pipe(templ())
    .pipe(rename('extplug.js'))
    .pipe(gulp.dest('build/'));
});

gulp.task('clean-build', function (cb) {
  del('build', cb);
});

gulp.task('chrome-unpacked', function (cb) {
  return merge(
    gulp.src([ 'extensions/chrome/main.js', 'extensions/chrome/manifest.json' ])
      .pipe(templ(packg))
      .pipe(gulp.dest('build/chrome/')),

    gulp.src([ 'build/extplug.js' ])
      .pipe(concat('extplug.js'))
      .pipe(gulp.dest('build/chrome/'))
  );
});

gulp.task('chrome-pack', function () {
  return gulp.src('build/chrome/*')
    .pipe(zip('extplug.chrome.zip'))
    .pipe(gulp.dest('build/'));
});

gulp.task('chrome', function (cb) {
  runseq('chrome-unpacked', 'chrome-pack', cb);
});

gulp.task('firefox', function () {
  return merge(
    gulp.src([ 'extensions/firefox/*' ])
      .pipe(templ(packg))
      .pipe(gulp.dest('build/firefox/')),

    gulp.src([ 'build/extplug.js' ])
      .pipe(gulp.dest('build/firefox/data/'))
  );
});

gulp.task('userscript-meta', function () {
  return gulp.src([ 'extensions/userscript/extplug.user.js' ])
    .pipe(templ(packg))
    .pipe(rename('extplug.meta.user.js'))
    .pipe(gulp.dest('build/'));
});

gulp.task('userscript', [ 'userscript-meta' ], function () {
  return gulp.src([ 'build/extplug.meta.user.js', 'build/extplug.js' ])
    .pipe(concat('extplug.user.js'))
    .pipe(gulp.dest('build/'));
});

gulp.task('clean', [ 'clean-lib', 'clean-build' ]);

gulp.task('default', function (cb) {
  runseq(
    'clean',
    [ 'babel', 'dependencies' ],
    'rjs',
    'build',
    [ 'chrome', 'firefox', 'userscript' ],
    cb
  );
});
<commit_msg>build: sort requires<commit_after>var babel = require('gulp-babel');
var browserify = require('browserify');
var concat = require('gulp-concat');
var data = require('gulp-data');
var del = require('del');
var fs = require('fs');
var gulp = require('gulp');
var merge = require('merge-stream');
var mkdirp = require('mkdirp');
var packg  = require('./package.json');
var rename = require('gulp-rename');
var rjs = require('requirejs');
var runseq = require('run-sequence');
var source = require('vinyl-source-stream');
var template = require('gulp-template');
var zip = require('gulp-zip');

gulp.task('babel', function () {
  return gulp.src('src/**/*.js')
    .pipe(babel({ modules: 'ignore' }))
    .pipe(gulp.dest('lib/'));
});

gulp.task('clean-lib', function (cb) {
  del('lib', cb);
});

var nodelib = function (entry, standalone, name) {
  name = name || standalone + '.js';

  var opts = {
    entries: './node_modules/' + entry
  };
  if (standalone) opts.standalone = standalone;

  return function () {
    return browserify(opts)
      .bundle()
      .pipe(source(name))
      .pipe(gulp.dest('build/_deps/'));
  };
};

gulp.task('lib-debug', nodelib('debug/browser.js', 'debug'));
gulp.task('lib-semvercmp', nodelib('semver-compare/index.js', 'semvercmp'));
gulp.task('lib-symbol', nodelib('es6-symbol/implement.js', false, 'es6-symbol.js'));
gulp.task('lib-regexp-quote', nodelib('regexp-quote/regexp-quote.js', 'regexp-quote'));
gulp.task('lib-sistyl', nodelib('sistyl/lib/sistyl.js', 'sistyl'));

gulp.task('dependencies', [
  'lib-debug',
  'lib-semvercmp',
  'lib-sistyl',
  'lib-symbol',
  'lib-regexp-quote'
]);

gulp.task('rjs', function (done) {
  var npm = 'node_modules/';
  packg.builtAt = Date.now();
  var packgString = JSON.stringify(packg, null, 2);
  delete packg.builtAt;
  rjs.optimize({
    baseUrl: './',
    name: 'extplug/main',
    include: [ 'extplug/ExtPlug' ],
    paths: {
      // plug-modules defines, these are defined at runtime
      // so the r.js optimizer can't find them
      plug: 'empty:',
      lang: 'empty:',
      backbone: 'empty:',
      jquery: 'empty:',
      underscore: 'empty:',
      meld: npm + 'meld/meld',
      sistyl: 'build/_deps/sistyl',
      extplug: 'lib',
      'plug-modules': npm + 'plug-modules/plug-modules',
      'debug': 'build/_deps/debug',
      'regexp-quote': 'build/_deps/regexp-quote',
      'semver-compare': 'build/_deps/semvercmp'
    },
    rawText: {
      'extplug/package': 'define(' + packgString + ')'
    },
    insertRequire: [ 'extplug/main' ],
    optimize: 'none',
    out: function (text) {
      mkdirp('build', function (e) {
        if (e) {
          done(e);
        }
        else {
          fs.writeFile('build/build.rjs.js', text, done);
        }
      });
    }
  });
});

gulp.task('concat', function () {
  return gulp.src([ 'build/_deps/es6-symbol.js', 'build/build.rjs.js' ])
    .pipe(concat('extplug.code.js'))
    .pipe(gulp.dest('build/'));
});

gulp.task('build', [ 'concat' ], function () {
  return gulp.src('src/loader.js.template')
    .pipe(data(function (file, cb) {
      fs.readFile('build/extplug.code.js', 'utf8', function (e, c) {
        if (e) cb(e);
        else cb(null, { code: c });
      });
    }))
    .pipe(template())
    .pipe(rename('extplug.js'))
    .pipe(gulp.dest('build/'));
});

gulp.task('clean-build', function (cb) {
  del('build', cb);
});

gulp.task('chrome-unpacked', function (cb) {
  return merge(
    gulp.src([ 'extensions/chrome/main.js', 'extensions/chrome/manifest.json' ])
      .pipe(template(packg))
      .pipe(gulp.dest('build/chrome/')),

    gulp.src([ 'build/extplug.js' ])
      .pipe(concat('extplug.js'))
      .pipe(gulp.dest('build/chrome/'))
  );
});

gulp.task('chrome-pack', function () {
  return gulp.src('build/chrome/*')
    .pipe(zip('extplug.chrome.zip'))
    .pipe(gulp.dest('build/'));
});

gulp.task('chrome', function (cb) {
  runseq('chrome-unpacked', 'chrome-pack', cb);
});

gulp.task('firefox', function () {
  return merge(
    gulp.src([ 'extensions/firefox/*' ])
      .pipe(template(packg))
      .pipe(gulp.dest('build/firefox/')),

    gulp.src([ 'build/extplug.js' ])
      .pipe(gulp.dest('build/firefox/data/'))
  );
});

gulp.task('userscript-meta', function () {
  return gulp.src([ 'extensions/userscript/extplug.user.js' ])
    .pipe(template(packg))
    .pipe(rename('extplug.meta.user.js'))
    .pipe(gulp.dest('build/'));
});

gulp.task('userscript', [ 'userscript-meta' ], function () {
  return gulp.src([ 'build/extplug.meta.user.js', 'build/extplug.js' ])
    .pipe(concat('extplug.user.js'))
    .pipe(gulp.dest('build/'));
});

gulp.task('clean', [ 'clean-lib', 'clean-build' ]);

gulp.task('default', function (cb) {
  runseq(
    'clean',
    [ 'babel', 'dependencies' ],
    'rjs',
    'build',
    [ 'chrome', 'firefox', 'userscript' ],
    cb
  );
});
<|endoftext|>


<commit_before>var _ = require('lodash'),
    Promise = require('bluebird'),
    common = require('../../lib/common'),
    db = require('../db'),
    schema = require('./schema'),
    clients = require('./clients');

function addTableColumn(tableName, table, columnName, columnSpec = schema[tableName][columnName]) {
    var column;

    // creation distinguishes between text with fieldtype, string with maxlength and all others
    if (columnSpec.type === 'text' && Object.prototype.hasOwnProperty.call(columnSpec, 'fieldtype')) {
        column = table[columnSpec.type](columnName, columnSpec.fieldtype);
    } else if (columnSpec.type === 'string') {
        if (Object.prototype.hasOwnProperty.call(columnSpec, 'maxlength')) {
            column = table[columnSpec.type](columnName, columnSpec.maxlength);
        } else {
            column = table[columnSpec.type](columnName, 191);
        }
    } else {
        column = table[columnSpec.type](columnName);
    }

    if (Object.prototype.hasOwnProperty.call(columnSpec, 'nullable') && columnSpec.nullable === true) {
        column.nullable();
    } else {
        column.nullable(false);
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'primary') && columnSpec.primary === true) {
        column.primary();
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'unique') && columnSpec.unique) {
        column.unique();
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'unsigned') && columnSpec.unsigned) {
        column.unsigned();
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'references')) {
        // check if table exists?
        column.references(columnSpec.references);
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'defaultTo')) {
        column.defaultTo(columnSpec.defaultTo);
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'index') && columnSpec.index === true) {
        column.index();
    }
}

function addColumn(tableName, column, transaction, columnSpec) {
    return (transaction || db.knex).schema.table(tableName, function (table) {
        addTableColumn(tableName, table, column, columnSpec);
    });
}

function dropColumn(table, column, transaction) {
    return (transaction || db.knex).schema.table(table, function (table) {
        table.dropColumn(column);
    });
}

function addUnique(table, column, transaction) {
    return (transaction || db.knex).schema.table(table, function (table) {
        table.unique(column);
    });
}

function dropUnique(table, column, transaction) {
    return (transaction || db.knex).schema.table(table, function (table) {
        table.dropUnique(column);
    });
}

/**
 * https://github.com/tgriesser/knex/issues/1303
 * createTableIfNotExists can throw error if indexes are already in place
 */
function createTable(table, transaction) {
    return (transaction || db.knex).schema.hasTable(table)
        .then(function (exists) {
            if (exists) {
                return;
            }

            return (transaction || db.knex).schema.createTable(table, function (t) {
                var columnKeys = _.keys(schema[table]);
                _.each(columnKeys, function (column) {
                    return addTableColumn(table, t, column);
                });
            });
        });
}

function deleteTable(table, transaction) {
    return (transaction || db.knex).schema.dropTableIfExists(table);
}

function getTables(transaction) {
    var client = (transaction || db.knex).client.config.client;

    if (_.includes(_.keys(clients), client)) {
        return clients[client].getTables(transaction);
    }

    return Promise.reject(common.i18n.t('notices.data.utils.index.noSupportForDatabase', {client: client}));
}

function getIndexes(table, transaction) {
    var client = (transaction || db.knex).client.config.client;

    if (_.includes(_.keys(clients), client)) {
        return clients[client].getIndexes(table, transaction);
    }

    return Promise.reject(common.i18n.t('notices.data.utils.index.noSupportForDatabase', {client: client}));
}

function getColumns(table, transaction) {
    var client = (transaction || db.knex).client.config.client;

    if (_.includes(_.keys(clients), client)) {
        return clients[client].getColumns(table);
    }

    return Promise.reject(common.i18n.t('notices.data.utils.index.noSupportForDatabase', {client: client}));
}

function checkTables(transaction) {
    var client = (transaction || db.knex).client.config.client;

    if (client === 'mysql') {
        return clients[client].checkPostTable();
    }
}

const createLog = type => msg => common.logging[type](msg);

function createColumnMigration(...migrations) {
    async function runColumnMigration(conn, migration) {
        const {
            table,
            column,
            dbIsInCorrectState,
            operation,
            operationVerb,
            columnDefinition
        } = migration;

        const hasColumn = await conn.schema.hasColumn(table, column);
        const isInCorrectState = dbIsInCorrectState(hasColumn);

        const log = createLog(isInCorrectState ? 'info' : 'warn');

        log(`${operationVerb} ${table}.${column}`);

        if (!isInCorrectState) {
            await operation(table, column, conn, columnDefinition);
        }
    }

    return async function columnMigration(options) {
        const conn = options.transacting || options.connection;

        for (const migration of migrations) {
            await runColumnMigration(conn, migration);
        }
    };
}

module.exports = {
    checkTables: checkTables,
    createTable: createTable,
    deleteTable: deleteTable,
    getTables: getTables,
    getIndexes: getIndexes,
    addUnique: addUnique,
    dropUnique: dropUnique,
    addColumn: addColumn,
    dropColumn: dropColumn,
    getColumns: getColumns,
    createColumnMigration
};
<commit_msg>Fixed log usage for columnMigration command<commit_after>var _ = require('lodash'),
    Promise = require('bluebird'),
    common = require('../../lib/common'),
    db = require('../db'),
    schema = require('./schema'),
    clients = require('./clients');

function addTableColumn(tableName, table, columnName, columnSpec = schema[tableName][columnName]) {
    var column;

    // creation distinguishes between text with fieldtype, string with maxlength and all others
    if (columnSpec.type === 'text' && Object.prototype.hasOwnProperty.call(columnSpec, 'fieldtype')) {
        column = table[columnSpec.type](columnName, columnSpec.fieldtype);
    } else if (columnSpec.type === 'string') {
        if (Object.prototype.hasOwnProperty.call(columnSpec, 'maxlength')) {
            column = table[columnSpec.type](columnName, columnSpec.maxlength);
        } else {
            column = table[columnSpec.type](columnName, 191);
        }
    } else {
        column = table[columnSpec.type](columnName);
    }

    if (Object.prototype.hasOwnProperty.call(columnSpec, 'nullable') && columnSpec.nullable === true) {
        column.nullable();
    } else {
        column.nullable(false);
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'primary') && columnSpec.primary === true) {
        column.primary();
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'unique') && columnSpec.unique) {
        column.unique();
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'unsigned') && columnSpec.unsigned) {
        column.unsigned();
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'references')) {
        // check if table exists?
        column.references(columnSpec.references);
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'defaultTo')) {
        column.defaultTo(columnSpec.defaultTo);
    }
    if (Object.prototype.hasOwnProperty.call(columnSpec, 'index') && columnSpec.index === true) {
        column.index();
    }
}

function addColumn(tableName, column, transaction, columnSpec) {
    return (transaction || db.knex).schema.table(tableName, function (table) {
        addTableColumn(tableName, table, column, columnSpec);
    });
}

function dropColumn(table, column, transaction) {
    return (transaction || db.knex).schema.table(table, function (table) {
        table.dropColumn(column);
    });
}

function addUnique(table, column, transaction) {
    return (transaction || db.knex).schema.table(table, function (table) {
        table.unique(column);
    });
}

function dropUnique(table, column, transaction) {
    return (transaction || db.knex).schema.table(table, function (table) {
        table.dropUnique(column);
    });
}

/**
 * https://github.com/tgriesser/knex/issues/1303
 * createTableIfNotExists can throw error if indexes are already in place
 */
function createTable(table, transaction) {
    return (transaction || db.knex).schema.hasTable(table)
        .then(function (exists) {
            if (exists) {
                return;
            }

            return (transaction || db.knex).schema.createTable(table, function (t) {
                var columnKeys = _.keys(schema[table]);
                _.each(columnKeys, function (column) {
                    return addTableColumn(table, t, column);
                });
            });
        });
}

function deleteTable(table, transaction) {
    return (transaction || db.knex).schema.dropTableIfExists(table);
}

function getTables(transaction) {
    var client = (transaction || db.knex).client.config.client;

    if (_.includes(_.keys(clients), client)) {
        return clients[client].getTables(transaction);
    }

    return Promise.reject(common.i18n.t('notices.data.utils.index.noSupportForDatabase', {client: client}));
}

function getIndexes(table, transaction) {
    var client = (transaction || db.knex).client.config.client;

    if (_.includes(_.keys(clients), client)) {
        return clients[client].getIndexes(table, transaction);
    }

    return Promise.reject(common.i18n.t('notices.data.utils.index.noSupportForDatabase', {client: client}));
}

function getColumns(table, transaction) {
    var client = (transaction || db.knex).client.config.client;

    if (_.includes(_.keys(clients), client)) {
        return clients[client].getColumns(table);
    }

    return Promise.reject(common.i18n.t('notices.data.utils.index.noSupportForDatabase', {client: client}));
}

function checkTables(transaction) {
    var client = (transaction || db.knex).client.config.client;

    if (client === 'mysql') {
        return clients[client].checkPostTable();
    }
}

const createLog = type => msg => common.logging[type](msg);

function createColumnMigration(...migrations) {
    async function runColumnMigration(conn, migration) {
        const {
            table,
            column,
            dbIsInCorrectState,
            operation,
            operationVerb,
            columnDefinition
        } = migration;

        const hasColumn = await conn.schema.hasColumn(table, column);
        const isInCorrectState = dbIsInCorrectState(hasColumn);

        const log = createLog(isInCorrectState ? 'warn' : 'info');

        log(`${operationVerb} ${table}.${column}`);

        if (!isInCorrectState) {
            await operation(table, column, conn, columnDefinition);
        }
    }

    return async function columnMigration(options) {
        const conn = options.transacting || options.connection;

        for (const migration of migrations) {
            await runColumnMigration(conn, migration);
        }
    };
}

module.exports = {
    checkTables: checkTables,
    createTable: createTable,
    deleteTable: deleteTable,
    getTables: getTables,
    getIndexes: getIndexes,
    addUnique: addUnique,
    dropUnique: dropUnique,
    addColumn: addColumn,
    dropColumn: dropColumn,
    getColumns: getColumns,
    createColumnMigration
};
<|endoftext|>


<commit_before>'use strict';

const lib = require('lib');

const Command = require('cmnd').Command;
const APIResource = require('api-res');
const Credentials = require('../../credentials.js');

const chalk = require('chalk');
const inquirer = require('inquirer');
const async = require('async');

const path = require('path');
const fs = require('fs');

const host = 'api.polybit.com';
//const host = 'api.jacobb.us'

const port = 443;

class TaskCreate extends Command {

  constructor() {

    super('task', 'create');

  }

  help() {

    return {
      description: 'Create a Scheduled Task from a StdLib service',
      args: [
        'service',
        'function',
      ],
      flags: {
        v: 'Service version (default lastest release)'
      },
      vflags: {
        version: 'Service version (default lastest release)'
      }
    };

  }

  run(params, callback) {

    let service = params.args[0];
    let f = params.args[1];
    let version = (params.flags.v || params.vflags.version || [])[0] || 'latest';

    if (!service) {
      console.log();
      console.log(chalk.bold.red('Oops!'));
      console.log();
      console.log(`Please specify a service name`);
      console.log();
      return callback(null);
    }

    if (!f) {
      f = '';
    }

    async.waterfall([
      async.apply(getServiceDetails, service, f, version),
      getTokens,
      promptQuestions,
    ], (err, results) => {

      let params = {
        name: results.name,
        library_token_id: results.library_token_id,
        service_id: results.service_id,
        function_name: results.function_name,
        frequency: convertFrequency(results.frequency),
        period: convertPeriod(results.period),
        period_offset: convertPeriodOffset(results.period_offset, results.weekly_period_offset),
        kwargs: results.kwargs,
      }

      console.log(params);
      let resource = new APIResource(host, port);

      resource.authorize(Credentials.read('ACCESS_TOKEN'));
      resource.request('/v1/scheduled_tasks').create({}, params, (err, response) => {

        if (err) {
          console.log(err);
          return callback(err);
        }

        console.log(response)
        return callback(null);

      });
    });

  }

}

function getServiceDetails(service, f, version, callback) {

  let params = {
    name:  service,
    include_private: true,
  }

  if (version === 'latest') {
    params.latest = true;
  } else {
    params.version = version;
  }

  let resource = new APIResource(host, port);

  resource.authorize(Credentials.read('ACCESS_TOKEN'));
  resource.request('/v1/services').index(params, (err, response) => {

    if (err) {
      return callback(err);
    }

    if (!response.data.length) {
      return callback(new Error('Could not find service'));
    }

    let selectedService = response.data[0];

    let details = {
      service_id: selectedService.id,
      function_name: f,
    };

    if (selectedService.definitions_json[f]) {
      details['fArgs'] = selectedService.definitions_json[f].params;
    }
    console.log(selectedService);
    return callback(null, details);

  });

}

function getTokens(prev, callback) {

  let resource = new APIResource(host, port);

  resource.authorize(Credentials.read('ACCESS_TOKEN'));
  resource.request('v1/dashboard/library_tokens').index({}, (err, response) => {

    if (err) {
      return callback(err);
    }

    if (!response.data.length) {
      return callback(new Error('You have no library tokens'));
    }

    prev.tokens = response.data.reduce((tokens, current) => {
      tokens.push(current.id.toString());
      return tokens;
    }, []);

    return callback(null, prev);

  });

}

function promptQuestions(prev, callback) {

  let questions;

  if (prev.fArgs) {
    questions = prev.fArgs.reduce((prompts, arg, index) => {
      prompts.push({
        name: arg.name,
        type: 'input',
        message: `Enter param for argument ${arg.name} (type ${arg.type})`,
        argument: true,
      });
      return prompts;
    }, []);
  } else {
    questions = [];
  }

  questions = questions.concat([{
    name: 'library_token_id',
    type: 'list',
    message: 'Pick a library token to use',
    choices: prev.tokens
  }, {
    name: 'period',
    type: 'list',
    message: 'Run service every: ',
    choices: ['minute', 'hour', 'day', 'week']
  }, {
    name: 'frequency',
    type: 'list',
    message: (answers) => `How ofter per ${answers.period}`,
    choices: ['once'],
    when: (answers) => answers.period === 'minute'
  }, {
    name: 'frequency',
    type: 'list',
    message: (answers) => `How ofter per ${answers.period}`,
    choices: ['once', 'twice', 'three times', 'four times', 'five times',
              'six times', 'ten times', 'twelve times', 'fifteen times',
              'twenty times', 'thirty times'],
    when: (answers) => answers.period === 'hour'
  }, {
    name: 'frequency',
    type: 'list',
    message: (answers) => `How ofter per ${answers.period}`,
    choices: ['once', 'twice', 'three times', 'four times', 'six times', 'twelve times'],
    when: (answers) => answers.period === 'day'
  }, {
    name: 'frequency',
    type: 'list',
    message: (answers) => `How ofter per ${answers.period}`,
    choices: ['once'],
    when: (answers) => answers.period === 'week'
  }, {
    name: 'period_offset',
    type: 'input',
    message: 'Starting at minute',
    validate: (value, answers) => {
      let offset = Number(value);
      let maxOffset = convertPeriod(answers.period) / convertFrequency(answers.frequency) / 60;
      if (Number.isInteger(offset) && (offset >= 0 && offset < maxOffset)) {
        return true;
      }
      return `Please enter an integer between 0 - ${maxOffset - 1} inclusive`;
    },
    when: (answers) => answers.period === 'hour'
  }, {
    name: 'weekly_period_offset',
    type: 'list',
    message: 'Starting on',
    choices: days,
    when: (answers) => answers.period === 'week'
  }, {
    name: 'period_offset',
    type: 'list',
    message: 'Starting at',
    choices: (answers) => {
      let maxOffset = hours.length / convertFrequency(answers.frequency);
      return hours.splice(0, maxOffset);
    },
    when: (answers) => answers.period === 'day'
  }, {
    name: 'period_offset',
    type: 'list',
    message: 'Starting at',
    choices: hours,
    when: (answers) => answers.period === 'week'
  }, {
    name: 'name',
    type: 'input',
    message: 'Task name',
  }]);

  inquirer.prompt(questions, function(answers) {

    answers['service_id'] = prev['service_id'];
    answers['function_name'] = prev['function_name'];
    answers['kwargs'] = {};

    for (let answer in answers) {
      if (['name','library_token_id', 'period', 'frequency', 'period_offset', 'weekly_period_offset', 'service_id', 'function_name', 'kwargs'].indexOf(answer) === -1) {
        answers['kwargs'][answer] = answers[answer];
        delete answers[answer];
      }
    }

    return callback(null, answers);

  });

}

const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const hours = ['0:00 UTC', '1:00 UTC', '3:00 UTC', '4:00 UTC', '5:00 UTC', '6:00 UTC',
'7:00 UTC', '8:00 UTC', '9:00 UTC', '10:00 UTC', '11:00 UTC', '12:00 UTC',
'13:00 UTC', '14:00 UTC', '15:00 UTC', '16:00 UTC', '17:00 UTC', '18:00 UTC',
'19:00 UTC', '20:00 UTC', '21:00 UTC', '22:00 UTC', '23:00 UTC'];

function convertPeriod(period) {

  if (period === 'minute') {
    return 60;
  }
  if (period === 'hour') {
    return 3600;
  }
  if (period === 'day') {
    return 86400;
  }
  if (period === 'week') {
    return 604800;
  }

}

function convertPeriodOffset(periodOffset, weeklyPeriodOffset) {

  let offset = 0;

  if (!periodOffset && ! weeklyPeriodOffset) {
    return offset;
  }

  if (weeklyPeriodOffset) {
    offset += 86400 * days.indexOf(weeklyPeriodOffset);
  }

  if (hours.indexOf(periodOffset) !== -1) {
    offset += 3600 * hours.indexOf(periodOffset);
  } else {
    offset += 3600 * periodOffset;
  }

  return offset;

}

function convertFrequency(frequency) {

  if (frequency === 'once') return 1;
  if (frequency === 'twice') return 2;
  if (frequency === 'three times') return 3;
  if (frequency === 'four times') return 4;
  if (frequency === 'five times') return 5;
  if (frequency === 'six times') return 6;
  if (frequency === 'ten times') return 10;
  if (frequency === 'twelve times') return 12;
  if (frequency === 'fifteen times') return 15;
  if (frequency === 'twenty times') return 20;
  if (frequency === 'thirty times') return 30;

}

module.exports = TaskCreate;
<commit_msg>Added better error handling in task:create<commit_after>'use strict';

const lib = require('lib');
const Command = require('cmnd').Command;
const APIResource = require('api-res');
const Credentials = require('../../credentials.js');

const chalk = require('chalk');
const inquirer = require('inquirer');
const async = require('async');

const path = require('path');
const fs = require('fs');

const host = 'api.polybit.com';
const port = 443;

class TaskCreate extends Command {

  constructor() {

    super('task', 'create');

  }

  help() {

    return {
      description: 'Create a Scheduled Task from a StdLib service',
      args: [
        'service',
        'function',
      ],
      flags: {
        v: 'Service version (default lastest release)'
      },
      vflags: {
        version: 'Service version (default lastest release)'
      }
    };

  }

  run(params, callback) {

    let service = params.args[0];
    let f = params.args[1];
    let version = (params.flags.v || params.vflags.version || [])[0] || 'latest';

    if (!service) {
      console.log();
      console.log(chalk.bold.red('Oops!'));
      console.log();
      console.log(`Please specify a service name`);
      console.log();
      return callback(null);
    }

    if (!f) {
      f = '';
    }

    async.waterfall([
      async.apply(getServiceDetails, service, f, version),
      getTokens,
      promptQuestions,
    ], (err, results) => {

      if (err) {
        return callback(err);
      }

      let params = {
        name: results.name,
        library_token_id: results.library_token_id,
        service_id: results.service_id,
        function_name: results.function_name,
        frequency: convertFrequency(results.frequency),
        period: convertPeriod(results.period),
        period_offset: convertPeriodOffset(results.period_offset, results.weekly_period_offset),
        kwargs: results.kwargs,
      }

      let resource = new APIResource(host, port);

      resource.authorize(Credentials.read('ACCESS_TOKEN'));
      resource.request('/v1/scheduled_tasks').create({}, params, (err, response) => {

        if (err) {
          return callback(err);
        }

        console.log();
        console.log(chalk.bold.green('Success!'));
        console.log();
        console.log(`Task ${chalk.bold(params.name)} created`);
        console.log();

        return callback(null);

      });
    });

  }

}

function getServiceDetails(service, f, version, callback) {

  let params = {
    name: service,
    include_private: true,
  }

  if (version === 'latest') {
    params.latest = true;
  } else {
    params.version = version;
  }

  let resource = new APIResource(host, port);

  resource.authorize(Credentials.read('ACCESS_TOKEN'));
  resource.request('/v1/services').index(params, (err, response) => {

    if (err) {
      return callback(err);
    }

    let selectedService = response.data[0];

    let details = {
      service_id: selectedService.id,
      function_name: f,
    };

    if (selectedService.definitions_json[f] === undefined) {
      return callback(new Error(`Could not find function ${f} in service ${service}`));
    }

    details['fArgs'] = selectedService.definitions_json[f].params;

    return callback(null, details);

  });

}

function getTokens(prev, callback) {

  let resource = new APIResource(host, port);

  resource.authorize(Credentials.read('ACCESS_TOKEN'));
  resource.request('v1/dashboard/library_tokens').index({}, (err, response) => {

    if (err) {
      return callback(err);
    }

    if (!response.data.length) {
      return callback(new Error('You have no library tokens'));
    }

    prev.tokens = response.data.reduce((tokens, current) => {
      tokens.push(current.id.toString());
      return tokens;
    }, []);

    return callback(null, prev);

  });

}

function promptQuestions(prev, callback) {

  let questions;

  if (prev.fArgs) {
    questions = prev.fArgs.reduce((prompts, arg, index) => {
      prompts.push({
        name: arg.name,
        type: 'input',
        message: `Enter param for argument ${arg.name} (type ${arg.type})`,
        argument: true,
      });
      return prompts;
    }, []);
  } else {
    questions = [];
  }

  questions = questions.concat([{
    name: 'library_token_id',
    type: 'list',
    message: 'Pick a library token to use',
    choices: prev.tokens
  }, {
    name: 'period',
    type: 'list',
    message: 'Run service every: ',
    choices: ['minute', 'hour', 'day', 'week']
  }, {
    name: 'frequency',
    type: 'list',
    message: (answers) => `How ofter per ${answers.period}`,
    choices: ['once'],
    when: (answers) => answers.period === 'minute'
  }, {
    name: 'frequency',
    type: 'list',
    message: (answers) => `How ofter per ${answers.period}`,
    choices: ['once', 'twice', 'three times', 'four times', 'five times',
              'six times', 'ten times', 'twelve times', 'fifteen times',
              'twenty times', 'thirty times'],
    when: (answers) => answers.period === 'hour'
  }, {
    name: 'frequency',
    type: 'list',
    message: (answers) => `How ofter per ${answers.period}`,
    choices: ['once', 'twice', 'three times', 'four times', 'six times', 'twelve times'],
    when: (answers) => answers.period === 'day'
  }, {
    name: 'frequency',
    type: 'list',
    message: (answers) => `How ofter per ${answers.period}`,
    choices: ['once'],
    when: (answers) => answers.period === 'week'
  }, {
    name: 'period_offset',
    type: 'input',
    message: 'Starting at minute',
    validate: (value, answers) => {
      let offset = Number(value);
      let maxOffset = convertPeriod(answers.period) / convertFrequency(answers.frequency) / 60;
      if (Number.isInteger(offset) && (offset >= 0 && offset < maxOffset)) {
        return true;
      }
      return `Please enter an integer between 0 - ${maxOffset - 1} inclusive`;
    },
    when: (answers) => answers.period === 'hour'
  }, {
    name: 'weekly_period_offset',
    type: 'list',
    message: 'Starting on',
    choices: days,
    when: (answers) => answers.period === 'week'
  }, {
    name: 'period_offset',
    type: 'list',
    message: 'Starting at',
    choices: (answers) => {
      let maxOffset = hours.length / convertFrequency(answers.frequency);
      return hours.splice(0, maxOffset);
    },
    when: (answers) => answers.period === 'day'
  }, {
    name: 'period_offset',
    type: 'list',
    message: 'Starting at',
    choices: hours,
    when: (answers) => answers.period === 'week'
  }, {
    name: 'name',
    type: 'input',
    message: 'Task name',
  }]);

  inquirer.prompt(questions, function(answers) {

    answers['service_id'] = prev['service_id'];
    answers['function_name'] = prev['function_name'];
    answers['kwargs'] = {};

    for (let answer in answers) {
      if (['name','library_token_id', 'period', 'frequency', 'period_offset', 'weekly_period_offset', 'service_id', 'function_name', 'kwargs'].indexOf(answer) === -1) {
        answers['kwargs'][answer] = answers[answer];
        delete answers[answer];
      }
    }

    return callback(null, answers);

  });

}

const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
const hours = ['0:00 UTC', '1:00 UTC', '3:00 UTC', '4:00 UTC', '5:00 UTC', '6:00 UTC',
'7:00 UTC', '8:00 UTC', '9:00 UTC', '10:00 UTC', '11:00 UTC', '12:00 UTC',
'13:00 UTC', '14:00 UTC', '15:00 UTC', '16:00 UTC', '17:00 UTC', '18:00 UTC',
'19:00 UTC', '20:00 UTC', '21:00 UTC', '22:00 UTC', '23:00 UTC'];

function convertPeriod(period) {

  if (period === 'minute') {
    return 60;
  }
  if (period === 'hour') {
    return 3600;
  }
  if (period === 'day') {
    return 86400;
  }
  if (period === 'week') {
    return 604800;
  }

}

function convertPeriodOffset(periodOffset, weeklyPeriodOffset) {

  let offset = 0;

  if (!periodOffset && ! weeklyPeriodOffset) {
    return offset;
  }

  if (weeklyPeriodOffset) {
    offset += 86400 * days.indexOf(weeklyPeriodOffset);
  }

  if (hours.indexOf(periodOffset) !== -1) {
    offset += 3600 * hours.indexOf(periodOffset);
  } else {
    offset += 3600 * periodOffset;
  }

  return offset;

}

function convertFrequency(frequency) {

  if (frequency === 'once') return 1;
  if (frequency === 'twice') return 2;
  if (frequency === 'three times') return 3;
  if (frequency === 'four times') return 4;
  if (frequency === 'five times') return 5;
  if (frequency === 'six times') return 6;
  if (frequency === 'ten times') return 10;
  if (frequency === 'twelve times') return 12;
  if (frequency === 'fifteen times') return 15;
  if (frequency === 'twenty times') return 20;
  if (frequency === 'thirty times') return 30;

}

module.exports = TaskCreate;
<|endoftext|>