<commit_before>import * as path from 'path';

import chalk from 'chalk';
import * as semver from 'semver';

import { fsReadDir, fsReadFile, pathExists } from '@ionic/cli-framework/utils/fs';
import { readPackageJsonFile } from '@ionic/cli-framework/utils/npm';

import { IAilmentRegistry } from '../../../definitions';
import { App } from '../../app';
import { getIonicRemote, isRepoInitialized } from '../../git';
import { pkgLatestVersion, pkgManagerArgs } from '../../utils/npm';
import { getPlatforms } from '../../integrations/cordova/project';
import { ConfigXml } from '../../integrations/cordova/config';

import { Ailment, AutomaticallyTreatableAilment, AutomaticallyTreatableAilmentDeps } from './base';
export * from './base';

export function registerAilments(registry: IAilmentRegistry, deps: AutomaticallyTreatableAilmentDeps) {
  registry.register(new NpmInstalledLocally(deps));
  registry.register(new IonicCLIInstalledLocally(deps));
  registry.register(new GitNotUsed(deps));
  registry.register(new GitConfigInvalid(deps));
  registry.register(new IonicNativeUpdateAvailable(deps));
  registry.register(new IonicNativeMajorUpdateAvailable(deps));
  registry.register(new IonicNativeOldVersionInstalled(deps));
  registry.register(new UnsavedCordovaPlatforms(deps));
  registry.register(new DefaultCordovaBundleIdUsed(deps));
  registry.register(new ViewportFitNotSet(deps));
  registry.register(new CordovaPlatformsCommitted(deps));
}

class NpmInstalledLocally extends AutomaticallyTreatableAilment {
  id = 'npm-installed-locally';

  async getMessage() {
    return (
      `${chalk.bold('npm')} is installed locally.\n` +
      `${chalk.bold('npm')} is typically installed globally and may cause some confusion about versions when other CLIs use it.\n`
    ).trim();
  }

  async detected() {
    return pathExists(path.join(this.project.directory, 'node_modules', 'npm'));
  }

  async getTreatmentSteps() {
    const config = await this.config.load();
    const { npmClient } = config;
    const [ manager, ...managerArgs ] = await pkgManagerArgs({ npmClient, shell: this.shell }, { command: 'uninstall', pkg: 'npm' });

    return [
      {
        name: `Run: ${chalk.green(manager + ' ' + managerArgs.join(' '))}`,
        treat: async () => {
          await this.shell.run(manager, managerArgs, {});
        },
      },
    ];
  }
}

class IonicCLIInstalledLocally extends AutomaticallyTreatableAilment {
  id = 'ionic-installed-locally';

  async getMessage() {
    return (
      `The Ionic CLI is installed locally.\n` +
      `While the CLI can run locally, there's no longer a reason to have it installed locally and it may cause some confusion over configuration and versions.\n`
    ).trim();
  }

  async detected() {
    return pathExists(path.join(this.project.directory, 'node_modules', 'ionic'));
  }

  async getTreatmentSteps() {
    const config = await this.config.load();
    const { npmClient } = config;
    const [ manager, ...managerArgs ] = await pkgManagerArgs({ npmClient, shell: this.shell }, { command: 'uninstall', pkg: 'ionic' });

    return [
      {
        name: `Run: ${chalk.green(manager + ' ' + managerArgs.join(' '))}`,
        treat: async () => {
          await this.shell.run(manager, managerArgs, {});
        },
      },
    ];
  }
}

