import { GeneralItem, Incrementable, SearchBody } from 'lemon-model';
import elasticsearch from '@elastic/elasticsearch';
import $hangul from './hangul-service';
export { elasticsearch, $hangul };
export declare type SearchType = 'query_then_fetch' | 'dfs_query_then_fetch';
export interface SearchResponse<T = any> {
    total: number;
    list: Array<T>;
    last: Array<T>;
    aggregations: T;
}
/**
 * options for construction.
 */
export interface ElasticOption {
    /**
     * endpoint url of ES6
     */
    endpoint: string;
    /**
     * index-name
     */
    indexName: string;
    /**
     * document type (default as `_doc` in ES6)
     * - it must be `_doc` since ES6.x
     */
    docType?: string;
    /**
     * id-name (optional if time-seriese)
     */
    idName?: string;
    /**
     * is TIMESERIES data?
     */
    timeSeries?: boolean;
    /**
     * (optional) version of engine.
     * - (default) 6.8
     */
    version?: string;
    /**
     * fields to provide autocomplete(Search-as-You-Type) feature
     */
    autocompleteFields?: string[] | null;
}
/**
 * common type of item
 */
export interface ElasticItem {
    _id?: string;
    _version?: number;
    _score?: number;
    /**
     * only has simple string or number (and in arrays)
     */
    [key: string]: string | string[] | number | number[] | undefined;
}
/**
 * options for retrying searchAll
 */
export interface RetryOptions {
    /** do retry? (default true) */
    do?: boolean;
    /** retry after t msec (default 5000ms) */
    t?: number;
    /** maximum Retries (default 3 times) */
    maxRetries?: number;
}
/**
 * parameters for searchAll
 */
interface ElasticSearchAllParams {
    /** search-type */
    searchType?: SearchType;
    /** limit (default -1) */
    limit?: number;
    /** options for retrying (default true)*/
    retryOptions?: RetryOptions;
}
/**
 * type of search-engine type
 */
export declare type EngineType = 'os' | 'es';
/**
 * parsed version with major and minor version numbers.
 */
export interface ParsedVersion {
    /** search-engine type */
    engine?: EngineType;
    /** major version */
    major: number;
    /** minor version */
    minor: number;
    /** patch version */
    patch: number;
    /** pre-release label (e.g., 'alpha', 'beta') */
    prerelease?: string;
    /** build metadata */
    build?: string;
}
/** ****************************************************************************************************************
 *  Elastic Index Service
 ** ****************************************************************************************************************/
/**
 * abstarct class: `ElasticIndexService`
 * - abstract class for basic Elasticsearch CRUD operations
 * - common operations that are shared across different versions.
 * TODO - support `Elastic` and `OpenSearch`
 */
export declare abstract class ElasticIndexService<T extends ElasticItem = any> {
    protected _options: ElasticOption;
    readonly _client: elasticsearch.Client;
    /**
     * simple instance maker.
     *
     * ```js
     * const { client } = ElasticIndexService.instance(endpoint);
     * ```
     *
     * @param endpoint  service-url
     * @see https://www.elastic.co/guide/en/elasticsearch/client/javascript-api/16.x/configuration.html
     */
    static instance(endpoint: string): {
        client: elasticsearch.Client;
    };
    /**
     * default constuctor w/ options.
     * @param options { endpoint, indexName } is required.
     */
    constructor(options: ElasticOption);
    /**
     * get the client instance.
     */
    get client(): elasticsearch.Client;
    /**
     * get the current options.
     */
    get options(): ElasticOption;
    /**
     * get the version from options
     */
    get version(): number;
    /**
     * say hello
     */
    abstract hello(): string;
    /**
     * save an item
     * @param id - item id
     * @param item - item to save
     * @param type - document type
     */
    abstract saveItem(id: string, item: T, type?: string): Promise<T>;
    /**
     * push item for time-series data
     * @param item - item to push
     * @param type - document type
     */
    abstract pushItem(item: T, type?: string): Promise<T>;
    /**
     * read item with projections
     * @param id - item id
     * @param views - projections
     */
    abstract readItem(id: string, views?: string[] | object): Promise<T>;
    /**
     * delete an item by id
     * @param id - item id
     */
    abstract deleteItem(id: string): Promise<T>;
    /**
     * update an item
     * @param id - item id
     * @param item - item to update
     * @param increments - fields to increment
     */
    abstract updateItem(id: string, item: T | null, increments?: any, options?: {
        maxRetries?: number;
    }): Promise<T>;
    /**
     * search raw results using a query body
     * @param body - search query
     * @param searchType - type of search
     */
    abstract searchRaw<T extends object = any>(body: any, searchType?: string): Promise<T>;
    /**
     * search and return formatted response
     * @param body - search query
     * @param searchType - type of search
     */
    abstract search(body: any, searchType?: string): Promise<any>;
}
/** ****************************************************************************************************************
 *  Elastic6Service
 ** ****************************************************************************************************************/
