async function updateConfigFiles()

in src/update.js [29:105]


async function updateConfigFiles(fromConfigPath, toConfigPath, creds) {
  fromConfigPath = path.resolve(fromConfigPath);
  toConfigPath = path.resolve(toConfigPath);

  const fromConfigs = [];
  const toConfigs = [];
  const registryAuthConfigs = new Map();

  // We do not use basic auth any more in `gcloud artifacts print-settings`; replace them.
  let fromConfigLines = await fs.promises.readFile(fromConfigPath, "utf8")
  const legacyRegex = /(\/\/[a-zA-Z1-9-]+[-]npm[.]pkg[.]dev\/.*\/):_password=.*(\n\/\/[a-zA-Z1-9-]+[-]npm[.]pkg[.]dev\/.*\/:username=oauth2accesstoken)/g;
  fromConfigLines = fromConfigLines.replace(legacyRegex, `$1:_authToken=${creds}`)

  // Read configs from project npmrc file. For each:
  // - registry config, create an auth token config in the user npmrc file (expect an auth token or password config already exists)
  // - auth token config, print a warning and remove it.
  // - password config, print a warning and move it to the user npmrc file.
  // - everything else, keep it in the project npmrc file.
  for (const line of fromConfigLines.split('\n')) {
    let config = c.parseConfig(line.trim());
    switch (config.type) {
      case c.configType.Registry:
        fromConfigs.push(config);
        registryAuthConfigs.set(config.registry, {
          type: c.configType.AuthToken,
          registry: config.registry,
          token: creds,
          toString: function() {
            return `${this.registry}:_authToken=${this.token}`;
          }
        });
        break;
      case c.configType.AuthToken:
        logger.debug(`Found an auth token for the registry ${config.registry} in the project npmrc file. Moving it to the user npmrc file...`);
        break;
      case c.configType.Password:
        logger.debug(`Found password for the registry ${config.registry} in the project npmrc file. Moving it to the user npmrc file...`);
        registryAuthConfigs.set(config.registry, config);
        break;
      default:
        fromConfigs.push(config);
    }
  }

  if (fs.existsSync(toConfigPath)) {
    const toConfigLines = await fs.promises.readFile(toConfigPath, "utf8")

    // refresh tokens for all auth token configs; keep everything else unchanged.
    for (const line of toConfigLines.split('\n')) {
      if (line == "") {
        continue;
      }
      let config = c.parseConfig(line.trim());
      if (config.type == c.configType.AuthToken || config.type == c.configType.Password) {
        registryAuthConfigs.delete(config.registry);
      }
      // refresh the token.
      if (config.type == c.configType.AuthToken) {
        config.token = creds;
      }
      toConfigs.push(config);
    }
  }

  // Registries that we need to move password configs from the project npmrc file
  // or write a new auth token config.
  toConfigs.push(...registryAuthConfigs.values());

  // Write to the user npmrc file first so that if it failed the project npmrc file
  // would still be untouched.
  await fs.promises.writeFile(toConfigPath, toConfigs.join(`\n`));
  if(fromConfigPath !== toConfigPath) {
    // If the files are the same (and likely the user .npmrc file) only write once with the auth configs
    // Otherwise, we'd overwrite this file without adding the credentials
    await fs.promises.writeFile(fromConfigPath, fromConfigs.join(`\n`));
  }
}