function main()

in internal/pkg_npm/packager.js [98:233]


function main(args) {
  args = fs.readFileSync(args[0], {encoding: 'utf-8'}).split('\n').map(unquoteArgs);
  const
      [outDir, owningPackageName, srcsArg, depsArg, packagesArg, substitutionsArg,
       volatileFile, infoFile, vendorExternalArg, target, validate, packageNameArg] = args;

  /** @type BazelFileInfo[] */
  const srcs = JSON.parse(srcsArg);

  /** @type BazelFileInfo[] */
  const deps = JSON.parse(depsArg);

  /** @type BazelFileInfo[] */
  const packages = JSON.parse(packagesArg);

  const vendorExternal = vendorExternalArg.split(',').filter(s => !!s);

  const substitutions = [
    // Strip content between BEGIN-INTERNAL / END-INTERNAL comments
    [/(#|\/\/)\s+BEGIN-INTERNAL[\w\W]+?END-INTERNAL/g, ''],
  ];
  const rawReplacements = JSON.parse(substitutionsArg);
  for (const key of Object.keys(rawReplacements)) {
    substitutions.push([new RegExp(key, 'g'), rawReplacements[key]])
  }
  // Replace statuses last so that earlier substitutions can add
  // status-related placeholders
  if (volatileFile || infoFile) {
    const statuses = {
      ...parseStatusFile(volatileFile),
      ...parseStatusFile(infoFile),
    };
    // Looks like {'BUILD_SCM_VERSION': 'v1.2.3'}
    for (let idx = 0; idx < substitutions.length; idx++) {
      const match = substitutions[idx][1].match(/\{(.*)\}/);
      if (!match) continue;
      const statusKey = match[1];
      let statusValue = statuses[statusKey];
      if (statusValue) {
        // npm versions must be numeric, so if the VCS tag starts with leading 'v', strip it
        // See https://github.com/bazelbuild/rules_nodejs/pull/1591
        if (statusKey.endsWith('_VERSION')) {
          statusValue = statusValue.replace(/^v/, '');
        }
        substitutions[idx][1] = statusValue;
      }
    }
  }

  // src like owningPackageName/my/path is just copied to outDir/my/path
  for (let srcFile of srcs) {
    if (srcFile.shortPath.startsWith('../')) {
      // If src is from external workspace drop the ../wksp portion
      copyWithReplace(srcFile.path, path.join(outDir,
          srcFile.shortPath.split('/').slice(2).join('/')), substitutions);
    } else {
      // Source is from local workspace
      if (!srcFile.path.startsWith(owningPackageName)) {
        throw new Error(
            `${srcFile.shortPath} in 'srcs' does not reside in the base directory, ` +
            `generated file should belong in 'deps' instead.`);
      }

      const outRelativePath = getOwningPackageRelativeOutPath(srcFile);

      if (validate === "true" && outRelativePath === "package.json") {
        const packageJson = JSON.parse(fs.readFileSync(srcFile.path, 'utf8'));
        if (packageJson['name'] !== packageNameArg) {
          console.error(`ERROR: pkg_npm rule ${
            target} was configured with attributes that don't match the package.json`);
          console.error(` - attribute package_name=${packageNameArg} does not match package.json name=${packageJson['name']}`)
          console.error('You can automatically fix this by running:');
          console.error(
              `    npx @bazel/buildozer 'set package_name "${packageJson['name']}"' ${target}`);
          console.error('Or to suppress this error, run:');
          console.error(`    npx @bazel/buildozer 'set validate False' ${target}`);
          return 1;
        }
      }
      copyWithReplace(srcFile.path, path.join(outDir, outRelativePath), substitutions);
    }
  }

  /**
   * Gets the output path for the given file, relative to the output package directory.
   * e.g. if the file path is `bazel-out/<..>/bin/packages/core/index.js` and the
   * owning package is `packages/core`, then `index.js` is being returned.
   * @param file {BazelFileInfo}
   * @returns {string}
   */
  function getOwningPackageRelativeOutPath(file) {
    for (const workspaceName of vendorExternal) {
      if (file.shortPath.startsWith(`../${workspaceName}`)) {
        return path.relative(`../${workspaceName}`, file.shortPath);
      }
    }

    return path.relative(owningPackageName, file.shortPath);
  }

  // Deps like bazel-bin/baseDir/my/path is copied to outDir/my/path.
  for (const dep of deps) {
    const outPath = path.join(outDir, getOwningPackageRelativeOutPath(dep));
    try {
      copyWithReplace(dep.path, outPath, substitutions);
    } catch (e) {
      console.error(`Failed to copy ${dep} to ${outPath}`);
      throw e;
    }
  }

  // package contents like bazel-bin/baseDir/my/directory/* is
  // recursively copied to outDir/my/*
  for (const pkg of packages) {
    const outRelativePath = path.dirname(getOwningPackageRelativeOutPath(pkg));
    const outExecPath = path.join(outDir, outRelativePath);

    function copyRecursive(base, file) {
      const absolutePath = path.join(base, file);
      file = file.replace(/\\/g, '/');

      if (fs.lstatSync(absolutePath).isDirectory()) {
        const files = fs.readdirSync(absolutePath);

        files.forEach(f => {
          copyRecursive(base, path.join(file, f));
        });
      } else {
        copyWithReplace(absolutePath, path.join(outExecPath, file), substitutions);
      }
    }
    fs.readdirSync(pkg.path).forEach(f => {
      copyRecursive(pkg.path, f);
    });
  }
}