dustinspecker/generator-ng-poly

View on GitHub
lib/genBase/index.js

Summary

Maintainability
D
1 day
Test Coverage
'use strict';
import 'babel-polyfill';
import path from 'path';
import pify from 'pify';
import pkg from '../../package.json';
import recursiveReaddir from 'recursive-readdir';
import updateNotifier from 'update-notifier';
import utils from '../utils';
import yeoman from 'yeoman-generator';

module.exports = yeoman.Base.extend({
  constructor(...args) {
    /* eslint-disable prefer-reflect */
    yeoman.Base.apply(this, args);
    /* eslint-enable prefer-reflect */
    this.name = args['0'][0];
  },

  askForModuleName(params) {
    const config = this.config
      , name = this.name
      , options = this.options;

    const notifier = updateNotifier({
      packageName: pkg.name,
      packageVersion: pkg.version
    });

    // notifiy user about update, if there is an update
    notifier.notify();

    return this.prompt([
      {
        type: 'list',
        name: 'module',
        store: true,
        message: 'Which module is this for?',
        default: config.get('lastUsedModule'),
        when: () => !(options && options.module),
        async choices() {
          const directory = await utils.getAppDir()
            , files = await pify(recursiveReaddir)(directory);

          const choices = await utils.moduleFilter(files);

          return choices;
        }
      },
      {
        name: 'url',
        message: 'What\'s the URL for this route?',
        default: () => {
          // if child state return child portion as url
          if (name.indexOf('.') > -1) {
            return '/' + utils.hyphenName(name.split('.')[1]);
          }

          return '/' + utils.hyphenName(name);
        },
        when: () => params && params.url && !config.get('ngRoute') && !(options && options.url)
      },
      {
        name: 'templateUrl',
        message: 'What\'s the templateURL for this route?',
        async default(answers) {
          const module = answers.module || options.module
            , normalizeModulePath = await utils.normalizeModulePath(module);

          return normalizeModulePath + '/' +
            (options.structure === 'module-type' ||
              config.get('structure') === 'module-type' ? 'views/' : '') +
            utils.hyphenName(name.replace('.', '-')) + '.tpl.html';
        },
        when: () => params && params.templateUrl && !(options && options['template-url'])
      }
    ]).then(props => {
      this.module = props.module || options.module;
      this.url = props.url || options.url || name;
      this.templateUrl = props.templateUrl || options['template-url'];

      // if moduleName ends with a slash remove it
      if (this.module.charAt(this.module.length - 1) === '/' || this.module.charAt(this.module.length - 1) === '\\') {
        this.module = this.module.slice(0, this.module.length - 1);
      }

      // prepend slash if missing
      if (this.url && (this.url.charAt(0) !== '/' && this.url.charAt(0) !== '\\')) {
        this.url = '/' + this.url;
      }

      // convert backslashes to forwardslashes for Windows
      if (this.templateUrl) {
        this.templateUrl = this.templateUrl.replace('\\', '/');
      }

      // append .tpl.html if not existing
      if (!(/[.]tpl[.]html$/).test(this.templateUrl)) {
        this.templateUrl = this.templateUrl + '.tpl.html';
      }
    });
  },

  async getConfig() {
    const config = {
      name: this.name,
      markup: this.options.markup || this.config.get('markup'),
      appScript: this.options['app-script'] || this.config.get('appScript'),

      structure: this.options.structure || this.config.get('structure'),
      controllerAs: this.config.get('controllerAs'),

      directiveTemplateUrl: this.options['directive-template-url'] !== undefined &&
        this.options['directive-template-url'] !== null
          ? this.options['directive-template-url'] : this.config.get('directiveTemplateUrl'),

      skipController: this.options['skip-controller'] !== undefined && this.options['skip-controller'] !== null
        ? this.options['skip-controller'] : this.config.get('skipController'),

      testScript: this.options['test-script'] || this.config.get('testScript'),
      testFramework: this.config.get('testFramework'),
      e2eTestFramework: this.config.get('e2eTestFramework'),
      style: this.options.style || this.config.get('style'),
      ngRoute: this.config.get('ngRoute'),

      appDir: await utils.getAppDir(),
      appName: await utils.getAppName(),
      testDir: await utils.getUnitTestDir(),
      ctrlName: utils.ctrlName(this.name),
      humanName: utils.humanName(this.name),
      hyphenName: utils.hyphenName(this.name),
      lowerCamel: utils.lowerCamel(this.name),
      upperCamel: utils.upperCamel(this.name)
    };

    if (!this.module) {
      return config;
    }

    // only run for Angular components
    const modules = await utils.extractModuleNames(this.module);
    config.moduleName = utils.lowerCamel(modules[0]);
    config.parentModuleName = utils.lowerCamel(modules[1]);

    config.modulePath = await utils.normalizeModulePath(this.module);

    // create reference path to typings/tsd.d.ts from generated file
    if (config.appScript === 'ts') {
      // relative path between module path
      config.referencePath = path.relative(config.modulePath, path.dirname(this.config.path));
      // replace Windows path separators with Unix
      config.referencePath = config.referencePath.replace('\\', '/');
      config.referencePath = '../' + config.referencePath + '/typings/tsd.d.ts';
      // if module/type structure we need to go up one more folder
      if (config.structure === 'module-type' && !this.isModule) {
        config.referencePath = '../' + config.referencePath;
      }
    }

    return config;
  },

  async copyFile(type, component, dest, context) {
    const pluralComponent = component === 'factory' ? 'factories' : component + 's';

    let fileName, src;

    if (typeof dest === 'object') {
      context = dest;
      dest = null;
    }

    context = context || await this.getConfig();

    if (!dest) {
      // test or app directory?
      dest = type === 'unit' ? context.testDir : context.appDir;
      // append module path and type (if using module-type)
      dest = path.join(dest, context.modulePath,
        component !== 'module' && context.structure === 'module-type' ? pluralComponent : '');

      // create file name
      fileName = context.hyphenName + '-' + component;
      if (type === 'markup') {
        fileName += '.tpl.' + context.markup;
      }
      if (type === 'src') {
        fileName += '.' + context.appScript;
      }
      if (type === 'unit') {
        fileName += '_test.' + context.testScript;
      }
      // style types ALWAYS send a dest

      // append file name to dest
      dest = path.join(dest, fileName);
    }

    if (type === 'markup') {
      src = '_' + component + '.' + context.markup;
    }
    if (type === 'src') {
      src = '_' + component + '.' + context.appScript;
    }
    if (type === 'style') {
      src = component + '.' + context.style;
    }
    if (type === 'unit') {
      src = '_spec.' + context.testScript;
    }

    this.copySimpleFile(src, dest, context);
  },

  copySimpleFile(src, dest, context) {
    context = context || this.context;
    // remove underscore from templated file names
    dest = dest || src.replace(/_/g, '');

    this.fs.copyTpl(
      this.templatePath(src),
      this.destinationPath(dest),
      context
    );
  },

  copyMarkupFile(component, dest, context) {
    return this.copyFile('markup', component, dest, context);
  },

  copySrcFile(component, dest, context) {
    return this.copyFile('src', component, dest, context);
  },

  copyStyleFile(component, dest, context) {
    return this.copyFile('style', component, dest, context);
  },

  copyUnitTest(component, dest, context) {
    return this.copyFile('unit', component, dest, context);
  },

  copyE2e(context) {
    const testScript = context.testScript === 'ts' ? 'js' : context.testScript
      , e2eFile = path.join('e2e', context.hyphenName, context.hyphenName);

    this.copySimpleFile('page.po.' + testScript, e2eFile + '.po.' + testScript, context);
    this.copySimpleFile('page_test.' + testScript, e2eFile + '_test.' + testScript, context);
  }
});