class GitNotUsed extends Ailment {<commit_msg>fix(doctor): detect local proxy plugin w/o local cli<commit_after>import * as path from 'path';

import chalk from 'chalk';
import * as semver from 'semver';

import { fsReadDir, fsReadFile, pathExists } from '@ionic/cli-framework/utils/fs';
import { readPackageJsonFile } from '@ionic/cli-framework/utils/npm';

import { IAilmentRegistry } from '../../../definitions';
import { App } from '../../app';
import { getIonicRemote, isRepoInitialized } from '../../git';
import { pkgLatestVersion, pkgManagerArgs } from '../../utils/npm';
import { getPlatforms } from '../../integrations/cordova/project';
import { ConfigXml } from '../../integrations/cordova/config';

import { Ailment, AutomaticallyTreatableAilment, AutomaticallyTreatableAilmentDeps } from './base';
export * from './base';

export function registerAilments(registry: IAilmentRegistry, deps: AutomaticallyTreatableAilmentDeps) {
  registry.register(new NpmInstalledLocally(deps));
  registry.register(new IonicCLIInstalledLocally(deps));
  registry.register(new IonicCLIPluginProxyInstalledLocally(deps));
  registry.register(new GitNotUsed(deps));
  registry.register(new GitConfigInvalid(deps));
  registry.register(new IonicNativeUpdateAvailable(deps));
  registry.register(new IonicNativeMajorUpdateAvailable(deps));
  registry.register(new IonicNativeOldVersionInstalled(deps));
  registry.register(new UnsavedCordovaPlatforms(deps));
  registry.register(new DefaultCordovaBundleIdUsed(deps));
  registry.register(new ViewportFitNotSet(deps));
  registry.register(new CordovaPlatformsCommitted(deps));
}

class NpmInstalledLocally extends AutomaticallyTreatableAilment {
  id = 'npm-installed-locally';

  async getMessage() {
    return (
      `${chalk.bold('npm')} is installed locally.\n` +
      `${chalk.bold('npm')} is typically installed globally and may cause some confusion about versions when other CLIs use it.\n`
    ).trim();
  }

  async detected() {
    return pathExists(path.join(this.project.directory, 'node_modules', 'npm'));
  }

  async getTreatmentSteps() {
    const config = await this.config.load();
    const { npmClient } = config;
    const [ manager, ...managerArgs ] = await pkgManagerArgs({ npmClient, shell: this.shell }, { command: 'uninstall', pkg: 'npm' });

    return [
      {
        name: `Run: ${chalk.green(manager + ' ' + managerArgs.join(' '))}`,
        treat: async () => {
          await this.shell.run(manager, managerArgs, {});
        },
      },
    ];
  }
}

class IonicCLIInstalledLocally extends AutomaticallyTreatableAilment {
  id = 'ionic-installed-locally';

  async getMessage() {
    return (
      `The Ionic CLI is installed locally.\n` +
      `While the CLI can run locally, there's no longer a reason to have it installed locally and it may cause some confusion over configuration and versions.\n`
    ).trim();
  }

  async detected() {
    return pathExists(path.join(this.project.directory, 'node_modules', 'ionic'));
  }

  async getTreatmentSteps() {
    const config = await this.config.load();
    const { npmClient } = config;
    const [ manager, ...managerArgs ] = await pkgManagerArgs({ npmClient, shell: this.shell }, { command: 'uninstall', pkg: 'ionic' });

    return [
      {
        name: `Run: ${chalk.green(manager + ' ' + managerArgs.join(' '))}`,
        treat: async () => {
          await this.shell.run(manager, managerArgs, {});
        },
      },
    ];
  }
}

class IonicCLIPluginProxyInstalledLocally extends AutomaticallyTreatableAilment {
  id = 'ionic-cli-plugin-proxy-installed-locally-without-local-cli';

  async getMessage() {
    return (
      `${chalk.bold('@ionic/cli-plugin-proxy')} is installed locally.\n` +
      `The plugin for proxying CLI requests, ${chalk.bold('@ionic/cli-plugin-proxy')}, was detected in your project, but no local CLI installation was found. You can safely remove it if you're using the CLI globally.\n`
    ).trim();
  }

  async detected() {
    const cliExists = await pathExists(path.join(this.project.directory, 'node_modules', 'ionic'));
    return !cliExists && pathExists(path.join(this.project.directory, 'node_modules', '@ionic/cli-plugin-proxy'));
  }

  async getTreatmentSteps() {
    const config = await this.config.load();
    const { npmClient } = config;
    const [ manager, ...managerArgs ] = await pkgManagerArgs({ npmClient, shell: this.shell }, { command: 'uninstall', pkg: '@ionic/cli-plugin-proxy' });

    return [
      {
        name: `Run: ${chalk.green(manager + ' ' + managerArgs.join(' '))}`,
        treat: async () => {
          await this.shell.run(manager, managerArgs, {});
        },
      },
    ];
  }
}

class GitNotUsed extends Ailment {
{'fraction_non_alphanumeric': 0.14225317085302164, 'fraction_numerical': 0.0, 'mean_word_length': 3.8219424460431655, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 8, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '7056965', 'n_tokens_mistral': 2491, 'n_tokens_neox': 2393, 'n_words': 573}