How to use shouldUseTypescript method in Cypress

Best JavaScript code snippet using cypress

blueprint.js

Source:blueprint.js Github

copy

Full Screen

1'use strict';2/**3@module ember-cli4*/5const FileInfo = require('./file-info');6const chalk = require('chalk');7const MarkdownColor = require('../utilities/markdown-color');8const sequence = require('../utilities/sequence');9const printCommand = require('../utilities/print-command');10const insertIntoFile = require('../utilities/insert-into-file');11const cleanRemove = require('../utilities/clean-remove');12const fs = require('fs-extra');13const inflector = require('inflection');14const minimatch = require('minimatch');15const path = require('path');16const stringUtils = require('ember-cli-string-utils');17const _ = require('ember-cli-lodash-subset');18const walkSync = require('walk-sync');19const SilentError = require('silent-error');20const CoreObject = require('core-object');21const EOL = require('os').EOL;22const bowEpParser = require('bower-endpoint-parser');23const logger = require('heimdalljs-logger')('ember-cli:blueprint');24const normalizeEntityName = require('ember-cli-normalize-entity-name');25const { removeTypes } = require('remove-types');26const isAddon = require('../utilities/is-addon');27const { deprecate } = require('../debug');28const initialIgnoredFiles = ['.DS_Store'];29/**30  A blueprint is a bundle of template files with optional install31  logic.32  Blueprints follow a simple structure. Let's take the built-in33  `controller` blueprint as an example:34  ```35  blueprints/controller36  ├── files37  │   ├── app38  │   │   └── __path__39  │   │       └── __name__.js40  └── index.js41  blueprints/controller-test42  ├── files43  │   └── tests44  │       └── unit45  │           └── controllers46  │               └── __test__.js47  └── index.js48  ```49  ## Files50  `files` contains templates for the all the files to be51  installed into the target directory.52  The `__name__` token is subtituted with the dasherized53  entity name at install time. For example, when the user54  invokes `ember generate controller foo` then `__name__` becomes55  `foo`. When the `--pod` flag is used, for example `ember56  generate controller foo --pod` then `__name__` becomes57  `controller`.58  The `__path__` token is substituted with the blueprint59  name at install time. For example, when the user invokes60  `ember generate controller foo` then `__path__` becomes61  `controller`. When the `--pod` flag is used, for example62  `ember generate controller foo --pod` then `__path__`63  becomes `foo` (or `<podModulePrefix>/foo` if the64  podModulePrefix is defined). This token is primarily for65  pod support, and is only necessary if the blueprint can be66  used in pod structure. If the blueprint does not require pod67  support, simply use the blueprint name instead of the68  `__path__` token.69  The `__test__` token is substituted with the dasherized70  entity name and appended with `-test` at install time.71  This token is primarily for pod support and only necessary72  if the blueprint requires support for a pod structure. If73  the blueprint does not require pod support, simply use the74  `__name__` token instead.75  ## Template Variables (AKA Locals)76  Variables can be inserted into templates with77  `<%= someVariableName %>`.78  For example, the built-in `util` blueprint79  `files/app/utils/__name__.js` looks like this:80  ```js81  export default function <%= camelizedModuleName %>() {82    return true;83  }84  ```85  `<%= camelizedModuleName %>` is replaced with the real86  value at install time.87  The following template variables are provided by default:88  - `dasherizedPackageName`89  - `classifiedPackageName`90  - `dasherizedModuleName`91  - `classifiedModuleName`92  - `camelizedModuleName`93  `packageName` is the project name as found in the project's94  `package.json`.95  `moduleName` is the name of the entity being generated.96  The mechanism for providing custom template variables is97  described below.98  ## Index.js99  Custom installation and uninstallation behavior can be added100  by overriding the hooks documented below. `index.js` should101  export a plain object, which will extend the prototype of the102  `Blueprint` class. If needed, the original `Blueprint` prototype103  can be accessed through the `_super` property.104  ```js105  module.exports = {106    locals(options) {107      // Return custom template variables here.108      return {};109    },110    normalizeEntityName(entityName) {111      // Normalize and validate entity name here.112      return entityName;113    },114    fileMapTokens(options) {115      // Return custom tokens to be replaced in your files116      return {117        __token__(options){118          // logic to determine value goes here119          return 'value';120        }121      }122    },123    filesPath(options) {124      return path.join(this.path, 'files');125    },126    beforeInstall(options) {},127    afterInstall(options) {},128    beforeUninstall(options) {},129    afterUninstall(options) {}130  };131  ```132  ## Blueprint Hooks133  ### beforeInstall & beforeUninstall134  Called before any of the template files are processed and receives135  the `options` and `locals` hashes as parameters. Typically used for136  validating any additional command line options or for any asynchronous137  setup that is needed.   As an example, the `controller` blueprint validates138  its `--type` option in this hook.  If you need to run any asynchronous code,139  wrap it in a promise and return that promise from these hooks.  This will140  ensure that your code is executed correctly.141  ### afterInstall & afterUninstall142  The `afterInstall` and `afterUninstall` hooks receives the same143  arguments as `locals`. Use it to perform any custom work after the144  files are processed. For example, the built-in `route` blueprint145  uses these hooks to add and remove relevant route declarations in146  `app/router.js`.147  ### Overriding Install148  If you don't want your blueprint to install the contents of149  `files` you can override the `install` method. It receives the150  same `options` object described above and must return a promise.151  See the built-in `resource` blueprint for an example of this.152  @class Blueprint153  @constructor154  @extends CoreObject155  @param {String} [blueprintPath]156*/157let Blueprint = CoreObject.extend({158  availableOptions: [],159  anonymousOptions: ['name'],160  _printableProperties: ['name', 'description', 'availableOptions', 'anonymousOptions', 'overridden'],161  /**162    Indicates whether or not a blueprint is a candidate for automatic transpilation from TS to JS.163    This property could be false in the case that the blueprint is written in JS and is not intended164    to work with TS at all, OR in the case that the blueprint is written in TS and the author does165    not intend to support transpilation to JS.166    @public167    @property shouldTransformTypeScript168    @type Boolean169  */170  shouldTransformTypeScript: false,171  init(blueprintPath) {172    this._super();173    this.path = blueprintPath;174    this.name = path.basename(blueprintPath);175  },176  /**177    Hook to specify the path to the blueprint's files. By default this is178    `path.join(this.path, 'files)`.179    This can be used to customize which set of files to install based on options180    or environmental variables. It defaults to the `files` directory within the181    blueprint's folder.182    @public183    @method filesPath184    @param {Object} options185    @return {String} Path to the blueprints files directory.186  */187  filesPath(/* options */) {188    return path.join(this.path, 'files');189  },190  /**191    Used to retrieve files for blueprint.192    @public193    @method files194    @return {Array} Contents of the blueprint's files directory195  */196  files() {197    if (this._files) {198      return this._files;199    }200    let filesPath = this.filesPath(this.options);201    if (Blueprint._existsSync(filesPath)) {202      this._files = walkSync(filesPath);203    } else {204      this._files = [];205    }206    return this._files;207  },208  /**209    @method srcPath210    @param {String} file211    @return {String} Resolved path to the file212  */213  srcPath(file) {214    return path.resolve(this.filesPath(this.options), file);215  },216  /**217    Hook for normalizing entity name218    Use the `normalizeEntityName` hook to add custom normalization and219    validation of the provided entity name. The default hook does not220    make any changes to the entity name, but makes sure an entity name221    is present and that it doesn't have a trailing slash.222    This hook receives the entity name as its first argument. The string223    returned by this hook will be used as the new entity name.224    @public225    @method normalizeEntityName226    @param {String} entityName227    @return {null}228  */229  normalizeEntityName(entityName) {230    return normalizeEntityName(entityName);231  },232  /**233    Write a status and message to the UI234    @private235    @method _writeStatusToUI236    @param {Function} chalkColor237    @param {String} keyword238    @param {String} message239  */240  _writeStatusToUI(chalkColor, keyword, message) {241    if (this.ui) {242      this.ui.writeLine(`  ${chalkColor(keyword)} ${message}`);243    }244  },245  /**246    @private247    @method _writeFile248    @param {Object} info249    @return {Promise}250  */251  async _writeFile(info) {252    if (!this.dryRun) {253      return fs.outputFile(info.outputPath, await info.render());254    }255  },256  /**257    Actions lookup258    @private259    @property _actions260    @type Object261  */262  _actions: {263    write(info) {264      this._writeStatusToUI(chalk.green, 'create', info.displayPath);265      return this._writeFile(info);266    },267    skip(info) {268      let label = 'skip';269      if (info.resolution === 'identical') {270        label = 'identical';271      }272      this._writeStatusToUI(chalk.yellow, label, info.displayPath);273    },274    overwrite(info) {275      this._writeStatusToUI(chalk.yellow, 'overwrite', info.displayPath);276      return this._writeFile(info);277    },278    edit(info) {279      this._writeStatusToUI(chalk.green, 'edited', info.displayPath);280    },281    remove(info) {282      this._writeStatusToUI(chalk.red, 'remove', info.displayPath);283      if (!this.dryRun) {284        return cleanRemove(info);285      }286    },287  },288  /**289    Calls an action.290    @private291    @method _commit292    @param {Object} result293    @return {Promise}294    @throws {Error} Action doesn't exist.295  */296  _commit(result) {297    let action = this._actions[result.action];298    if (action) {299      return action.call(this, result);300    } else {301      throw new Error(`Tried to call action "${result.action}" but it does not exist`);302    }303  },304  /**305    Prints warning for pod unsupported.306    @private307    @method _checkForPod308  */309  _checkForPod(verbose) {310    if (!this.hasPathToken && this.pod && verbose) {311      this.ui.writeLine(312        chalk.yellow(313          'You specified the pod flag, but this' +314            ' blueprint does not support pod structure. It will be generated with' +315            ' the default structure.'316        )317      );318    }319  },320  /**321    @private322    @method _normalizeEntityName323    @param {Object} entity324  */325  _normalizeEntityName(entity) {326    if (entity) {327      entity.name = this.normalizeEntityName(entity.name);328    }329  },330  /**331    @private332    @method _checkInRepoAddonExists333    @param {Object} options334  */335  _checkInRepoAddonExists(options) {336    let addon;337    if (options.inRepoAddon) {338      addon = findAddonByName(this.project, options.inRepoAddon);339      if (!addon) {340        throw new SilentError(341          `You specified the 'in-repo-addon' flag, but the ` +342            `in-repo-addon '${options.inRepoAddon}' does not exist. Please check the name and try again.`343        );344      }345    }346    if (options.in) {347      if (!ensureTargetDirIsAddon(options.in)) {348        throw new SilentError(349          `You specified the 'in' flag, but the ` +350            `in repo addon '${options.in}' does not exist. Please check the name and try again.`351        );352      }353    }354  },355  /**356    @private357    @method _process358    @param {Object} options359    @param {Function} beforeHook360    @param {Function} process361    @param {Function} afterHook362  */363  async _process(options, beforeHook, process, afterHook) {364    let intoDir = options.target;365    let locals = await this._locals(options);366    // run beforeInstall/beforeUninstall userland hooks367    await beforeHook.call(this, options, locals);368    // gather fileInfos to be processed369    let fileInfos = await process.call(this, intoDir, locals);370    // commit changes for each FileInfo (with prompting as needed)371    await Promise.all(fileInfos.map((info) => this._commit(info)));372    // run afterInstall/afterUninstall userland hooks373    await afterHook.call(this, options);374  },375  /**376    @private377    @method shouldConvertToJS378    @param {Object} options379    @param {FileInfo} fileInfo380    @return {Boolean}381  */382  shouldConvertToJS(options, fileInfo) {383    // If this isn't turned on, it doesn't matter what else was passed, we're not touching it.384    if (!this.shouldTransformTypeScript) {385      return false;386    }387    // If the blueprint isn't a TS file to begin with, there's nothing to convert.388    if (!isTypeScriptFile(fileInfo.outputPath)) {389      // If the user wants TypeScript output but there is no TypeScript blueprint available, we want390      // to warn them that they're not going to get what they're expecting while still at least giving391      // them the JS output. We check for this *after* checking `shouldTranformTypeScript` because392      // it's possible for people to set `{typescript: true}` in their `.ember-cli` file, which would393      // then erroneously trigger this message every time they generate a JS blueprint even though394      // they didn't pass the flag.395      if (options.typescript === true) {396        this.ui.writeLine(397          chalk.yellow(398            "You passed the '--typescript' flag but there is no TypeScript blueprint available. " +399              'A JavaScript blueprint will be generated instead.'400          )401        );402      }403      return false;404    }405    // Indicates when the user explicitly passed either `--typescript` or `--no-typescript` as opposed406    // to not passing a flag at all and allowing for default behavior407    const userExplicitlySelectedTypeScriptStatus = options.typescript !== undefined;408    // Indicates when the user has asked for TypeScript either globally (by setting409    // `isTypeScriptProject` to true) or locally (by passing the `--typescript` flag when they410    // invoked the generator). Although ember-cli merges `.ember-cli` and all of the flag values into411    // one object, we thought the DX would be improved by differentiating between what is intended412    // to be global vs. local config.413    const shouldUseTypeScript = userExplicitlySelectedTypeScriptStatus414      ? options.typescript415      : options.isTypeScriptProject;416    // if the user wants TS output and we have a TS file available, we do *not* want to downlevel to JS417    if (shouldUseTypeScript) {418      return false;419    }420    return true;421  },422  /**423    @private424    @method convertToJS425    @param {FileInfo} fileInfo426    @return {Promise}427  */428  async convertToJS(fileInfo) {429    let rendered = await fileInfo.render();430    const transformed = await removeTypes(rendered);431    fileInfo.rendered = transformed;432    fileInfo.displayPath = replaceExtension(fileInfo.displayPath, '.js');433    fileInfo.outputPath = replaceExtension(fileInfo.outputPath, '.js');434    return fileInfo;435  },436  /**437    @method install438    @param {Object} options439    @return {Promise}440  */441  install(options) {442    let ui = (this.ui = options.ui);443    let dryRun = (this.dryRun = options.dryRun);444    this.project = options.project;445    this.pod = options.pod;446    this.options = options;447    this.hasPathToken = hasPathToken(this.files(this.options));448    ui.writeLine(`installing ${this.name}`);449    if (dryRun) {450      ui.writeLine(chalk.yellow('You specified the dry-run flag, so no' + ' changes will be written.'));451    }452    this._normalizeEntityName(options.entity);453    this._checkForPod(options.verbose);454    this._checkInRepoAddonExists(options);455    logger.info('START: processing blueprint: `%s`', this.name);456    let start = new Date();457    return this._process(options, this.beforeInstall, this.processFiles, this.afterInstall).finally(() =>458      logger.info('END: processing blueprint: `%s` in (%dms)', this.name, new Date() - start)459    );460  },461  /**462    @method uninstall463    @param {Object} options464    @return {Promise}465  */466  uninstall(options) {467    let ui = (this.ui = options.ui);468    let dryRun = (this.dryRun = options.dryRun);469    this.project = options.project;470    this.pod = options.pod;471    this.options = options;472    this.hasPathToken = hasPathToken(this.files(this.options));473    ui.writeLine(`uninstalling ${this.name}`);474    if (dryRun) {475      ui.writeLine(chalk.yellow('You specified the dry-run flag, so no' + ' files will be deleted.'));476    }477    this._normalizeEntityName(options.entity);478    this._checkForPod(options.verbose);479    return this._process(options, this.beforeUninstall, this.processFilesForUninstall, this.afterUninstall);480  },481  /**482    Hook for running operations before install.483    @method beforeInstall484    @return {Promise|null}485  */486  beforeInstall() {},487  /**488    Hook for running operations after install.489    @method afterInstall490    @return {Promise|null}491  */492  afterInstall() {},493  /**494    Hook for running operations before uninstall.495    @method beforeUninstall496    @return {Promise|null}497  */498  beforeUninstall() {},499  /**500    Hook for running operations after uninstall.501    @method afterUninstall502    @return {Promise|null}503  */504  afterUninstall() {},505  filesToRemove: [],506  /**507    Hook for adding custom template variables.508    When the following is called on the command line:509    ```sh510    ember generate controller foo --type=array --dry-run isAdmin:true511    ```512    The object passed to `locals` looks like this:513    ```js514    {515      entity: {516        name: 'foo',517        options: {518          isAdmin: true519        }520      },521      dryRun: true522      type: "array"523      // more keys524    }525    ```526    This hook must return an object or a Promise which resolves to an object.527    The resolved object will be merged with the aforementioned default locals.528    @public529    @method locals530    @param {Object} options General and entity-specific options531    @return {Object|Promise|null}532  */533  locals(/* options */) {},534  /**535    Hook to add additional or override existing fileMap tokens.536    Use `fileMapTokens` to add custom fileMap tokens for use537    in the `mapFile` method. The hook must return an object in the538    following pattern:539    ```js540    {541      __token__(options){542        // logic to determine value goes here543        return 'value';544      }545    }546    ```547    It will be merged with the default `fileMapTokens`, and can be used548    to override any of the default tokens.549    Tokens are used in the files folder (see `files`), and get replaced with550    values when the `mapFile` method is called.551    @public552    @method fileMapTokens553    @return {Object|null}554  */555  fileMapTokens() {},556  /**557    @private558    @method _fileMapTokens559    @param {Object} options560    @return {Object}561  */562  _fileMapTokens(options) {563    let { project } = this;564    let standardTokens = {565      __name__(options) {566        if (options.pod && options.hasPathToken) {567          return options.blueprintName;568        }569        return options.dasherizedModuleName;570      },571      __path__(options) {572        let blueprintName = options.blueprintName;573        if (/-test/.test(blueprintName)) {574          blueprintName = options.blueprintName.slice(0, options.blueprintName.indexOf('-test'));575        }576        if (options.pod && options.hasPathToken) {577          return path.join(options.podPath, options.dasherizedModuleName);578        }579        return inflector.pluralize(blueprintName);580      },581      __root__(options) {582        if (options.inRepoAddon) {583          let addon = findAddonByName(project, options.inRepoAddon);584          let relativeAddonPath = path.relative(project.root, addon.root);585          return path.join(relativeAddonPath, 'addon');586        }587        if (options.in) {588          let relativeAddonPath = path.relative(project.root, options.in);589          return path.join(relativeAddonPath, 'addon');590        }591        if (options.inDummy) {592          return path.join('tests', 'dummy', 'app');593        }594        if (options.inAddon) {595          return 'addon';596        }597        return 'app';598      },599      __test__(options) {600        if (options.pod && options.hasPathToken) {601          return options.blueprintName;602        }603        return `${options.dasherizedModuleName}-test`;604      },605    };606    let customTokens = this.fileMapTokens(options) || options.fileMapTokens || {};607    return _.merge(standardTokens, customTokens);608  },609  /**610    Used to generate fileMap tokens for mapFile.611    @method generateFileMap612    @param {Object} fileMapVariables613    @return {Object}614  */615  generateFileMap(fileMapVariables) {616    let tokens = this._fileMapTokens(fileMapVariables);617    let fileMapValues = _.values(tokens);618    let tokenValues = fileMapValues.map((token) => token(fileMapVariables));619    let tokenKeys = Object.keys(tokens);620    return _.zipObject(tokenKeys, tokenValues);621  },622  /**623    @method buildFileInfo624    @param {Function} destPath625    @param {Object} templateVariables626    @param {String} file627    @return {FileInfo}628  */629  buildFileInfo(intoDir, templateVariables, file) {630    let mappedPath = this.mapFile(file, templateVariables);631    return new FileInfo({632      action: 'write',633      outputBasePath: path.normalize(intoDir),634      outputPath: path.join(intoDir, mappedPath),635      displayPath: path.normalize(mappedPath),636      inputPath: this.srcPath(file),637      templateVariables,638      ui: this.ui,639    });640  },641  /**642    @method isUpdate643    @return {Boolean}644  */645  isUpdate() {646    if (this.project && this.project.isEmberCLIProject) {647      return this.project.isEmberCLIProject();648    }649  },650  /**651    @private652    @method _getFileInfos653    @param {Array} files654    @param {String} intoDir655    @param {Object} templateVariables656    @return {Array} file infos657  */658  _getFileInfos(files, intoDir, templateVariables) {659    return files.map(this.buildFileInfo.bind(this, intoDir, templateVariables));660  },661  /**662    Add update files to ignored files or reset them663    @private664    @method _ignoreUpdateFiles665  */666  _ignoreUpdateFiles() {667    if (this.isUpdate()) {668      Blueprint.ignoredFiles = Blueprint.ignoredFiles.concat(Blueprint.ignoredUpdateFiles);669    } else {670      Blueprint.ignoredFiles = initialIgnoredFiles;671    }672  },673  /**674    @private675    @method _getFilesForInstall676    @param {Array} targetFiles677    @return {Array} files678  */679  _getFilesForInstall(targetFiles) {680    let files = this.files(this.options);681    // if we've defined targetFiles, get file info on ones that match682    return (targetFiles && targetFiles.length > 0 && _.intersection(files, targetFiles)) || files;683  },684  /**685    @private686    @method _checkForNoMatch687    @param {Array} fileInfos688    @param {String} rawArgs689  */690  _checkForNoMatch(fileInfos, rawArgs) {691    if (fileInfos.filter(isFilePath).length < 1 && rawArgs) {692      this.ui.writeLine(693        chalk.yellow(`The globPattern "${rawArgs}" ` + `did not match any files, so no file updates will be made.`)694      );695    }696  },697  /**698    @method processFiles699    @param {String} intoDir700    @param {Object} templateVariables701    @return {Promise<FileInfo[]>}702  */703  processFiles(intoDir, templateVariables) {704    let files = this._getFilesForInstall(templateVariables.targetFiles);705    let fileInfos = this._getFileInfos(files, intoDir, templateVariables);706    this._checkForNoMatch(fileInfos, templateVariables.rawArgs);707    this._ignoreUpdateFiles();708    let fileInfosToRemove = this._getFileInfos(this.filesToRemove, intoDir, templateVariables);709    fileInfosToRemove = finishProcessingForUninstall(fileInfosToRemove);710    return Promise.all(fileInfos.filter(isValidFile).map(prepareConfirm))711      .then(finishProcessingForInstall)712      .then((fileInfos) => {713        return Promise.all(714          fileInfos.map((info) => {715            if (this.shouldConvertToJS(this.options, info)) {716              return this.convertToJS(info);717            }718            return info;719          })720        );721      })722      .then((fileInfos) => fileInfos.concat(fileInfosToRemove));723  },724  /**725    @method processFilesForUninstall726    @param {String} intoDir727    @param {Object} templateVariables728  */729  processFilesForUninstall(intoDir, templateVariables) {730    let fileInfos = this._getFileInfos(this.files(this.options), intoDir, templateVariables);731    this._ignoreUpdateFiles();732    fileInfos = fileInfos.filter(isValidFile).reduce((acc, info) => {733      // if it's possible that this blueprint could have produced either typescript OR javascript, we have to do some734      // work to figure out which files to delete.735      if (this.shouldTransformTypeScript) {736        if (this.options.typescript === true) {737          // if the user explicitly passed `--typescript`, we only want to delete TS files, so we stick with the existing738          // info object since it will contain a .ts outputPath (since we know this blueprint is authored in TS because739          // of our check above)740          acc.push(info);741          return acc;742        }743        const jsInfo = new FileInfo({744          ...info,745          outputPath: replaceExtension(info.outputPath, '.js'),746          displayPath: replaceExtension(info.displayPath, '.js'),747        });748        if (this.options.typescript === false) {749          // if the user explicitly passed `--no-typescript`, we only want to delete JS file, so we return our newly750          // created jsInfo object since it contains the javascript version of the output path.751          acc.push(jsInfo);752          return acc;753        }754        if (this.options.typescript === undefined) {755          // if the user didn't specify one way or the other, then both the JS and TS paths are possibilities, so we add756          // both of them to the list. `finishProcessingForUninstall` will actually look to see which of them exists and757          // delete whatever it finds.758          acc.push(info, jsInfo);759          return acc;760        }761      }762      acc.push(info);763      return acc;764    }, []);765    return finishProcessingForUninstall(fileInfos);766  },767  /**768    @method mapFile769    @param {String} file770    @param locals771    @return {String}772  */773  mapFile(file, locals) {774    let pattern, i;775    let fileMap = locals.fileMap || { __name__: locals.dasherizedModuleName };776    file = Blueprint.renamedFiles[file] || file;777    for (i in fileMap) {778      pattern = new RegExp(i, 'g');779      file = file.replace(pattern, fileMap[i]);780    }781    return file;782  },783  /**784    Looks for a __root__ token in the files folder. Must be present for785    the blueprint to support addon tokens. The `server`, `blueprints`, and `test`786    @private787    @method supportsAddon788    @return {Boolean}789  */790  supportsAddon() {791    return /__root__/.test(this.files().join());792  },793  /**794    @private795    @method _generateFileMapVariables796    @param {String} moduleName797    @param locals798    @param {Object} options799    @return {Object}800  */801  _generateFileMapVariables(moduleName, locals, options) {802    let originBlueprintName = options.originBlueprintName || this.name;803    let podModulePrefix = this.project.config().podModulePrefix || '';804    let podPath = podModulePrefix.substr(podModulePrefix.lastIndexOf('/') + 1);805    let inAddon = this.project.isEmberCLIAddon() || !!options.inRepoAddon;806    let inDummy = this.project.isEmberCLIAddon() ? options.dummy : false;807    return {808      pod: this.pod,809      podPath,810      hasPathToken: this.hasPathToken,811      inAddon,812      inRepoAddon: options.inRepoAddon,813      in: options.in,814      inDummy,815      blueprintName: this.name,816      originBlueprintName,817      dasherizedModuleName: stringUtils.dasherize(moduleName),818      locals,819    };820  },821  /**822    @private823    @method _locals824    @param {Object} options825    @return {Object}826  */827  _locals(options) {828    let packageName = options.project.name();829    let moduleName = (options.entity && options.entity.name) || packageName;830    let sanitizedModuleName = moduleName.replace(/\//g, '-');831    return new Promise((resolve) => {832      resolve(this.locals(options));833    }).then((customLocals) => {834      let fileMapVariables = this._generateFileMapVariables(moduleName, customLocals, options);835      let fileMap = this.generateFileMap(fileMapVariables);836      let standardLocals = {837        dasherizedPackageName: stringUtils.dasherize(packageName),838        classifiedPackageName: stringUtils.classify(packageName),839        dasherizedModuleName: stringUtils.dasherize(moduleName),840        classifiedModuleName: stringUtils.classify(sanitizedModuleName),841        camelizedModuleName: stringUtils.camelize(sanitizedModuleName),842        decamelizedModuleName: stringUtils.decamelize(sanitizedModuleName),843        fileMap,844        hasPathToken: this.hasPathToken,845        targetFiles: options.targetFiles,846        rawArgs: options.rawArgs,847      };848      return _.merge({}, standardLocals, customLocals);849    });850  },851  /**852    Used to add a package to the project's `package.json`.853    Generally, this would be done from the `afterInstall` hook, to854    ensure that a package that is required by a given blueprint is855    available.856    @method addPackageToProject857    @param {String} packageName858    @param {String} target859    @return {Promise}860  */861  addPackageToProject(packageName, target) {862    let packageObject = { name: packageName };863    if (target) {864      packageObject.target = target;865    }866    return this.addPackagesToProject([packageObject]);867  },868  /**869    Used to add multiple packages to the project's `package.json`.870    Generally, this would be done from the `afterInstall` hook, to871    ensure that a package that is required by a given blueprint is872    available.873    Expects each array item to be an object with a `name`.  Each object874    may optionally have a `target` to specify a specific version.875    @method addPackagesToProject876    @param {Array} packages877    @return {Promise}878    @example879    ```js880    this.addPackagesToProject([881      { name: 'lodash' },882      { name: 'moment', target: '^2.17.0' },883    ]);884    ```885  */886  addPackagesToProject(packages) {887    let task = this.taskFor('npm-install');888    let installText = packages.length > 1 ? 'install packages' : 'install package';889    let packageNames = [];890    let packageArray = [];891    for (let i = 0; i < packages.length; i++) {892      packageNames.push(packages[i].name);893      let packageNameAndVersion = packages[i].name;894      if (packages[i].target) {895        packageNameAndVersion += `@${packages[i].target}`;896      }897      packageArray.push(packageNameAndVersion);898    }899    this._writeStatusToUI(chalk.green, installText, packageNames.join(', '));900    return task.run({901      'save-dev': true,902      verbose: false,903      packages: packageArray,904    });905  },906  /**907    Used to remove a package from the project's `package.json`.908    Generally, this would be done from the `afterInstall` hook, to909    ensure that any package conflicts can be resolved before the910    addon is used.911    @method removePackageFromProject912    @param {String} packageName913    @return {Promise}914  */915  removePackageFromProject(packageName) {916    let packageObject = { name: packageName };917    return this.removePackagesFromProject([packageObject]);918  },919  /**920    Used to remove multiple packages from the project's `package.json`.921    Generally, this would be done from the `afterInstall` hook, to922    ensure that any package conflicts can be resolved before the923    addon is used.924    Expects each array item to be an object with a `name` property.925    @method removePackagesFromProject926    @param {Array} packages927    @return {Promise}928  */929  removePackagesFromProject(packages) {930    let task = this.taskFor('npm-uninstall');931    let installText = packages.length > 1 ? 'uninstall packages' : 'uninstall package';932    let packageNames = [];933    let projectDependencies = this.project.dependencies();934    for (let i = 0; i < packages.length; i++) {935      let packageName = packages[i].name;936      if (packageName in projectDependencies) {937        packageNames.push(packageName);938      }939    }940    if (packageNames.length === 0) {941      this._writeStatusToUI(chalk.yellow, 'remove', 'Skipping uninstall because no matching package is installed.');942      return Promise.resolve();943    }944    this._writeStatusToUI(chalk.green, installText, packageNames.join(', '));945    return task.run({946      'save-dev': true,947      verbose: false,948      packages: packageNames,949    });950  },951  /**952    Used to add a Bower package to the projects `bower.json`.953    954    Bower is a package manager that is no longer recommended 955    for new projects, but you may find this hook used in older956    addons.957    Generally, this would be done from the `afterInstall` hook, to958    ensure that a package that is required by a given blueprint is959    available.960    `localPackageName` and `target` may be thought of as equivalent961    to the key-value pairs in the `dependency` or `devDepencency`962    objects contained within a bower.json file.963    @method addBowerPackageToProject964    @param {String} localPackageName965    @param {String} target966    @param {Object} installOptions967    @return {Promise}968    @example969    ```js970    addBowerPackageToProject('jquery', '~1.11.1');971    addBowerPackageToProject('old_jquery', 'jquery#~1.9.1');972    addBowerPackageToProject('bootstrap-3', 'https://twitter.github.io/bootstrap/assets/bootstrap');973    ```974  */975  addBowerPackageToProject(localPackageName, target, installOptions) {976    deprecate(977      [978        `(Blueprint: \`${this.name}\`) \`addBowerPackageToProject\` has been deprecated.`,979        'If the package is also available on the npm registry, please use `addPackageToProject` instead.',980        'If not, please install the Bower package manually by running:',981        `\`bower install ${localPackageName} --save\``,982      ].join('\n'),983      false,984      {985        for: 'ember-cli',986        id: 'ember-cli.blueprint.add-bower-package-to-project',987        since: {988          available: '4.2.0',989          enabled: '4.2.0',990        },991        until: '5.0.0',992      }993    );994    let lpn = localPackageName;995    let tar = target;996    let packageObject = bowEpParser.json2decomposed(lpn, tar);997    return this.addBowerPackagesToProject([packageObject], installOptions, true);998  },999  /**1000    Used to add an array of packages to the projects `bower.json`.1001    1002    Bower is a package manager that is no longer recommended 1003    for new projects, but you may find this hook used in older1004    addons.1005    Generally, this would be done from the `afterInstall` hook, to1006    ensure that a package that is required by a given blueprint is1007    available.1008    Expects each array item to be an object with a `name`.  Each object1009    may optionally have a `target` to specify a specific version, or a1010    `source` to specify a non-local name to be resolved.1011    @method addBowerPackagesToProject1012    @param {Array} packages1013    @param {Object} installOptions1014    @return {Promise}1015  */1016  addBowerPackagesToProject(packages, installOptions, _deprecationCondition = false) {1017    let task = this.taskFor('bower-install');1018    let installText = packages.length > 1 ? 'install bower packages' : 'install bower package';1019    let packageNames = [];1020    let packageNamesAndVersions = packages1021      .map((pkg) => {1022        pkg.source = pkg.source || pkg.name;1023        packageNames.push(pkg.name);1024        return pkg;1025      })1026      .map(bowEpParser.compose);1027    deprecate(1028      [1029        `(Blueprint: \`${this.name}\`) \`addBowerPackagesToProject\` has been deprecated.`,1030        'If the packages are also available on the npm registry, please use `addPackagesToProject` instead.',1031        'If not, please install the Bower packages manually by running:',1032        `\`bower install ${packageNames.join(' ')} --save\``,1033      ].join('\n'),1034      _deprecationCondition,1035      {1036        for: 'ember-cli',1037        id: 'ember-cli.blueprint.add-bower-packages-to-project',1038        since: {1039          available: '4.2.0',1040          enabled: '4.2.0',1041        },1042        until: '5.0.0',1043      }1044    );1045    this._writeStatusToUI(chalk.green, installText, packageNames.join(', '));1046    return task.run({1047      verbose: true,1048      packages: packageNamesAndVersions,1049      installOptions: installOptions || { save: true },1050    });1051  },1052  /**1053    Used to add an addon to the project's `package.json` and run it's1054    `defaultBlueprint` if it provides one.1055    Generally, this would be done from the `afterInstall` hook, to1056    ensure that a package that is required by a given blueprint is1057    available.1058    @method addAddonToProject1059    @param {Object} options1060    @return {Promise}1061  */1062  addAddonToProject(options) {1063    return this.addAddonsToProject({1064      packages: [options],1065      extraArgs: options.extraArgs || {},1066      blueprintOptions: options.blueprintOptions || {},1067    });1068  },1069  /**1070    Used to add multiple addons to the project's `package.json` and run their1071    `defaultBlueprint` if they provide one.1072    Generally, this would be done from the `afterInstall` hook, to1073    ensure that a package that is required by a given blueprint is1074    available.1075    @method addAddonsToProject1076    @param {Object} options1077    @return {Promise}1078  */1079  addAddonsToProject(options) {1080    let taskOptions = {1081      packages: [],1082      extraArgs: options.extraArgs || [],1083      blueprintOptions: options.blueprintOptions || {},1084    };1085    let packages = options.packages;1086    if (packages && packages.length) {1087      taskOptions.packages = packages.map((pkg) => {1088        if (typeof pkg === 'string') {1089          return pkg;1090        }1091        if (!pkg.name) {1092          throw new SilentError('You must provide a package `name` to addAddonsToProject');1093        }1094        if (pkg.target) {1095          pkg.name += `@${pkg.target}`;1096        }1097        return pkg.name;1098      });1099    } else {1100      throw new SilentError('You must provide package to addAddonsToProject');1101    }1102    let installText = packages.length > 1 ? 'install addons' : 'install addon';1103    this._writeStatusToUI(chalk.green, installText, taskOptions['packages'].join(', '));1104    return this.taskFor('addon-install').run(taskOptions);1105  },1106  /**1107    Used to retrieve a task with the given name. Passes the new task1108    the standard information available (like `ui`, `analytics`, `project`, etc).1109    @method taskFor1110    @param dasherizedName1111    @public1112  */1113  taskFor(dasherizedName) {1114    const Task = require(`../tasks/${dasherizedName}`);1115    return new Task({1116      ui: this.ui,1117      project: this.project,1118      analytics: this.analytics,1119    });1120  },1121  /**1122    Inserts the given content into a file. If the `contentsToInsert` string is already1123    present in the current contents, the file will not be changed unless `force` option1124    is passed.1125    If `options.before` is specified, `contentsToInsert` will be inserted before1126    the first instance of that string.  If `options.after` is specified, the1127    contents will be inserted after the first instance of that string.1128    If the string specified by options.before or options.after is not in the file,1129    no change will be made.1130    If neither `options.before` nor `options.after` are present, `contentsToInsert`1131    will be inserted at the end of the file.1132    Example:1133    ```1134    // app/router.js1135    Router.map(function () {1136    });1137    ```1138    ```1139    insertIntoFile('app/router.js', '  this.route("admin");', {1140      after: 'Router.map(function () {' + EOL1141    }).then(function() {1142      // file has been inserted into!1143    });1144    ```1145    ```1146    // app/router.js1147    Router.map(function () {1148      this.route("admin");1149    });1150    ```1151    @method insertIntoFile1152    @param {String} pathRelativeToProjectRoot1153    @param {String} contentsToInsert1154    @param {Object} providedOptions1155    @return {Promise}1156  */1157  insertIntoFile(pathRelativeToProjectRoot, contentsToInsert, providedOptions) {1158    let fullPath = path.join(this.project.root, pathRelativeToProjectRoot);1159    return insertIntoFile(fullPath, contentsToInsert, providedOptions);1160  },1161  _printCommand: printCommand,1162  printBasicHelp(verbose) {1163    let initialMargin = '      ';1164    let output = initialMargin;1165    if (this.overridden) {1166      output += chalk.grey(`(overridden) ${this.name}`);1167    } else {1168      output += this.name;1169      output += this._printCommand(initialMargin, true);1170      if (verbose) {1171        output += EOL + this.printDetailedHelp(this.availableOptions);1172      }1173    }1174    return output;1175  },1176  printDetailedHelp() {1177    let markdownColor = new MarkdownColor();1178    let filePath = getDetailedHelpPath(this.path);1179    if (Blueprint._existsSync(filePath)) {1180      return markdownColor.renderFile(filePath, { indent: '        ' });1181    }1182    return '';1183  },1184  getJson(verbose) {1185    let json = {};1186    this._printableProperties.forEach((key) => {1187      let value = this[key];1188      if (key === 'availableOptions') {1189        value = _.cloneDeep(value);1190        value.forEach((option) => {1191          if (typeof option.type === 'function') {1192            option.type = option.type.name;1193          }1194        });1195      }1196      json[key] = value;1197    });1198    if (verbose) {1199      let detailedHelp = this.printDetailedHelp(this.availableOptions);1200      if (detailedHelp) {1201        json.detailedHelp = detailedHelp;1202      }1203    }1204    return json;1205  },1206  /**1207    Used to retrieve a blueprint with the given name.1208    @method lookupBlueprint1209    @param {String} dasherizedName1210    @return {Blueprint}1211    @public1212  */1213  lookupBlueprint(dasherizedName) {1214    let projectPaths = this.project ? this.project.blueprintLookupPaths() : [];1215    return Blueprint.lookup(dasherizedName, {1216      paths: projectPaths,1217    });1218  },1219});1220/**1221  @static1222  @method lookup1223  @namespace Blueprint1224  @param {String} name1225  @param {Object} [options]1226  @param {Array} [options.paths] Extra paths to search for blueprints1227  @param {Boolean} [options.ignoreMissing] Throw a `SilentError` if a1228    matching Blueprint could not be found1229  @return {Blueprint}1230*/1231Blueprint.lookup = function (name, options) {1232  options = options || {};1233  if (name.includes(path.sep)) {1234    let blueprintPath = path.resolve(name);1235    let isNameAPath = Boolean(blueprintPath);1236    if (isNameAPath) {1237      if (Blueprint._existsSync(blueprintPath)) {1238        return Blueprint.load(blueprintPath);1239      }1240      if (!options.ignoreMissing) {1241        throw new SilentError(`Unknown blueprint: ${name}`);1242      }1243      return;1244    }1245  }1246  let lookupPaths = generateLookupPaths(options.paths);1247  let lookupPath;1248  for (let i = 0; (lookupPath = lookupPaths[i]); i++) {1249    let blueprintPath = path.resolve(lookupPath, name);1250    if (Blueprint._existsSync(blueprintPath)) {1251      return Blueprint.load(blueprintPath);1252    }1253  }1254  if (!options.ignoreMissing) {1255    throw new SilentError(`Unknown blueprint: ${name}`);1256  }1257};1258/**1259  Loads a blueprint from given path.1260  @static1261  @method load1262  @namespace Blueprint1263  @param {String} blueprintPath1264  @return {Blueprint} blueprint instance1265*/1266Blueprint.load = function (blueprintPath) {1267  if (fs.lstatSync(blueprintPath).isDirectory()) {1268    let Constructor = Blueprint;1269    let constructorPath = path.resolve(blueprintPath, 'index.js');1270    if (Blueprint._existsSync(constructorPath)) {1271      const blueprintModule = require(constructorPath);1272      if (typeof blueprintModule === 'function') {1273        Constructor = blueprintModule;1274      } else {1275        Constructor = Blueprint.extend(blueprintModule);1276      }1277    }1278    return new Constructor(blueprintPath);1279  }1280};1281/**1282  @static1283  @method list1284  @namespace Blueprint1285  @param {Object} [options]1286  @param {Array} [options.paths] Extra paths to search for blueprints1287  @return {Array}1288*/1289Blueprint.list = function (options) {1290  options = options || {};1291  let lookupPaths = generateLookupPaths(options.paths);1292  let seen = [];1293  return lookupPaths.map((lookupPath) => {1294    let source;1295    let packagePath = path.join(lookupPath, '../package.json');1296    if (Blueprint._existsSync(packagePath)) {1297      source = require(packagePath).name;1298    } else {1299      source = path.basename(path.join(lookupPath, '..'));1300    }1301    let blueprints = dir(lookupPath).map((blueprintPath) => {1302      let blueprint = Blueprint.load(blueprintPath);1303      if (blueprint) {1304        let name = blueprint.name;1305        blueprint.overridden = _.includes(seen, name);1306        seen.push(name);1307        return blueprint;1308      }1309    });1310    return {1311      source,1312      blueprints: _.compact(blueprints),1313    };1314  });1315};1316Blueprint._existsSync = function (path, parent) {1317  return fs.existsSync(path, parent);1318};1319Blueprint._readdirSync = function (path) {1320  return fs.readdirSync(path);1321};1322/**1323  Files that are renamed when installed into the target directory.1324  This allows including files in the blueprint that would have an effect1325  on another process, such as a file named `.gitignore`.1326  The keys are the filenames used in the files folder.1327  The values are the filenames used in the target directory.1328  @static1329  @property renamedFiles1330*/1331Blueprint.renamedFiles = {1332  gitignore: '.gitignore',1333};1334/**1335  @static1336  @property ignoredFiles1337*/1338Blueprint.ignoredFiles = initialIgnoredFiles;1339/**1340  @static1341  @property ignoredUpdateFiles1342*/1343Blueprint.ignoredUpdateFiles = ['.gitkeep', 'app.css', 'LICENSE.md'];1344/**1345  @static1346  @property defaultLookupPaths1347*/1348Blueprint.defaultLookupPaths = function () {1349  return [path.resolve(__dirname, '..', '..', 'blueprints')];1350};1351/**1352  @private1353  @method prepareConfirm1354  @param {FileInfo} info1355  @return {Promise}1356*/1357function prepareConfirm(info) {1358  return info.checkForConflict().then((resolution) => {1359    info.resolution = resolution;1360    return info;1361  });1362}1363/**1364  @private1365  @method markIdenticalToBeSkipped1366  @param {FileInfo} info1367*/1368function markIdenticalToBeSkipped(info) {1369  if (info.resolution === 'identical') {1370    info.action = 'skip';1371  }1372}1373/**1374  @private1375  @method markToBeRemoved1376  @param {FileInfo} info1377*/1378function markToBeRemoved(info) {1379  info.action = 'remove';1380}1381/**1382  @private1383  @method gatherConfirmationMessages1384  @param {Array} collection1385  @param {FileInfo} info1386  @return {Array}1387*/1388function gatherConfirmationMessages(collection, info) {1389  if (info.resolution === 'confirm') {1390    collection.push(info.confirmOverwriteTask());1391  }1392  return collection;1393}1394/**1395  @private1396  @method isIgnored1397  @param {FileInfo} info1398  @return {Boolean}1399*/1400function isIgnored(info) {1401  let fn = info.inputPath;1402  return Blueprint.ignoredFiles.some((ignoredFile) => minimatch(fn, ignoredFile, { matchBase: true }));1403}1404/**1405  Combines provided lookup paths with defaults and removes1406  duplicates.1407  @private1408  @method generateLookupPaths1409  @param {Array} lookupPaths1410  @return {Array}1411*/1412function generateLookupPaths(lookupPaths) {1413  lookupPaths = lookupPaths || [];1414  lookupPaths = lookupPaths.concat(Blueprint.defaultLookupPaths());1415  return _.uniq(lookupPaths);1416}1417/**1418  Looks for a __path__ token in the files folder. Must be present for1419  the blueprint to support pod tokens.1420  @private1421  @method hasPathToken1422  @param {files} files1423  @return {Boolean}1424*/1425function hasPathToken(files) {1426  return /__path__/.test(files.join());1427}1428function findAddonByName(addonOrProject, name) {1429  let addon = addonOrProject.addons.find((addon) => addon.name === name);1430  if (addon) {1431    return addon;1432  }1433  return addonOrProject.addons.find((addon) => findAddonByName(addon, name));1434}1435function ensureTargetDirIsAddon(addonPath) {1436  let projectInfo;1437  try {1438    projectInfo = require(path.join(addonPath, 'package.json'));1439  } catch (err) {1440    if (err.code === 'MODULE_NOT_FOUND') {1441      throw new Error(`The directory ${addonPath} does not appear to be a valid addon directory.`);1442    } else {1443      throw err;1444    }1445  }1446  return isAddon(projectInfo.keywords);1447}1448/**1449  @private1450  @method isValidFile1451  @param {Object} fileInfo1452  @return {Promise}1453*/1454function isValidFile(fileInfo) {1455  if (isIgnored(fileInfo)) {1456    return false;1457  } else {1458    return isFilePath(fileInfo);1459  }1460}1461/**1462  @private1463  @method isFilePath1464  @param {Object} fileInfo1465  @return {Promise}1466*/1467function isFilePath(fileInfo) {1468  return fs.statSync(fileInfo.inputPath).isFile();1469}1470/**1471 @private1472 @method dir1473 @return {Array} list of files in the given directory or and empty array if no directory exists1474*/1475function dir(fullPath) {1476  if (Blueprint._existsSync(fullPath)) {1477    return Blueprint._readdirSync(fullPath).map((fileName) => path.join(fullPath, fileName));1478  } else {1479    return [];1480  }1481}1482/**1483  @private1484  @method getDetailedHelpPath1485  @param {String} thisPath1486  @return {String} help path1487*/1488function getDetailedHelpPath(thisPath) {1489  return path.join(thisPath, './HELP.md');1490}1491function finishProcessingForInstall(infos) {1492  infos.forEach(markIdenticalToBeSkipped);1493  let infosNeedingConfirmation = infos.reduce(gatherConfirmationMessages, []);1494  return sequence(infosNeedingConfirmation).then(() => infos);1495}1496function finishProcessingForUninstall(infos) {1497  let validInfos = infos.filter((info) => fs.existsSync(info.outputPath));1498  validInfos.forEach(markToBeRemoved);1499  return validInfos;1500}1501function replaceExtension(filePath, newExt) {1502  const { dir, name } = path.parse(filePath);1503  return path.format({1504    dir,1505    name,1506    ext: newExt,1507  });1508}1509function isTypeScriptFile(filePath) {1510  return path.extname(filePath) === '.ts';1511}...

Full Screen

Full Screen

typescript-blueprint-polyfill.js

Source:typescript-blueprint-polyfill.js Github

copy

Full Screen

1const { removeTypes } = require('remove-types');2const chalk = require('chalk');3const { replaceExtension, isTypeScriptFile } = require('./utils');4module.exports = function (context) {5  const blueprintClass = context._super.constructor.prototype;6  const originalProcessFiles = context.processFiles;7  const originalInstall = context.install;8  const originalUninstall = context.uninstall;9  if (Object.keys(blueprintClass).includes('shouldConvertToJS')) {10    return;11  }12  context.install = function () {13    this.blueprintFunction = 'install';14    return originalInstall.apply(this, arguments);15  };16  context.uninstall = function () {17    this.blueprintFunction = 'uninstall';18    return originalUninstall.apply(this, arguments);19  };20  context.shouldConvertToJS = function (options, fileInfo) {21    // If this isn't turned on, it doesn't matter what else was passed, we're not touching it.22    if (!this.shouldTransformTypeScript) {23      return false;24    }25    // If the blueprint isn't a TS file to begin with, there's nothing to convert.26    if (!isTypeScriptFile(fileInfo.outputPath)) {27      // If the user wants TypeScript output but there is no TypeScript blueprint available, we want28      // to warn them that they're not going to get what they're expecting while still at least giving29      // them the JS output. We check for this *after* checking `shouldTranformTypeScript` because30      // it's possible for people to set `{typescript: true}` in their `.ember-cli` file, which would31      // then erroneously trigger this message every time they generate a JS blueprint even though32      // they didn't pass the flag.33      if (options.typescript === true) {34        this.ui.writeLine(35          chalk.yellow(36            "You passed the '--typescript' flag but there is no TypeScript blueprint available. " +37              'A JavaScript blueprint will be generated instead.'38          )39        );40      }41      return false;42    }43    // Indicates when the user explicitly passed either `--typescript` or `--no-typescript` as opposed44    // to not passing a flag at all and allowing for default behavior45    const userExplicitlySelectedTypeScriptStatus =46      options.typescript !== undefined;47    // Indicates when the user has asked for TypeScript either globally (by setting48    // `isTypeScriptProject` to true) or locally (by passing the `--typescript` flag when they49    // invoked the generator). Although ember-cli merges `.ember-cli` and all of the flag values into50    // one object, we thought the DX would be improved by differentiating between what is intended51    // to be global vs. local config.52    const shouldUseTypeScript = userExplicitlySelectedTypeScriptStatus53      ? options.typescript54      : options.isTypeScriptProject;55    // if the user wants TS output and we have a TS file available, we do *not* want to downlevel to JS56    if (shouldUseTypeScript) {57      return false;58    }59    return true;60  };61  context.convertToJS = async function (fileInfo) {62    let rendered = await fileInfo.render();63    const transformed = await removeTypes(rendered);64    fileInfo.rendered = transformed;65    fileInfo.displayPath = replaceExtension(fileInfo.displayPath, '.js');66    fileInfo.outputPath = replaceExtension(fileInfo.outputPath, '.js');67    return fileInfo;68  };69  context.processFiles = function () {70    const upstreamResult = originalProcessFiles.apply(this, arguments);71    return upstreamResult.then((fileInfos) => {72      return Promise.all(73        fileInfos.map((info) => {74          if (this.shouldConvertToJS(this.options, info)) {75            return this.convertToJS(info);76          }77          return info;78        })79      );80    });81  };82  context._getFileInfos = function (files, intoDir, templateVariables) {83    const fileInfos = files.map(84      this.buildFileInfo.bind(this, intoDir, templateVariables)85    );86    if (this.blueprintFunction === 'install') {87      return fileInfos;88    }89    return fileInfos.reduce((acc, info) => {90      // if it's possible that this blueprint could have produced either typescript OR javascript, we have to do some91      // work to figure out which files to delete.92      if (this.shouldTransformTypeScript) {93        if (this.options.typescript === true) {94          // if the user explicitly passed `--typescript`, we only want to delete TS files, so we stick with the existing95          // info object since it will contain a .ts outputPath (since we know this blueprint is authored in TS because96          // of our check above)97          acc.push(info);98          return acc;99        }100        const jsInfo = Object.create(info);101        Object.assign(jsInfo, {102          outputPath: replaceExtension(info.outputPath, '.js'),103          displayPath: replaceExtension(info.displayPath, '.js'),104        });105        if (this.options.typescript === false) {106          // if the user explicitly passed `--no-typescript`, we only want to delete JS file, so we return our newly107          // created jsInfo object since it contains the javascript version of the output path.108          acc.push(jsInfo);109          return acc;110        }111        if (this.options.typescript === undefined) {112          // if the user didn't specify one way or the other, then both the JS and TS paths are possibilities, so we add113          // both of them to the list. `finishProcessingForUninstall` will actually look to see which of them exists and114          // delete whatever it finds.115          acc.push(info, jsInfo);116          return acc;117        }118      }119      acc.push(info);120      return acc;121    }, []);122  };...

Full Screen

Full Screen

cli.ts

Source:cli.ts Github

copy

Full Screen

...28  .description(pkg.description)29program.command('dev').action(async () => {30  printLogo()31  const config = await getUserSNextConfig()32  const useTypescript = shouldUseTypescript()33  process.env.NODE_ENV = 'development'34  if (config.runtime === 'cloudflare-worker') {35    ensureSNextCloudflareWorkerInstalled()36    const { startWorkerDevServer } = await import('@snext/cloudflare-worker')37    startWorkerDevServer({38      ...config,39      useTypescript,40    })41  } else {42    const { default: startDevServer } = await import('./startDevServer.js')43    startDevServer({44      ...config,45      useTypescript,46      compileNodeCommonJS: config.runtime === 'commonjs',47    })48  }49})50program.command('build').action(async () => {51  printLogo()52  const config = await getUserSNextConfig()53  const useTypescript = shouldUseTypescript()54  process.env.NODE_ENV = 'production'55  if (config.runtime === 'cloudflare-worker') {56    ensureSNextCloudflareWorkerInstalled()57    const { buildForWorker } = await import('@snext/cloudflare-worker')58    console.log()59    console.log('Creating an optimized build...')60    console.log()61    buildForWorker({62      ...config,63      useTypescript,64    })65  } else {66    const { default: build } = await import('./build.js')67    console.log()...

Full Screen

Full Screen

Using AI Code Generation

copy

Full Screen

1describe('My First Test', function() {2  it('Does not do much!', function() {3    expect(true).to.equal(true)4  })5})6{7  "compilerOptions": {8  }9}10{11  "env": {},12  "reporterOptions": {13  },14}15{16  "compilerOptions": {17  }18}19module.exports = (on, config) => {20  require('@cypress/code-coverage/task')(on, config)21}22module.exports = (on, config) => {23  require('@cypress/code-coverage/task')(on, config)24}25import '@cypress/code-coverage/support'26{

Full Screen

Using AI Code Generation

copy

Full Screen

1const cypress = require('cypress');2cypress.shouldUseTypescript();3import * as cypress from 'cypress';4cypress.shouldUseTypescript();5import { shouldUseTypescript } from 'cypress';6shouldUseTypescript();7import shouldUseTypescript from 'cypress';8shouldUseTypescript();9const shouldUseTypescript = require('cypress').shouldUseTypescript;10shouldUseTypescript();11const { shouldUseTypescript } = require('cypress');12shouldUseTypescript();13const shouldUseTypescript = require('cypress/shouldUseTypescript');14shouldUseTypescript();15const shouldUseTypescript = require('cypress/shouldUseTypescript').default;16shouldUseTypescript();17const shouldUseTypescript = require('cypress/shouldUseTypescript').shouldUseTypescript;18shouldUseTypescript();19const { shouldUseTypescript } = require('cypress/shouldUseTypescript');20shouldUseTypescript();21import shouldUseTypescript from 'cypress/shouldUseTypescript';22shouldUseTypescript();23import { shouldUseTypescript } from 'cypress/shouldUseTypescript';24shouldUseTypescript();25import shouldUseTypescript from 'cypress/shouldUseTypescript.js';26shouldUseTypescript();27import { shouldUseTypescript } from 'cypress/shouldUseTypescript.js';28shouldUseTypescript();29import shouldUseTypescript from 'cypress/shouldUseTypescript.ts';30shouldUseTypescript();

Full Screen

Using AI Code Generation

copy

Full Screen

1{2  "dependencies": {3  },4  "devDependencies": {5  },6  "scripts": {7  },8  "cypress-cucumber-preprocessor": {9  }10}11{12  "reporterOptions": {

Full Screen

Using AI Code Generation

copy

Full Screen

1Cypress.shouldUseTypescript = () => {2  return true;3};4Cypress.shouldUseTypescript = () => {5  return false;6};7{8  "compilerOptions": {9  }10}11{12  "compilerOptions": {13  }14}15Cypress.shouldUseTypescript = () => {16  return true;17};18Cypress.shouldUseTypescript = () => {19  return false;20};21Cypress.shouldUseTypescript = () => {22  return true;23};24Cypress.shouldUseTypescript = () => {25  return false;26};27Cypress.shouldUseTypescript = () => {28  return true;29};30Cypress.shouldUseTypescript = () => {31  return false;32};33Cypress.shouldUseTypescript = () => {34  return true;35};36Cypress.shouldUseTypescript = () => {37  return false;38};39Cypress.shouldUseTypescript = () => {40  return true;41};42Cypress.shouldUseTypescript = () => {43  return false;44};45Cypress.shouldUseTypescript = () => {46  return true;47};48Cypress.shouldUseTypescript = () => {49  return false;50};

Full Screen

Using AI Code Generation

copy

Full Screen

1cy.shouldUseTypescript();2Cypress.Commands.add('shouldUseTypescript', function() {3  cy.exec('npm ls typescript').then((result) => {4    if (result.stdout.includes('typescript')) {5      cy.log('Typescript is installed');6    } else {7      cy.log('Typescript is not installed');8    }9  });10});11describe('My First Test', function() {12  it('Does not do much!', function() {13    cy.shouldUseTypescript();14  });15});

Full Screen

Using AI Code Generation

copy

Full Screen

1const { shouldUseTypescript } = require('@nrwl/cypress/plugins/should-use-typescript');2const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin');3module.exports = (on, config) => {4  if (shouldUseTypescript(config)) {5    const { initPlugin } = require('@nrwl/cypress/plugins/init');6    initPlugin(on, config);7  }8  addMatchImageSnapshotPlugin(on, config);9  return config;10};11{12  "compilerOptions": {13  },14}15{16}17describe('app', () => {18  beforeEach(() => cy.visit('/'));19  it('should display welcome message', () => {20    cy.get('h1').should('contain', 'Welcome to app!');21  });22});23export class AppPage {24  navigateTo() {25    return cy.visit('/');26  }27  getParagraphText() {28    return cy.get('h1').should('contain', 'Welcome to app!');29  }30}31import './commands';32import { initPlugin } from '@nrwl/cypress/plugin';33import { addMatchImageSnapshotPlugin } from '

Full Screen

Cypress Tutorial

Cypress is a renowned Javascript-based open-source, easy-to-use end-to-end testing framework primarily used for testing web applications. Cypress is a relatively new player in the automation testing space and has been gaining much traction lately, as evidenced by the number of Forks (2.7K) and Stars (42.1K) for the project. LambdaTest’s Cypress Tutorial covers step-by-step guides that will help you learn from the basics till you run automation tests on LambdaTest.

Chapters:

  1. What is Cypress? -
  2. Why Cypress? - Learn why Cypress might be a good choice for testing your web applications.
  3. Features of Cypress Testing - Learn about features that make Cypress a powerful and flexible tool for testing web applications.
  4. Cypress Drawbacks - Although Cypress has many strengths, it has a few limitations that you should be aware of.
  5. Cypress Architecture - Learn more about Cypress architecture and how it is designed to be run directly in the browser, i.e., it does not have any additional servers.
  6. Browsers Supported by Cypress - Cypress is built on top of the Electron browser, supporting all modern web browsers. Learn browsers that support Cypress.
  7. Selenium vs Cypress: A Detailed Comparison - Compare and explore some key differences in terms of their design and features.
  8. Cypress Learning: Best Practices - Take a deep dive into some of the best practices you should use to avoid anti-patterns in your automation tests.
  9. How To Run Cypress Tests on LambdaTest? - Set up a LambdaTest account, and now you are all set to learn how to run Cypress tests.

Certification

You can elevate your expertise with end-to-end testing using the Cypress automation framework and stay one step ahead in your career by earning a Cypress certification. Check out our Cypress 101 Certification.

YouTube

Watch this 3 hours of complete tutorial to learn the basics of Cypress and various Cypress commands with the Cypress testing at LambdaTest.

Run Cypress automation tests on LambdaTest cloud grid

Perform automation testing on 3000+ real desktop and mobile devices online.

Try LambdaTest Now !!

Get 100 minutes of automation test minutes FREE!!

Next-Gen App & Browser Testing Cloud

Was this article helpful?

Helpful

NotHelpful