// TypeScript Version: 3.0
/// <reference types="node" />
import type { URL } from 'url';

export interface DotenvParseOutput {
  [name: string]: string;
}

export interface DotenvPopulateOutput {
  [name: string]: string;
}

export interface DotenvParseOptions {
  /**
   * Default: `false`
   *
   * Use the faster character-scanner parser (from PR #1010).
   *
   * example: `require('dotenv').parse(src, { fast: true })`
   */
  fast?: boolean;
}

/**
 * Parses a string or buffer in the .env file format into an object.
 *
 * See https://dotenvx.com/docs
 *
 * @param src - contents to be parsed. example: `'DB_HOST=localhost'`
 * @param options - parse options. example: `{ fast: true }`
 * @returns an object with keys and values based on `src`. example: `{ DB_HOST : 'localhost' }`
 */
export function parse<T extends DotenvParseOutput = DotenvParseOutput>(
  src: string | Buffer,
  options?: DotenvParseOptions
): T;

export interface DotenvConfigOptions {
  /**
   * Default: `path.resolve(process.cwd(), '.env')`
   *
   * Specify a custom path if your file containing environment variables is located elsewhere.
   * Can also be an array of strings, specifying multiple paths.
   *
   * example: `require('dotenv').config({ path: '/custom/path/to/.env' })`
   * example: `require('dotenv').config({ path: ['/path/to/first.env', '/path/to/second.env'] })`
   */
  path?: string | string[] | URL;

  /**
   * Default: `utf8`
   *
   * Specify the encoding of your file containing environment variables.
   *
   * example: `require('dotenv').config({ encoding: 'latin1' })`
   */
  encoding?: string;

  /**
   * Default: `false`
   *
   * Suppress all output (except errors).
   *
   * example: `require('dotenv').config({ quiet: true })`
   */
  quiet?: boolean;

  /**
   * Default: `false`
   *
   * Turn on logging to help debug why certain keys or values are not being set as you expect.
   *
   * example: `require('dotenv').config({ debug: process.env.DEBUG })`
   */
  debug?: boolean;

  /**
   * Default: `false`
   *
   * Override any environment variables that have already been set on your machine with values from your .env file.
   *
   * example: `require('dotenv').config({ override: true })`
   */
  override?: boolean;

  /**
   * Default: `false`
   *
   * Use the faster character-scanner parser.
   *
   * example: `require('dotenv').config({ fast: true })`
   */
  fast?: boolean;

  /**
   * Default: `process.env`
   *
   * Specify an object to write your secrets to. Defaults to process.env environment variables.
   *
   * example: `const processEnv = {}; require('dotenv').config({ processEnv: processEnv })`
   */
  processEnv?: DotenvPopulateInput;

}

export interface DotenvConfigOutput {
  error?: DotenvError;
  parsed?: DotenvParseOutput;
}

type DotenvError = Error & {
  // `config()` also returns whatever `fs` threw for a path it could not read,
  // most often `ENOENT`, so OBJECT_REQUIRED is not the only possible code.
  code: 'OBJECT_REQUIRED' | (string & {});
}

export interface DotenvPopulateOptions {
  /**
   * Default: `false`
   *
   * Turn on logging to help debug why certain keys or values are not being set as you expect.
   *
   * example: `require('dotenv').populate(processEnv, parsed, { debug: true })`
   */
  debug?: boolean;

  /**
   * Default: `false`
   *
   * Override any environment variables that have already been set on your machine with values from your .env file.
   *
   * example: `require('dotenv').populate(processEnv, parsed, { override: true })`
   */
  override?: boolean;
}

export interface DotenvPopulateInput {
  [name: string]: string | undefined;
}

/**
 * Loads `.env` file contents into process.env by default.
 *
 * See https://dotenvx.com/docs
 *
 * @param options - additional options. example: `{ path: './custom/path', encoding: 'latin1', quiet: false, debug: true, override: false }`
 * @returns an object with a `parsed` key if successful or `error` key if an error occurred. example: { parsed: { KEY: 'value' } }
 *
 */
export function config(options?: DotenvConfigOptions): DotenvConfigOutput;

/**
 * Loads `.env` file contents into process.env.
 *
 * See https://dotenvx.com/docs
 *
 * @param options - additional options. example: `{ path: './custom/path', encoding: 'latin1', quiet: false, debug: true, override: false }`
 * @returns an object with a `parsed` key if successful or `error` key if an error occurred. example: { parsed: { KEY: 'value' } }
 *
 */
export function configDotenv(options?: DotenvConfigOptions): DotenvConfigOutput;

/**
 * Loads `source` json contents into `target` like process.env.
 *
 * See https://dotenvx.com/docs
 *
 * @param processEnv - the target JSON object. in most cases use process.env but you can also pass your own JSON object
 * @param parsed - the source JSON object
 * @param options - additional options. example: `{ debug: true, override: false }`
 * @returns an object with the keys and values that were actually set
 *
 */
export function populate(
  processEnv: DotenvPopulateInput,
  parsed: DotenvPopulateInput,
  options?: DotenvPopulateOptions
): DotenvPopulateOutput;
