lib/plugins/package/lib/zipService.js/excludeNodeDevDependencies
function excludeNodeDevDependencies(servicePath) {
  const exAndIn = {
    include: [],
    exclude: [],
  };

  // the files where we'll write the dependencies into
  const tmpDir = os.tmpdir();
  const randHash = crypto.randomBytes(8).toString('hex');
  const nodeDevDepFile = path.join(tmpDir, `node-dependencies-${randHash}-dev`);
  const nodeProdDepFile = path.join(tmpDir, `node-dependencies-${randHash}-prod`);

  try {
    const packageJsonFilePaths = globby.sync(
      [
        '**/package.json',
        // TODO add glob for node_modules filtering
      ],
      {
        cwd: servicePath,
        dot: true,
        silent: true,
        follow: true,
        nosort: true,
      }
    );

    // filter out non node_modules file paths
    const packageJsonPaths = _.filter(packageJsonFilePaths, filePath => {
      const isNodeModulesDir = !!filePath.match(/node_modules/);
      return !isNodeModulesDir;
    });

    if (_.isEmpty(packageJsonPaths)) {
      return BbPromise.resolve(exAndIn);
    }

    // NOTE: using mapSeries here for a sequential computation (w/o race conditions)
    return (
      BbPromise.mapSeries(packageJsonPaths, packageJsonPath => {
        // the path where the package.json file lives
        const fullPath = path.join(servicePath, packageJsonPath);
        const dirWithPackageJson = fullPath.replace(path.join(path.sep, 'package.json'), '');

        // we added a catch which resolves so that npm commands with an exit code of 1
        // (e.g. if the package.json is invalid) won't crash the dev dependency exclusion process
        return BbPromise.map(['dev', 'prod'], env => {
          const depFile = env === 'dev' ? nodeDevDepFile : nodeProdDepFile;
          return childProcess
            .execAsync(
              `npm ls --${env}=true --parseable=true --long=false --silent >> ${depFile}`,
              { cwd: dirWithPackageJson }
            )
            .catch(() => BbPromise.resolve());
        });
      })
        // NOTE: using mapSeries here for a sequential computation (w/o race conditions)
        .then(() =>
          BbPromise.mapSeries(['dev', 'prod'], env => {
            const depFile = env === 'dev' ? nodeDevDepFile : nodeProdDepFile;
            return fs
              .readFileAsync(depFile)
              .then(fileContent =>
                _.compact(
                  _.uniq(_.split(fileContent.toString('utf8'), '\n')),
                  elem => elem.length > 0
                )
              )
              .catch(() => BbPromise.resolve());
          })
        )
        .then(devAndProDependencies => {
          const devDependencies = devAndProDependencies[0];
          const prodDependencies = devAndProDependencies[1];

          // NOTE: the order for _.difference is important
          const dependencies = _.difference(devDependencies, prodDependencies);
          const nodeModulesRegex = new RegExp(`${path.join('node_modules', path.sep)}.*`, 'g');

          if (!_.isEmpty(dependencies)) {
            return BbPromise.map(dependencies, item =>
              item.replace(path.join(servicePath, path.sep), '')
            )
              .filter(item => item.length > 0 && item.match(nodeModulesRegex))
              .reduce((globs, item) => {
                const packagePath = path.join(servicePath, item, 'package.json');
                return fs.readFileAsync(packagePath, 'utf-8').then(packageJsonFile => {
                  const lastIndex = item.lastIndexOf(path.sep) + 1;
                  const moduleName = item.substr(lastIndex);
                  const modulePath = item.substr(0, lastIndex);

                  const packageJson = JSON.parse(packageJsonFile);
                  const bin = packageJson.bin;

                  const baseGlobs = [path.join(item, '**')];

                  // NOTE: pkg.bin can be object, string, or undefined
                  if (typeof bin === 'object') {
                    _.each(_.keys(bin), executable => {
                      baseGlobs.push(path.join(modulePath, '.bin', executable));
                    });
                    // only 1 executable with same name as lib
                  } else if (typeof bin === 'string') {
                    baseGlobs.push(path.join(modulePath, '.bin', moduleName));
                  }

                  return globs.concat(baseGlobs);
                });
              }, [])
              .then(globs => {
                exAndIn.exclude = exAndIn.exclude.concat(globs);
                return exAndIn;
              });
          }

          return exAndIn;
        })
        .then(() => {
          // cleanup
          fs.unlinkSync(nodeDevDepFile);
          fs.unlinkSync(nodeProdDepFile);
          return exAndIn;
        })
        .catch(() => exAndIn)
    );
  } catch (e) {
    // fail silently
  }
}