import { type PackageDotJson } from '../package-json';
import { type PackageManager } from '../package-manager';
import type { Feature, SentryProjectData, WizardOptions } from '../types';
export declare const SENTRY_DOT_ENV_FILE = ".env.sentry-build-plugin";
export declare const SENTRY_CLI_RC_FILE = ".sentryclirc";
export declare const SENTRY_PROPERTIES_FILE = "sentry.properties";
interface WizardProjectData {
    apiKeys?: {
        token?: string;
    };
    projects?: SentryProjectData[];
}
export interface CliSetupConfig {
    filename: string;
    name: string;
    gitignore: boolean;
    likelyAlreadyHasAuthToken(contents: string): boolean;
    tokenContent(authToken: string): string;
    likelyAlreadyHasOrgAndProject(contents: string): boolean;
    orgAndProjContent(org: string, project: string): string;
    likelyAlreadyHasUrl?(contents: string): boolean;
    urlContent?(url: string): string;
}
export interface CliSetupConfigContent {
    authToken: string;
    org?: string;
    project?: string;
    url?: string;
}
export declare const rcCliSetupConfig: CliSetupConfig;
export declare const propertiesCliSetupConfig: Required<CliSetupConfig>;
/**
 * Aborts the wizard and sets the Sentry transaction status to `cancelled` or `aborted`.
 *
 * @param message The message to display to the user.
 * @param status The status to set on the Sentry transaction. Defaults to `1`.
 */
export declare function abort(message?: string, status?: number): Promise<never>;
export declare function abortIfCancelled<T>(input: T | Promise<T>): Promise<Exclude<T, symbol>>;
export declare function printWelcome(options: {
    wizardName: string;
    promoCode?: string;
    message?: string;
    telemetryEnabled?: boolean;
}): void;
/**
 * Confirms if the user wants to continue with the wizard if the project is not a git repository.
 *
 * @param options.ignoreGitChanges If true, the wizard will not check if the project is a git repository.
 * @param options.cwd The directory of the project. If undefined, the current process working directory will be used.
 */
export declare function confirmContinueIfNoOrDirtyGitRepo(options: {
    ignoreGitChanges: boolean | undefined;
    cwd: string | undefined;
}): Promise<void>;
export declare function askToInstallSentryCLI(): Promise<boolean>;
export declare function askForItemSelection(items: string[], message: string): Promise<{
    value: string;
    index: number;
}>;
export declare function confirmContinueIfPackageVersionNotSupported({ packageId, packageName, packageVersion, acceptableVersions, note, }: {
    packageId: string;
    packageName: string;
    packageVersion: string;
    acceptableVersions: string;
    note?: string;
}): Promise<void>;
type InstallPackageOptions = {
    /** The string that is passed to the package manager CLI as identifier to install (e.g. `@sentry/nextjs`, or `@sentry/nextjs@^8`) */
    packageName: string;
    alreadyInstalled: boolean;
    askBeforeUpdating?: boolean;
    /** Overrides what is shown in the installation logs in place of the `packageName` option. Useful if the `packageName` is ugly (e.g. `@sentry/nextjs@^8`) */
    packageNameDisplayLabel?: string;
    packageManager?: PackageManager;
    /** Add force install flag to command to skip install precondition fails */
    forceInstall?: boolean;
    /** Install as a dev dependency (@default: false) */
    devDependency?: boolean;
};
/**
 * Installs or updates a package with the user's package manager.
 *
 * IMPORTANT: This function modifies the `package.json`! Be sure to re-read
 * it if you make additional modifications to it after calling this function!
 */
export declare function installPackage({ packageName, alreadyInstalled, askBeforeUpdating, packageNameDisplayLabel, packageManager, forceInstall, devDependency, }: InstallPackageOptions): Promise<{
    packageManager?: PackageManager;
}>;
export declare function addSentryCliConfig({ authToken, org, project, url }: CliSetupConfigContent, setupConfig?: CliSetupConfig): Promise<void>;
export declare function addDotEnvSentryBuildPluginFile(authToken: string): Promise<void>;
/**
 * Runs available formatters (Prettier and/or Biome) on the changed or untracked files in the project.
 * This function provides a unified interface for running multiple formatters with a single user prompt.
 *
 * @param _opts The directory of the project. If undefined, the current process working directory will be used.
 */
