/* tslint:disable */
/* eslint-disable */
import type { Node } from 'estree';
/**
 * Create a new instrumentation matcher from an array of instrumentation configs.
 */
export function create(configs: InstrumentationConfig[], dc_module?: string | null): InstrumentationMatcher;
/**
 * Output of a transformation operation
 */
export interface TransformOutput {
    /**
     * The transformed JavaScript code
     */
    code: string;
    /**
     * The sourcemap for the transformation (if generated)
     */
    map: string | undefined;
}

/**
 * The kind of function
 */
export type FunctionKind = "Sync" | "Async" | "Callback" | "Auto";

/**
 * Describes which function to instrument
 */
export type FunctionQuery = { className: string; methodName: string; kind: FunctionKind; index?: number | null; isExportAlias?: boolean } | { className: string; privateMethodName: string; kind: FunctionKind; index?: number | null } | { className: string; index?: number | null; isExportAlias?: boolean } | { methodName: string; kind: FunctionKind; index?: number | null } | { functionName: string; kind: FunctionKind; index?: number | null; isExportAlias?: boolean } | { expressionName: string; kind: FunctionKind; index?: number | null; isExportAlias?: boolean };

/**
 * The merged instrumentation state passed to a transform function: the fields
 * of the matched {@link InstrumentationConfig} (with `functionQuery`'s export
 * aliases resolved to local names) plus runtime fields added by the
 * transformer for the current file.
 */
export type KnownState = InstrumentationConfig & {
    /** The diagnostics_channel module specifier injected into instrumented code */
    dcModule: string;
    /** Whether the file being transformed is ESM or CJS */
    moduleType: ModuleType;
    /** The version of the module being instrumented */
    moduleVersion: string;
    /** The resolved operator name: a built-in (e.g. `'traceSync'`) or a custom transform name */
    operator: string;
    /** The merged transform map (built-ins plus `addTransform` overrides) used for dispatch */
    transforms: Record<string, CustomTransform> & { defaults: Record<string, CustomTransform> };
    /** Counter of function nodes matched so far, used for `index`-based selection */
    functionIndex?: number;
};

/**
 * A custom transform function registered via `addTransform`.
 * Receives the instrumentation state and the matched AST node.
 */
export type CustomTransform<ExtraState = Record<string, unknown>> = (state: KnownState & ExtraState, node: Node, parent: Node, ancestry: Node[]) => void;

/**
 * The behaviour-only fields of a `FunctionQuery`. Used together with `astQuery`,
 * where the raw selector chooses the node and these fields drive how it is
 * wrapped (the name-based matching fields are ignored).
 */
export interface FunctionBehavior {
    kind?: FunctionKind;
    index?: number | null;
    callbackIndex?: number;
    mutableResult?: boolean;
}

/**
 * Configuration for injecting instrumentation code.
 *
 * Either `functionQuery` (name-based matching) or `astQuery` (a raw esquery
 * selector) must identify the node(s) to instrument. When `astQuery` is set it
 * takes precedence over `functionQuery`'s matching fields, and `functionQuery`
 * becomes an optional bag of behaviour options ({@link FunctionBehavior}).
 */
export type InstrumentationConfig =
    | {
        /** The name of the diagnostics channel to publish to */
        channelName: string;
        /** The module matcher to identify the module and file to instrument */
        module: ModuleMatcher;
        /** The function query to identify the function to instrument */
        functionQuery: FunctionQuery;
        /**
         * A raw esquery selector that chooses the node(s) to instrument. When
         * set, it takes precedence over `functionQuery`'s matching fields.
         */
        astQuery?: string;
        /**
         * The name of a custom transform registered via `addTransform`.
         * When set, takes precedence over `functionQuery.kind`.
         */
        transform?: string;
    }
    | {
        channelName: string;
        module: ModuleMatcher;
        /**
         * A raw esquery selector that chooses the node(s) to instrument. This is
         * the escape hatch for shapes the name-based `functionQuery` can't
         * express, e.g. an anonymous arrow returned by a factory function.
         */
        astQuery: string;
        /** Behaviour options for the matched node(s); matching fields are ignored. */
        functionQuery?: FunctionBehavior;
        transform?: string;
    };

/**
 * Describes the module and file path you would like to match
 */
export interface ModuleMatcher {
    /**
     * The name of the module you want to match
     */
    name: string;
    /**
     * The semver range that you want to match
     */
    versionRange: string;
    /**
     * The path of the file you want to match from the module root
     */
    filePath: string | RegExp;
}

/**
 * The type of module being passed - ESM, CJS or unknown
 */
export type ModuleType = "esm" | "cjs" | "unknown";

/**
 * The InstrumentationMatcher is responsible for matching specific modules
 */
export class InstrumentationMatcher {
  private constructor();
  free(): void;
  /**
   * Get a transformer for the given module name, version and file path.
   * Returns `undefined` if no matching instrumentations are found.
   */
  getTransformer(moduleName: string, version: string, filePath: string): Transformer | undefined;
  /**
   * Register a custom transform function under the given name.
   * The name can then be referenced via the `transform` option in an `InstrumentationConfig`.
   */
  addTransform(name: string, fn: CustomTransform): void;
}
/**
 * The Transformer is responsible for transforming JavaScript code.
 */
export class Transformer {
  private constructor();
  free(): void;

  /**
   * The name of the module to transform.
   */
  get moduleName(): string;

  /**
   * The relative file path within the npm package being instrumented.
   *
   * @returns {string}
   */
  get filePath(): string;

  /**
   * Transform JavaScript code and optionally sourcemap.
   *
   * # Errors
   * Returns an error if the transformation fails to find injection points.
   */
  transform(code: string | Buffer, moduleType: ModuleType, sourcemap?: string | object | null): TransformOutput;
}
