docs: function copyPlugin(pinfo, plugins_dir, link, projectRoot) {
  
      var plugin_dir = pinfo.dir;
      var dest = path.join(plugins_dir, pinfo.id);
      var altDest;
      //check if alternative id already exists in plugins directory
      if (pluginMapperotn[pinfo.id]) {
          altDest = path.join(plugins_dir, pluginMapperotn[pinfo.id]);
      }
      else if (pluginMappernto[pinfo.id]) {
          altDest = path.join(plugins_dir, pluginMappernto[pinfo.id]);
      }
      if (fs.existsSync(altDest)) {
          events.emit('log', pinfo.id + '" will not be added because its alternate id "' + altDest + '" is already present.');
          return altDest;
      }
      shell.rm('-rf', dest);
      if (!link && dest.indexOf(path.resolve(plugin_dir) + path.sep) === 0) {
          if (/^win/.test(process.platform)) {
              /*
                  [CB-10423]
                  This is a special case. On windows we cannot create a symlink unless we are run as admin
                  The error that we have is because src contains dest, so we end up with a recursive folder explosion
                  This code avoids copy the one folder that will explode, and allows plugins to contain a demo project
                  and to install the plugin via `cordova plugin add ../`
              */
              var resolvedSrcPath = path.resolve(plugin_dir);
              var filenames = fs.readdirSync(resolvedSrcPath);
              var relPath = path.relative(resolvedSrcPath, dest);
              var relativeRootFolder = relPath.split('\\')[0];
              filenames.splice(filenames.indexOf(relativeRootFolder), 1);
              shell.mkdir('-p', dest);
              events.emit('verbose', 'Copying plugin "' + resolvedSrcPath + '" => "' + dest + '"');
              events.emit('verbose', 'Skipping folder "' + relativeRootFolder + '"');
              filenames.forEach(function (elem) {
                  shell.cp('-R', path.join(resolvedSrcPath, elem), dest);
              });
              return dest;
          }
          else {
              events.emit('verbose', 'Copy plugin destination is child of src. Forcing --link mode.');
              link = true;
          }
      }
      if (link) {
          var isRelativePath = plugin_dir.charAt(1) != ':' && plugin_dir.charAt(0) != path.sep;
          var fixedPath = isRelativePath ? path.join(path.relative(plugins_dir, process.env.PWD || process.cwd()), plugin_dir) : plugin_dir;
          events.emit('verbose', 'Linking "' + dest + '" => "' + fixedPath + '"');
          fs.symlinkSync(fixedPath, dest, 'dir');
      }
      else {
          shell.mkdir('-p', dest);
          events.emit('verbose', 'Copying plugin "' + plugin_dir + '" => "' + dest + '"');
          shell.cp('-R', path.join(plugin_dir, '*'), dest);
          // try to export web
         // var pkgdir = path.join(projectRoot, 'package.json');
        //  var pkg = require(pkgdir);
          var current_module = {};
          try {
            current_module = require(path.join(dest, 'package.json'));
          } catch(ew) {
            events.emit('warn', 'package.json Not Found');
          }
  
          var version = current_module.version || '*';
          try {
              if (pkg.dependencies) {
                  if (!pkg.dependencies[pinfo.id]) {
                      pkg.dependencies[pinfo.id] = version;
  
                  }
                  else {
                      if (pkg.devDependencies) {
                          if (!pkg.devDependencies[pinfo.id]) {
                              pkg.devDependencies[pinfo.id] = version;
                          }
                      }
                  }
                  /*fs.writeFile(pkgdir, JSON.stringify(pkg, null, 2), function (err) {
                    if (err) return console.log(err);
                    events.emit('verbose', 'update' + pkgdir + 'info');
                  });
                  */
              }
          }
          catch (ew) {
              // events.emit('warn', 'package.json not support js module');
          }
  
          projectRoot = projectRoot || process.cwd() ;
          var webdest = path.join(projectRoot, 'node_modules', pinfo.id);
          if (!fs.existsSync(path.join(projectRoot, 'node_modules'))) {
              shell.mkdir('-p', path.join(projectRoot, 'node_modules'));
          }
  
          if (!fs.existsSync(webdest) && fs.existsSync(path.join(plugin_dir, 'js'))) {
              shell.cp('-rf', path.join(plugin_dir, 'js', '*'), webdest);
              //shell.cp('-f', path.join(plugin_dir, 'package.json'), webdest);
              var deps = current_module.dependencies || {};
              if(Object.keys(deps).length>0) {
                console.log('Install Dependences ...');
                return new Promise(function (resolve, reject) {
                  let npm = child_process.exec('npm install', {cwd: webdest}, function (error, stdout, stderr) {
                    if (error) {
                      console.log();
                      let err = verbose ? stderr.toString() : stderr.toString().split('\n')[0].replace(/npm ERR! /ig, '');
                      console.log(err);
                      console.log();
                      return reject(dest);
                    }
                    console.log(stdout.toString());
                    resolve(dest);
  
                  });
                });
              }
  
          }
      }
      return dest;
  }