export declare function runFormatters(_opts: {
    cwd: string | undefined;
}): Promise<void>;
/**
 * Runs prettier on the changed or untracked files in the project.
 *
 * @param options.cwd The directory of the project. If undefined, the current process working directory will be used.
 */
export declare function runPrettierIfInstalled(opts: {
    cwd: string | undefined;
}): Promise<void>;
/**
 * Runs Biome on the changed or untracked files in the project.
 *
 * @param options.cwd The directory of the project. If undefined, the current process working directory will be used.
 */
export declare function runBiomeIfInstalled(opts: {
    cwd: string | undefined;
}): Promise<void>;
/**
 * Checks if @param packageId is listed as a dependency in @param packageJson.
 * If not, it will ask users if they want to continue without the package.
 *
 * Use this function to check if e.g. a the framework of the SDK is installed
 *
 * @param packageJson the package.json object
 * @param packageId the npm name of the package
 * @param packageName a human readable name of the package
 */
export declare function ensurePackageIsInstalled(packageJson: PackageDotJson, packageId: string, packageName: string): Promise<void>;
export declare function getPackageDotJson(): Promise<PackageDotJson>;
export declare function updatePackageDotJson(packageDotJson: PackageDotJson): Promise<void>;
/**
 * Use this function to get the used JS Package manager.
 *
 * This function:
 * - attempts to auto-detect the used package manager and return it
 * - if unsuccessful, returns the passed fallback package manager
 * - if no fallback is passed, it asks the user to select a package manager
 *
 * The result is cached on the first invocation to avoid asking the user multiple times.
 *
 * @param fallback the package manager to use if auto-detection fails and you don't want to
 * ask the user. This is useful in cases where asking users would be too intrusive/low in value
 * and where it's okay to fall back to a default package manager. Use this with caution.
 */
export declare function getPackageManager(fallback?: PackageManager): Promise<PackageManager>;
export declare function isUsingTypeScript(): boolean;
/**
 * Checks if we already got project data from a previous wizard invocation.
 * If yes, this data is returned.
 * Otherwise, we start the login flow and ask the user to select a project.
 *
 * Use this function to get project data for the wizard.
 *
 * @param options wizard options
 * @param platform the platform of the wizard
 * @returns project data (org, project, token, url)
 */
export declare function getOrAskForProjectData(options: WizardOptions, platform?: 'javascript-angular' | 'javascript-nextjs' | 'javascript-nuxt' | 'javascript-react-router' | 'javascript-remix' | 'javascript-sveltekit' | 'node-cloudflare-workers' | 'apple-ios' | 'android' | 'react-native' | 'flutter'): Promise<{
    sentryUrl: string;
    selfHosted: boolean;
    selectedProject: SentryProjectData;
    authToken: string;
    spotlight: false;
} | {
    spotlight: true;
}>;
/**
 * Exported for testing
 */
export declare function askForWizardLogin(options: {
    url: string;
    promoCode?: string;
    platform?: 'javascript-angular' | 'javascript-nextjs' | 'javascript-nuxt' | 'javascript-react-router' | 'javascript-remix' | 'javascript-sveltekit' | 'node-cloudflare-workers' | 'apple-ios' | 'android' | 'react-native' | 'flutter';
    orgSlug?: string;
    projectSlug?: string;
    comingFrom?: string;
}): Promise<WizardProjectData>;
/**
 * Asks users if they have a config file for @param tool (e.g. Vite).
 * If yes, asks users to specify the path to their config file.
 *
 * Use this helper function as a fallback mechanism if the lookup for
 * a config file with its most usual location/name fails.
 *
 * @param toolName Name of the tool for which we're looking for the config file
 * @param configFileName Name of the most common config file name (e.g. vite.config.js)
 *
 * @returns a user path to the config file or undefined if the user doesn't have a config file
 */
