Search code examples
yeomanyeoman-generator

Getting the project base path in a yeoman generator


I have updated the yeoman generator dependency from 0.18.10 to 0.20.3. I have updated the deprecated this.dest to this.destinationRoot()

I am now having issues with the generator when it comes to getting the base path of the project, so that I can copy files from one location to another. I have created a function to put the paths together, this then passes to another function which excludes some files from being copied over.

Here is the function I getting the error with

// Copy Bower files to another directory
var copyBowerFiles = function (component, to, exclude) {
  var base = this.destinationRoot(),
      publicDir = base + '/' + this.publicDir,
      publicAssetsDir = publicDir + '/assets',
      bowerComponentsDir = publicAssetsDir + '/bower_components',
      bower,
      from;

  to = (base + '/' + to || publicAssetsDir);
  from = bowerComponentsDir + '/' + component;

  //this.dest.copy(from, to);
  this.bulkDirectory(from, copyDestPathPartial.call(this, to, exclude));
};

This is being called in the end function:

end: function () {
    this.installDependencies({
        callback: function () {
            copyBowerFiles.call('jam', this.publicDir, excludeJamFiles);
        }.bind(this)
    });
}

I get the error message:

var base = this.destinationRoot(),
                ^
TypeError: undefined is not a function

I have also tried sourceRoot()

I would like to update my generator to work with the latest version of the generator. Any help getting this working would be great.

Also do you still have to pass this as the first parameter when calling a function?

EDIT: Here is the copyDestPathPartial function

// Copy destination path partial
var copyDestPathPartial = function (to, exclude) {
  exclude = exclude || [];

  return function (abs, root, sub, file) {
    if (!_.contains(exclude, file) && ! _.contains(exclude, sub)) {
      this.copy(abs, to + '/' + (sub || '') + '/' + file);
    }
  }.bind(this.destinationRoot());
};

When I use this in the copyBowerFiles function I get another error message which says when I call this function:

throw new TypeError('Arguments to path.resolve must be strings');

Is the copyDestPathPartial function not outputting a string?


Solution

  • This is only a JavaScript error, this inside copyBowerFiles is not what you think it is.

    With the code you wrote, this is equal to jam.

    So here you'd want: copyBowerFiles.call(this, 'jam', this.publicDir, excludeJamFiles);. As the first argument to call is the this value. See documentation https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/call

    That being said, assigning random this value is very dirty and super hard to maintain. Why not making copyBowerFiles a prototype method?