export interface Elastic6Option extends ElasticOption {
}
export interface Elastic6Item extends ElasticItem {
}
/**
 * class: `Elastic6Service`
 * - extends `ElasticIndexService` and adds version-specific implementation
 */
export declare class Elastic6Service<T extends ElasticItem = any> extends ElasticIndexService {
    static readonly DECOMPOSED_FIELD = "_decomposed";
    static readonly QWERTY_FIELD = "_qwerty";
    /**
     * default constuctor w/ options.
     * @param options { endpoint, indexName } is required.
     */
    constructor(options: Elastic6Option);
    /**
     * say hello of identity.
     */
    hello: () => string;
    /**
     * get isOldES6
     * - used when setting doctype
     * - used when verifying mismatched error and results of search
     */
    get isOldES6(): boolean;
    /**
     * get isOldES71
     * - used when verifying mismatched error
     */
    get isOldES71(): boolean;
    /**
     * get isLatestOS2
     * - used when verifying results of search
     */
    get isLatestOS2(): boolean;
    /**
     * get the parsedVersion
     */
    get parsedVersion(): ParsedVersion;
    /**
     * get the root version from client
     *
     * @protected only for internal test.
     */
    protected getVersion(options?: {
        dump?: boolean;
    }): Promise<ParsedVersion>;
    /**
     * check whether the service version matches the version provided in the options.
     *
     * @protected only for internal test.
     */
    protected executeSelfTest(): Promise<{
        isEqual: boolean;
        optionVersion: ParsedVersion;
        rootVersion: ParsedVersion;
    }>;
    /**
     * parse version according to Semantic Versioning (SemVer) rules.
     *
     * @param version The version string to parse (e.g., "1.2.3", "1.2.3-alpha.1", "1.2.3+build.001").
     * @param options Optional configuration for throwable behavior.
     * @returns A ParsedVersion object or null if parsing fails and throwable is false.
     */
    parseVersion(version: string, options?: {
        throwable?: boolean;
    }): ParsedVersion;
    /**
     * save info to a JSON file.
     * @param info - The information to be saved
     * @param filePath - The file path where should be saved.
     */
    private saveInfoToFile;
    /**
     * list of index
     */
    listIndices(): Promise<{
        list: {
            pri: number;
            rep: number;
            docsCount: number;
            docsDeleted: number;
            health: string;
            index: string;
            status: string;
            uuid: string;
            priStoreSize: string;
            storeSize: string;
        }[];
    }>;
    /**
     * get mapping of an index
     * @param indexName - name of the index
     */
    getIndexMapping(): Promise<any>;
    /**
     * find the index by name
     * @param indexName - name of the index
     */
    findIndex(indexName?: string): Promise<{
        pri: number;
        rep: number;
        docsCount: number;
        docsDeleted: number;
        health: string;
        index: string;
        status: string;
        uuid: string;
        priStoreSize: string;
        storeSize: string;
    }>;
    /**
     * create index by name
     * @param settings - creating settings
     */
    createIndex(settings?: any): Promise<{
        status: any;
        index: string;
        acknowledged: any;
    }>;
    /**
     * destroy search index
     */
    destroyIndex(): Promise<{
        status: any;
        index: string;
        acknowledged: any;
    }>;
    /**
     * refresh search index - refresh index to make all items searchable
     */
    refreshIndex(): Promise<any>;
    /**
     * flush search index - force store changes into search index immediately
     */
    flushIndex(): Promise<any>;
    /**
     * describe `settings` and `mappings` of index.
     */
    describe(): Promise<{
        settings: any;
        mappings: any;
    }>;
    /**
     * save single item
     *
     * @param id - id
     * @param item - item to save
     * @param type - document type (default: doc-type given at construction time)
     */
    saveItem(id: string, item: T, type?: string): Promise<T>;
    /**
     * push item for time-series data.
     *
     * @param item - item to push
     * @param type - document type (default: doc-type given at construction time)
     */
    pushItem(item: T, type?: string): Promise<T>;
    /**
     * read item with projections
     *
     * @param id - item-id
     * @param views - projections
     */
    readItem(id: string, views?: string[] | object): Promise<T>;
    /**
     * delete item with projections
     *
     * @param id - item-id
     */
    deleteItem(id: string): Promise<T>;
    /**
     * update item (throw if not exist)
     * `update table set a=1, b=b+2 where id='a1'`
     * 0. no of `a1` -> 1,2 (created)
     * 1. a,b := 10,20 -> 11,22
     * 2. a,b := 10,null -> 11,2 (upsert)
     * 3. a,b := null,20 -> 1,22
     *
     * @param id - item-id
     * @param item - item to update
     * @param increments - item to increase
     * @param options - (optional) request option of client.
     */
    updateItem(id: string, item: T | null, increments?: Incrementable, options?: {
        maxRetries?: number;
    }): Promise<T>;
    /**
     * run search and get the raw response.
     * @param body - Elasticsearch Query DSL that defines the search request (e.g., size, query, filters).
     * @param searchType - type of search (e.g., 'query_then_fetch', 'dfs_query_then_fetch').
     */
    searchRaw<T extends object = any>(body: SearchBody, searchType?: SearchType): Promise<T>;
    /**
     * run search, and get the formatmted response.
     * @param body - Elasticsearch Query DSL that defines the search request (e.g., size, query, filters).
     * @param searchType - type of search (e.g., 'query_then_fetch', 'dfs_query_then_fetch').
     *
     */
    search(body: SearchBody, searchType?: SearchType): Promise<SearchResponse>;
    /**
     * search all until limit (-1 means no-limit)
     * @param body - Elasticsearch Query DSL that defines the search request (e.g., size, query, filters).
     * @param params - parameters including search type, limit, and retry options.
     */
    searchAll<T>(body: SearchBody, params?: ElasticSearchAllParams): Promise<T[]>;
    /**
     * create async generator that yields items queried until last
     *
     * @param body - Elasticsearch Query DSL that defines the search request (e.g., size, query, filters).
     * @param params - parameters including search type, limit, and retry options.
     */
    generateSearchResult(body: SearchBody, params?: ElasticSearchAllParams): AsyncGenerator<any[], void, unknown>;
    /**
     * prepare default setting
     * - migrated from engine-v2.
     *
     * @param docType       document type name
     * @param idName        id-name
     * @param shards        number of shards (default 4)
     * @param replicas      number of replicas (default 1)
     * @param timeSeries    flag of TIMESERIES (default false)
     */
    static prepareSettings(params: {
        docType: string;
        idName: string;
        version?: string;
        timeSeries?: boolean;
        shards?: number;
        replicas?: number;
    }): any;
    /**
     * generate autocomplete fields into the item body to be indexed
     * @param body  item body to be saved into ES6 index
     * @private
     */
    protected popullateAutocompleteFields<T = any>(body: T): T;
}
interface ErrorReasonDetail<T = any> {
    status: number;
    type: string;
    reason?: string;
    cause?: T;
}
interface ErrorReason {
    status: number;
    message: string;
    reason: ErrorReasonDetail;
}
/**
 * error samples
 */
export declare const $ERROR: {
    asJson: (e: any) => any;
    throwAsJson: (e: any) => never;
    parseMeta: <T extends {
        [key: string]: any;
        type?: string;
        value?: any;
        error?: string;
        list?: any[];
    }>(meta: any) => T;
    asError: (e: any) => ErrorReason;
    handler: (name: string, cb?: (e: Error, E?: ErrorReason) => any) => (e: any) => any;
};
/** ****************************************************************************************************************
 *  Dummy Elastic6 Service
 ** ****************************************************************************************************************/
/**
 * class: `DummyElastic6Service`
 * - service in-memory dummy data
 */
export declare class DummyElastic6Service<T extends GeneralItem> extends Elastic6Service<T> {
    constructor(dataFile: string, options: ElasticOption);
    private buffer;
    load(data: T[]): void;
    /**
     * say hello()
     */
    hello: () => string;
    readItem(id: string): Promise<T>;
    saveItem(id: string, item: T): Promise<T>;
    deleteItem(id: string, sort?: string | number): Promise<T>;
    updateItem(id: string, updates: T, increments?: Incrementable): Promise<T>;
}