export declare function askForToolConfigPath(toolName: string, configFileName: string): Promise<string | undefined>;
type ShowCopyPasteInstructionsOptions = {
    codeSnippet: string;
} & ({
    filename: string;
    hint?: string;
} | {
    instructions: string;
});
/**
 * Prints copy/paste-able instructions to the console.
 * Afterwards asks the user if they added the code snippet to their file.
 *
 * While there's no point in providing a "no" answer here, it gives users time to fulfill the
 * task before the wizard continues with additional steps.
 *
 * Use this function if you want to show users instructions on how to add/modify
 * code in their file. This is helpful if automatic insertion failed or is not possible/feasible.
 *
 * @param filename the name of the file to which the code snippet should be applied.
 * If a path is provided, only the filename will be used.
 *
 * @param codeSnippet the snippet to be printed. Use {@link makeCodeSnippet}  to create the
 * diff-like format for visually highlighting unchanged or modified lines of code.
 *
 * @param hint (optional) a hint to be printed after the main instruction to add
 * the code from @param codeSnippet to their @param filename.
 *
 * More guidelines on copy/paste instructions:
 * @see {@link https://develop.sentry.dev/sdk/setup-wizards/#copy--paste-snippets}
 *
 * TODO: refactor copy paste instructions across different wizards to use this function.
 *       this might require adding a custom message parameter to the function
 */
export declare function showCopyPasteInstructions(opts: ShowCopyPasteInstructionsOptions): Promise<void>;
/**
 * Callback that exposes formatting helpers for a code snippet.
 * @param unchanged - Formats text as old code.
 * @param plus - Formats text as new code.
 * @param minus - Formats text as removed code.
 */
type CodeSnippetFormatter = (unchanged: (txt: string) => string, plus: (txt: string) => string, minus: (txt: string) => string) => string;
/**
 * Crafts a code snippet that can be used to e.g.
 * - print copy/paste instructions to the console
 * - create a new config file.
 *
 * @param colors set this to true if you want the final snippet to be colored.
 * This is useful for printing the snippet to the console as part of copy/paste instructions.
 *
 * @param callback the callback that returns the formatted code snippet.
 * It exposes takes the helper functions for marking code as unchanged, new or removed.
 * These functions no-op if no special formatting should be applied
 * and otherwise apply the appropriate formatting/coloring.
 * (@see {@link CodeSnippetFormatter})
 *
 * @see {@link showCopyPasteInstructions} for the helper with which to display the snippet in the console.
 *
 * @returns a string containing the final, formatted code snippet.
 */
export declare function makeCodeSnippet(colors: boolean, callback: CodeSnippetFormatter): string;
/**
 * Creates a new config file with the given @param filepath and @param codeSnippet.
 *
 * Use this function to create a new config file for users. This is useful
 * when users answered that they don't yet have a config file for a tool.
 *
 * (This doesn't mean that they don't yet have some other way of configuring
 * their tool but we can leave it up to them to figure out how to merge configs
 * here.)
 *
 * @param filepath absolute path to the new config file
 * @param codeSnippet the snippet to be inserted into the file
 * @param moreInformation (optional) the message to be printed after the file was created
 * For example, this can be a link to more information about configuring the tool.
 *
 * @returns true on success, false otherwise
 */
export declare function createNewConfigFile(filepath: string, codeSnippet: string, moreInformation?: string): Promise<boolean>;
export declare function askShouldCreateExamplePage(customRoute?: string): Promise<boolean>;
export declare function askShouldCreateExampleComponent(): Promise<boolean>;
export declare function featureSelectionPrompt<F extends ReadonlyArray<Feature>>(features: F): Promise<{
    [key in F[number]['id']]: boolean;
}>;
export declare function askShouldInstallPackage(pkgName: string): Promise<boolean>;
export declare function askShouldAddPackageOverride(pkgName: string, pkgVersion: string): Promise<boolean>;
export declare function artifactsExist(relativePath: string): boolean;
export declare function askToRunBuildOrEnterPathOrProceed({ relativeArtifactPath, }: {
    relativeArtifactPath: string;
}): Promise<{
    validPath: boolean;
    relativeArtifactPath?: string;
}>;
export {};
