UNPKG

barikoiapis

Version:

Official TypeScript/JavaScript SDK for Barikoi Location Services

2,105 lines 71.4 kB
import * as z from 'zod';
import { z as z$1 } from 'zod';

// This file is auto-generated by @hey-api/openapi-ts
const serializeUrlSearchParamsPair = (data, key, value) => {
    if (typeof value === 'string') {
        data.append(key, value);
    }
    else {
        data.append(key, JSON.stringify(value));
    }
};
const jsonBodySerializer = {
    bodySerializer: (body) => JSON.stringify(body, (_key, value) => (typeof value === 'bigint' ? value.toString() : value)),
};
const urlSearchParamsBodySerializer = {
    bodySerializer: (body) => {
        const data = new URLSearchParams();
        Object.entries(body).forEach(([key, value]) => {
            if (value === undefined || value === null) {
                return;
            }
            if (Array.isArray(value)) {
                value.forEach(v => serializeUrlSearchParamsPair(data, key, v));
            }
            else {
                serializeUrlSearchParamsPair(data, key, value);
            }
        });
        return data.toString();
    },
};

// This file is auto-generated by @hey-api/openapi-ts
function createSseClient({ onRequest, onSseError, onSseEvent, responseTransformer, responseValidator, sseDefaultRetryDelay, sseMaxRetryAttempts, sseMaxRetryDelay, sseSleepFn, url, ...options }) {
    let lastEventId;
    const sleep = sseSleepFn ?? ((ms) => new Promise(resolve => setTimeout(resolve, ms)));
    const createStream = async function* () {
        let retryDelay = sseDefaultRetryDelay ?? 3000;
        let attempt = 0;
        const signal = options.signal ?? new AbortController().signal;
        while (true) {
            if (signal.aborted)
                break;
            attempt++;
            const headers = options.headers instanceof Headers
                ? options.headers
                : new Headers(options.headers);
            if (lastEventId !== undefined) {
                headers.set('Last-Event-ID', lastEventId);
            }
            try {
                const requestInit = {
                    redirect: 'follow',
                    ...options,
                    body: options.serializedBody,
                    headers,
                    signal,
                };
                let request = new Request(url, requestInit);
                if (onRequest) {
                    request = await onRequest(url, requestInit);
                }
                // fetch must be assigned here, otherwise it would throw the error:
                // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
                const _fetch = options.fetch ?? globalThis.fetch;
                const response = await _fetch(request);
                if (!response.ok)
                    throw new Error(`SSE failed: ${response.status} ${response.statusText}`);
                if (!response.body)
                    throw new Error('No body in SSE response');
                const reader = response.body.pipeThrough(new TextDecoderStream()).getReader();
                let buffer = '';
                const abortHandler = () => {
                    try {
                        reader.cancel();
                    }
                    catch {
                        // noop
                    }
                };
                signal.addEventListener('abort', abortHandler);
                try {
                    while (true) {
                        const { done, value } = await reader.read();
                        if (done)
                            break;
                        buffer += value;
                        buffer = buffer.replace(/\r\n?/g, '\n'); // normalize line endings
                        const chunks = buffer.split('\n\n');
                        buffer = chunks.pop() ?? '';
                        for (const chunk of chunks) {
                            const lines = chunk.split('\n');
                            const dataLines = [];
                            let eventName;
                            for (const line of lines) {
                                if (line.startsWith('data:')) {
                                    dataLines.push(line.replace(/^data:\s*/, ''));
                                }
                                else if (line.startsWith('event:')) {
                                    eventName = line.replace(/^event:\s*/, '');
                                }
                                else if (line.startsWith('id:')) {
                                    lastEventId = line.replace(/^id:\s*/, '');
                                }
                                else if (line.startsWith('retry:')) {
                                    const parsed = Number.parseInt(line.replace(/^retry:\s*/, ''), 10);
                                    if (!Number.isNaN(parsed)) {
                                        retryDelay = parsed;
                                    }
                                }
                            }
                            let data;
                            let parsedJson = false;
                            if (dataLines.length) {
                                const rawData = dataLines.join('\n');
                                try {
                                    data = JSON.parse(rawData);
                                    parsedJson = true;
                                }
                                catch {
                                    data = rawData;
                                }
                            }
                            if (parsedJson) {
                                if (responseValidator) {
                                    await responseValidator(data);
                                }
                                if (responseTransformer) {
                                    data = await responseTransformer(data);
                                }
                            }
                            onSseEvent?.({
                                data,
                                event: eventName,
                                id: lastEventId,
                                retry: retryDelay,
                            });
                            if (dataLines.length) {
                                yield data;
                            }
                        }
                    }
                }
                finally {
                    signal.removeEventListener('abort', abortHandler);
                    reader.releaseLock();
                }
                break; // exit loop on normal completion
            }
            catch (error) {
                // connection failed or aborted; retry after delay
                onSseError?.(error);
                if (sseMaxRetryAttempts !== undefined && attempt >= sseMaxRetryAttempts) {
                    break; // stop after firing error
                }
                // exponential backoff: double retry each attempt, cap at 30s
                const backoff = Math.min(retryDelay * 2 ** (attempt - 1), sseMaxRetryDelay ?? 30000);
                await sleep(backoff);
            }
        }
    };
    const stream = createStream();
    return { stream };
}

// This file is auto-generated by @hey-api/openapi-ts
const separatorArrayExplode = (style) => {
    switch (style) {
        case 'label':
            return '.';
        case 'matrix':
            return ';';
        case 'simple':
            return ',';
        default:
            return '&';
    }
};
const separatorArrayNoExplode = (style) => {
    switch (style) {
        case 'form':
            return ',';
        case 'pipeDelimited':
            return '|';
        case 'spaceDelimited':
            return '%20';
        default:
            return ',';
    }
};
const separatorObjectExplode = (style) => {
    switch (style) {
        case 'label':
            return '.';
        case 'matrix':
            return ';';
        case 'simple':
            return ',';
        default:
            return '&';
    }
};
const serializeArrayParam = ({ allowReserved, explode, name, style, value, }) => {
    if (!explode) {
        const joinedValues = (allowReserved ? value : value.map(v => encodeURIComponent(v))).join(separatorArrayNoExplode(style));
        switch (style) {
            case 'label':
                return `.${joinedValues}`;
            case 'matrix':
                return `;${name}=${joinedValues}`;
            case 'simple':
                return joinedValues;
            default:
                return `${name}=${joinedValues}`;
        }
    }
    const separator = separatorArrayExplode(style);
    const joinedValues = value
        .map(v => {
        if (style === 'label' || style === 'simple') {
            return allowReserved ? v : encodeURIComponent(v);
        }
        return serializePrimitiveParam({
            allowReserved,
            name,
            value: v,
        });
    })
        .join(separator);
    return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
};
const serializePrimitiveParam = ({ allowReserved, name, value, }) => {
    if (value === undefined || value === null) {
        return '';
    }
    if (typeof value === 'object') {
        throw new Error('Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.');
    }
    return `${name}=${allowReserved ? value : encodeURIComponent(value)}`;
};
const serializeObjectParam = ({ allowReserved, explode, name, style, value, valueOnly, }) => {
    if (value instanceof Date) {
        return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`;
    }
    if (style !== 'deepObject' && !explode) {
        let values = [];
        Object.entries(value).forEach(([key, v]) => {
            values = [...values, key, allowReserved ? v : encodeURIComponent(v)];
        });
        const joinedValues = values.join(',');
        switch (style) {
            case 'form':
                return `${name}=${joinedValues}`;
            case 'label':
                return `.${joinedValues}`;
            case 'matrix':
                return `;${name}=${joinedValues}`;
            default:
                return joinedValues;
        }
    }
    const separator = separatorObjectExplode(style);
    const joinedValues = Object.entries(value)
        .map(([key, v]) => serializePrimitiveParam({
        allowReserved,
        name: style === 'deepObject' ? `${name}[${key}]` : key,
        value: v,
    }))
        .join(separator);
    return style === 'label' || style === 'matrix' ? separator + joinedValues : joinedValues;
};

// This file is auto-generated by @hey-api/openapi-ts
const PATH_PARAM_RE = /\{[^{}]+\}/g;
const defaultPathSerializer = ({ path, url: _url }) => {
    let url = _url;
    const matches = _url.match(PATH_PARAM_RE);
    if (matches) {
        for (const match of matches) {
            let explode = false;
            let name = match.substring(1, match.length - 1);
            let style = 'simple';
            if (name.endsWith('*')) {
                explode = true;
                name = name.substring(0, name.length - 1);
            }
            if (name.startsWith('.')) {
                name = name.substring(1);
                style = 'label';
            }
            else if (name.startsWith(';')) {
                name = name.substring(1);
                style = 'matrix';
            }
            const value = path[name];
            if (value === undefined || value === null) {
                continue;
            }
            if (Array.isArray(value)) {
                url = url.replace(match, serializeArrayParam({ explode, name, style, value }));
                continue;
            }
            if (typeof value === 'object') {
                url = url.replace(match, serializeObjectParam({
                    explode,
                    name,
                    style,
                    value: value,
                    valueOnly: true,
                }));
                continue;
            }
            if (style === 'matrix') {
                url = url.replace(match, `;${serializePrimitiveParam({
                    name,
                    value: value,
                })}`);
                continue;
            }
            const replaceValue = encodeURIComponent(style === 'label' ? `.${value}` : value);
            url = url.replace(match, replaceValue);
        }
    }
    return url;
};
const getUrl = ({ baseUrl, path, query, querySerializer, url: _url, }) => {
    const pathUrl = _url.startsWith('/') ? _url : `/${_url}`;
    let url = (baseUrl ?? '') + pathUrl;
    if (path) {
        url = defaultPathSerializer({ path, url });
    }
    let search = query ? querySerializer(query) : '';
    if (search.startsWith('?')) {
        search = search.substring(1);
    }
    if (search) {
        url += `?${search}`;
    }
    return url;
};
function getValidRequestBody(options) {
    const hasBody = options.body !== undefined;
    const isSerializedBody = hasBody && options.bodySerializer;
    if (isSerializedBody) {
        if ('serializedBody' in options) {
            const hasSerializedBody = options.serializedBody !== undefined && options.serializedBody !== '';
            return hasSerializedBody ? options.serializedBody : null;
        }
        // not all clients implement a serializedBody property (i.e., client-axios)
        return options.body !== '' ? options.body : null;
    }
    // plain/text body
    if (hasBody) {
        return options.body;
    }
    // no body was provided
    return undefined;
}

// This file is auto-generated by @hey-api/openapi-ts
const getAuthToken = async (auth, callback) => {
    const token = typeof callback === 'function' ? await callback(auth) : callback;
    if (!token) {
        return;
    }
    if (auth.scheme === 'bearer') {
        return `Bearer ${token}`;
    }
    if (auth.scheme === 'basic') {
        return `Basic ${btoa(token)}`;
    }
    return token;
};

// This file is auto-generated by @hey-api/openapi-ts
const createQuerySerializer = ({ parameters = {}, ...args } = {}) => {
    const querySerializer = (queryParams) => {
        const search = [];
        if (queryParams && typeof queryParams === 'object') {
            for (const name in queryParams) {
                const value = queryParams[name];
                if (value === undefined || value === null) {
                    continue;
                }
                const options = parameters[name] || args;
                if (Array.isArray(value)) {
                    const serializedArray = serializeArrayParam({
                        allowReserved: options.allowReserved,
                        explode: true,
                        name,
                        style: 'form',
                        value,
                        ...options.array,
                    });
                    if (serializedArray)
                        search.push(serializedArray);
                }
                else if (typeof value === 'object') {
                    const serializedObject = serializeObjectParam({
                        allowReserved: options.allowReserved,
                        explode: true,
                        name,
                        style: 'deepObject',
                        value: value,
                        ...options.object,
                    });
                    if (serializedObject)
                        search.push(serializedObject);
                }
                else {
                    const serializedPrimitive = serializePrimitiveParam({
                        allowReserved: options.allowReserved,
                        name,
                        value: value,
                    });
                    if (serializedPrimitive)
                        search.push(serializedPrimitive);
                }
            }
        }
        return search.join('&');
    };
    return querySerializer;
};
/**
 * Infers parseAs value from provided Content-Type header.
 */
const getParseAs = (contentType) => {
    if (!contentType) {
        // If no Content-Type header is provided, the best we can do is return the raw response body,
        // which is effectively the same as the 'stream' option.
        return 'stream';
    }
    const cleanContent = contentType.split(';')[0]?.trim();
    if (!cleanContent) {
        return;
    }
    if (cleanContent.startsWith('application/json') || cleanContent.endsWith('+json')) {
        return 'json';
    }
    if (cleanContent === 'multipart/form-data') {
        return 'formData';
    }
    if (['application/', 'audio/', 'image/', 'video/'].some(type => cleanContent.startsWith(type))) {
        return 'blob';
    }
    if (cleanContent.startsWith('text/')) {
        return 'text';
    }
    return;
};
const checkForExistence = (options, name) => {
    if (!name) {
        return false;
    }
    if (options.headers.has(name) ||
        options.query?.[name] ||
        options.headers.get('Cookie')?.includes(`${name}=`)) {
        return true;
    }
    return false;
};
async function setAuthParams(options) {
    for (const auth of options.security ?? []) {
        if (checkForExistence(options, auth.name)) {
            continue;
        }
        const token = await getAuthToken(auth, options.auth);
        if (!token) {
            continue;
        }
        const name = auth.name ?? 'Authorization';
        switch (auth.in) {
            case 'query':
                if (!options.query) {
                    options.query = {};
                }
                options.query[name] = token;
                break;
            case 'cookie':
                options.headers.append('Cookie', `${name}=${token}`);
                break;
            case 'header':
            default:
                options.headers.set(name, token);
                break;
        }
    }
}
const buildUrl = options => getUrl({
    baseUrl: options.baseUrl,
    path: options.path,
    query: options.query,
    querySerializer: typeof options.querySerializer === 'function'
        ? options.querySerializer
        : createQuerySerializer(options.querySerializer),
    url: options.url,
});
const mergeConfigs = (a, b) => {
    const config = { ...a, ...b };
    if (config.baseUrl?.endsWith('/')) {
        config.baseUrl = config.baseUrl.substring(0, config.baseUrl.length - 1);
    }
    config.headers = mergeHeaders(a.headers, b.headers);
    return config;
};
const headersEntries = (headers) => {
    const entries = [];
    headers.forEach((value, key) => {
        entries.push([key, value]);
    });
    return entries;
};
const mergeHeaders = (...headers) => {
    const mergedHeaders = new Headers();
    for (const header of headers) {
        if (!header) {
            continue;
        }
        const iterator = header instanceof Headers ? headersEntries(header) : Object.entries(header);
        for (const [key, value] of iterator) {
            if (value === null) {
                mergedHeaders.delete(key);
            }
            else if (Array.isArray(value)) {
                for (const v of value) {
                    mergedHeaders.append(key, v);
                }
            }
            else if (value !== undefined) {
                // assume object headers are meant to be JSON stringified, i.e., their
                // content value in OpenAPI specification is 'application/json'
                mergedHeaders.set(key, typeof value === 'object' ? JSON.stringify(value) : value);
            }
        }
    }
    return mergedHeaders;
};
class Interceptors {
    constructor() {
        this.fns = [];
    }
    clear() {
        this.fns = [];
    }
    eject(id) {
        const index = this.getInterceptorIndex(id);
        if (this.fns[index]) {
            this.fns[index] = null;
        }
    }
    exists(id) {
        const index = this.getInterceptorIndex(id);
        return Boolean(this.fns[index]);
    }
    getInterceptorIndex(id) {
        if (typeof id === 'number') {
            return this.fns[id] ? id : -1;
        }
        return this.fns.indexOf(id);
    }
    update(id, fn) {
        const index = this.getInterceptorIndex(id);
        if (this.fns[index]) {
            this.fns[index] = fn;
            return id;
        }
        return false;
    }
    use(fn) {
        this.fns.push(fn);
        return this.fns.length - 1;
    }
}
const createInterceptors = () => ({
    error: new Interceptors(),
    request: new Interceptors(),
    response: new Interceptors(),
});
const defaultQuerySerializer = createQuerySerializer({
    allowReserved: false,
    array: {
        explode: true,
        style: 'form',
    },
    object: {
        explode: true,
        style: 'deepObject',
    },
});
const defaultHeaders = {
    'Content-Type': 'application/json',
};
const createConfig = (override = {}) => ({
    ...jsonBodySerializer,
    headers: defaultHeaders,
    parseAs: 'auto',
    querySerializer: defaultQuerySerializer,
    ...override,
});

// This file is auto-generated by @hey-api/openapi-ts
const createClient = (config = {}) => {
    let _config = mergeConfigs(createConfig(), config);
    const getConfig = () => ({ ..._config });
    const setConfig = (config) => {
        _config = mergeConfigs(_config, config);
        return getConfig();
    };
    const interceptors = createInterceptors();
    const beforeRequest = async (options) => {
        const opts = {
            ..._config,
            ...options,
            fetch: options.fetch ?? _config.fetch ?? globalThis.fetch,
            headers: mergeHeaders(_config.headers, options.headers),
            serializedBody: undefined,
        };
        if (opts.security) {
            await setAuthParams(opts);
        }
        if (opts.requestValidator) {
            await opts.requestValidator(opts);
        }
        if (opts.body !== undefined && opts.bodySerializer) {
            opts.serializedBody = opts.bodySerializer(opts.body);
        }
        // remove Content-Type header if body is empty to avoid sending invalid requests
        if (opts.body === undefined || opts.serializedBody === '') {
            opts.headers.delete('Content-Type');
        }
        const resolvedOpts = opts;
        const url = buildUrl(resolvedOpts);
        return { opts: resolvedOpts, url };
    };
    const request = async (options) => {
        const throwOnError = options.throwOnError ?? _config.throwOnError;
        const responseStyle = options.responseStyle ?? _config.responseStyle;
        let request;
        let response;
        try {
            const { opts, url } = await beforeRequest(options);
            const requestInit = {
                redirect: 'follow',
                ...opts,
                body: getValidRequestBody(opts),
            };
            request = new Request(url, requestInit);
            for (const fn of interceptors.request.fns) {
                if (fn) {
                    request = await fn(request, opts);
                }
            }
            // fetch must be assigned here, otherwise it would throw the error:
            // TypeError: Failed to execute 'fetch' on 'Window': Illegal invocation
            const _fetch = opts.fetch;
            response = await _fetch(request);
            for (const fn of interceptors.response.fns) {
                if (fn) {
                    response = await fn(response, request, opts);
                }
            }
            const result = {
                request,
                response,
            };
            if (response.ok) {
                const parseAs = (opts.parseAs === 'auto'
                    ? getParseAs(response.headers.get('Content-Type'))
                    : opts.parseAs) ?? 'json';
                if (response.status === 204 || response.headers.get('Content-Length') === '0') {
                    let emptyData;
                    switch (parseAs) {
                        case 'arrayBuffer':
                        case 'blob':
                        case 'text':
                            emptyData = await response[parseAs]();
                            break;
                        case 'formData':
                            emptyData = new FormData();
                            break;
                        case 'stream':
                            emptyData = response.body;
                            break;
                        case 'json':
                        default:
                            emptyData = {};
                            break;
                    }
                    return opts.responseStyle === 'data'
                        ? emptyData
                        : {
                            data: emptyData,
                            ...result,
                        };
                }
                let data;
                switch (parseAs) {
                    case 'arrayBuffer':
                    case 'blob':
                    case 'formData':
                    case 'text':
                        data = await response[parseAs]();
                        break;
                    case 'json': {
                        // Some servers return 200 with no Content-Length and empty body.
                        // response.json() would throw; read as text and parse if non-empty.
                        const text = await response.text();
                        data = text ? JSON.parse(text) : {};
                        break;
                    }
                    case 'stream':
                        return opts.responseStyle === 'data'
                            ? response.body
                            : {
                                data: response.body,
                                ...result,
                            };
                }
                if (parseAs === 'json') {
                    if (opts.responseValidator) {
                        await opts.responseValidator(data);
                    }
                    if (opts.responseTransformer) {
                        data = await opts.responseTransformer(data);
                    }
                }
                return opts.responseStyle === 'data'
                    ? data
                    : {
                        data,
                        ...result,
                    };
            }
            const textError = await response.text();
            let jsonError;
            try {
                jsonError = JSON.parse(textError);
            }
            catch {
                // noop
            }
            throw jsonError ?? textError;
        }
        catch (error) {
            let finalError = error;
            for (const fn of interceptors.error.fns) {
                if (fn) {
                    finalError = await fn(finalError, response, request, options);
                }
            }
            finalError = finalError || {};
            if (throwOnError) {
                throw finalError;
            }
            // TODO: we probably want to return error and improve types
            return responseStyle === 'data'
                ? undefined
                : {
                    error: finalError,
                    request,
                    response,
                };
        }
    };
    const makeMethodFn = (method) => (options) => request({ ...options, method });
    const makeSseFn = (method) => async (options) => {
        const { opts, url } = await beforeRequest(options);
        return createSseClient({
            ...opts,
            body: opts.body,
            method,
            onRequest: async (url, init) => {
                let request = new Request(url, init);
                for (const fn of interceptors.request.fns) {
                    if (fn) {
                        request = await fn(request, opts);
                    }
                }
                return request;
            },
            serializedBody: getValidRequestBody(opts),
            url,
        });
    };
    const _buildUrl = options => buildUrl({ ..._config, ...options });
    return {
        buildUrl: _buildUrl,
        connect: makeMethodFn('CONNECT'),
        delete: makeMethodFn('DELETE'),
        get: makeMethodFn('GET'),
        getConfig,
        head: makeMethodFn('HEAD'),
        interceptors,
        options: makeMethodFn('OPTIONS'),
        patch: makeMethodFn('PATCH'),
        post: makeMethodFn('POST'),
        put: makeMethodFn('PUT'),
        request,
        setConfig,
        sse: {
            connect: makeSseFn('CONNECT'),
            delete: makeSseFn('DELETE'),
            get: makeSseFn('GET'),
            head: makeSseFn('HEAD'),
            options: makeSseFn('OPTIONS'),
            patch: makeSseFn('PATCH'),
            post: makeSseFn('POST'),
            put: makeSseFn('PUT'),
            trace: makeSseFn('TRACE'),
        },
        trace: makeMethodFn('TRACE'),
    };
};

// This file is auto-generated by @hey-api/openapi-ts
const client = createClient(createConfig({ baseUrl: 'https://barikoi.xyz' }));

// This file is auto-generated by @hey-api/openapi-ts
z.object({
    place: z
        .object({
        id: z.union([z.string(), z.int()]).optional(),
        distance_within_meters: z.number().optional(),
        address: z.string().optional(),
        area: z.string().optional(),
        city: z.string().optional(),
        postCode: z.string().optional(),
        address_bn: z.string().optional(),
        area_bn: z.string().optional(),
        city_bn: z.string().optional(),
        country: z.string().optional(),
        division: z.string().optional(),
        district: z.string().optional(),
        sub_district: z.string().optional(),
        pauroshova: z.string().nullish(),
        union: z.string().nullish(),
        location_type: z.string().optional(),
        address_components: z
            .object({
            place_name: z.string().nullish(),
            house: z.string().nullish(),
            road: z.string().nullish(),
        })
            .nullish(),
        area_components: z
            .object({
            area: z.string().nullish(),
            sub_area: z.string().nullish(),
        })
            .nullish(),
        thana: z.string().optional(),
        thana_bn: z.string().optional(),
    })
        .optional(),
    status: z.int().optional(),
});
z.object({
    places: z
        .array(z.object({
        id: z.int().optional(),
        longitude: z.union([z.string(), z.number()]).optional(),
        latitude: z.union([z.string(), z.number()]).optional(),
        address: z.string().optional(),
        address_bn: z.string().optional(),
        city: z.string().optional(),
        city_bn: z.string().optional(),
        area: z.string().optional(),
        area_bn: z.string().optional(),
        postCode: z.union([z.string(), z.int()]).optional(),
        pType: z.string().optional(),
        uCode: z.string().optional(),
    }))
        .optional(),
    status: z.int().optional(),
});
z.object({
    given_address: z.string().optional(),
    fixed_address: z.string().optional(),
    bangla_address: z.string().optional(),
    address_status: z.enum(['complete', 'incomplete']).optional(),
    geocoded_address: z
        .object({
        id: z.union([z.string(), z.int()]).optional(),
        Address: z.string().optional(),
        address: z.string().optional(),
        address_bn: z.string().optional(),
        alternate_address: z.string().optional(),
        area: z.string().optional(),
        area_bn: z.string().optional(),
        bounds: z.string().nullish(),
        business_name: z.string().nullish(),
        city: z.string().optional(),
        city_bn: z.string().optional(),
        created_at: z.string().optional(),
        district: z.string().optional(),
        geo_location: z.array(z.number()).optional(),
        holding_number: z.string().nullish(),
        latitude: z.string().optional(),
        location: z.string().optional(),
        location_shape: z.string().optional(),
        longitude: z.string().optional(),
        match_freq: z.int().optional(),
        match_fuzzy: z.int().optional(),
        matching_diff: z.int().optional(),
        new_address: z.string().optional(),
        pType: z.string().optional(),
        place_code: z.string().optional(),
        place_name: z.string().nullish(),
        popularity_ranking: z.int().optional(),
        postCode: z.union([z.string(), z.int()]).optional(),
        postcode: z.union([z.string(), z.int()]).optional(),
        road_name_number: z.string().nullish(),
        score: z.number().optional(),
        subType: z.string().optional(),
        sub_area: z.string().nullish(),
        sub_district: z.string().optional(),
        sub_type: z.string().optional(),
        super_sub_area: z.string().nullish(),
        thana: z.string().optional(),
        type: z.string().optional(),
        uCode: z.string().optional(),
        union: z.union([z.string(), z.int()]).nullish(),
        unions: z.union([z.string(), z.int()]).nullish(),
        updated_at: z.string().optional(),
        user_id: z.int().optional(),
    })
        .optional(),
    confidence_score_percentage: z.int().optional(),
    status: z.int().optional(),
});
z.object({
    code: z.string().optional(),
    routes: z
        .array(z.object({
        geometry: z.union([z.string(), z.record(z.string(), z.unknown())]).optional(),
        legs: z
            .array(z.object({
            steps: z.array(z.record(z.string(), z.unknown())).optional(),
            distance: z
                .number()
                .register(z.globalRegistry, {
                description: 'Distance in meters',
            })
                .optional(),
            duration: z
                .number()
                .register(z.globalRegistry, {
                description: 'Duration in seconds',
            })
                .optional(),
            summary: z.string().optional(),
            weight: z.number().optional(),
        }))
            .optional(),
        distance: z.number().optional(),
        duration: z.number().optional(),
        weight_name: z.string().optional(),
        weight: z.number().optional(),
    }))
        .optional(),
    waypoints: z
        .array(z.object({
        hint: z.string().optional(),
        distance: z.number().optional(),
        name: z.string().nullish(),
        location: z.tuple([z.number(), z.number()]).optional(),
    }))
        .optional(),
});
z.object({
    places: z
        .array(z.object({
        address: z.string().optional(),
        place_code: z.string().optional(),
    }))
        .optional(),
    session_id: z.uuid().optional(),
    status: z.int().optional(),
});
z.object({
    place: z
        .object({
        address: z.string().optional(),
        place_code: z.string().optional(),
        latitude: z.string().optional(),
        longitude: z.string().optional(),
    })
        .optional(),
    session_id: z.uuid().optional(),
    status: z.int().optional(),
});
z.object({
    coordinates: z.tuple([z.number(), z.number()]).optional(),
    distance: z
        .number()
        .register(z.globalRegistry, {
        description: 'Distance in meters',
    })
        .optional(),
    type: z.enum(['Point']).optional(),
});
z.object({
    places: z
        .array(z.object({
        id: z.int().optional(),
        name: z.string().optional(),
        distance_in_meters: z.union([z.string(), z.number()]).optional(),
        longitude: z.string().optional(),
        latitude: z.string().optional(),
        pType: z.string().optional(),
        Address: z.string().optional(),
        area: z.string().optional(),
        city: z.string().optional(),
        postCode: z.string().optional(),
        subType: z.string().optional(),
        uCode: z.string().optional(),
    }))
        .optional(),
    status: z.int().optional(),
});
z.object({
    hints: z
        .object({
        'visited_nodes.sum': z.number().optional(),
        'visited_nodes.average': z.number().optional(),
    })
        .optional(),
    info: z
        .object({
        copyrights: z.array(z.string()).optional(),
        took: z.number().optional(),
    })
        .optional(),
    paths: z
        .array(z.object({
        distance: z
            .number()
            .register(z.globalRegistry, {
            description: 'Distance in meters',
        })
            .optional(),
        weight: z.number().optional(),
        time: z
            .int()
            .register(z.globalRegistry, {
            description: 'Time in milliseconds',
        })
            .optional(),
        transfers: z.int().optional(),
        points_encoded: z.boolean().optional(),
        bbox: z.tuple([z.number(), z.number(), z.number(), z.number()]).optional(),
        points: z
            .string()
            .register(z.globalRegistry, {
            description: 'Encoded polyline',
        })
            .optional(),
        instructions: z.array(z.record(z.string(), z.unknown())).optional(),
        legs: z.array(z.record(z.string(), z.unknown())).optional(),
        details: z
            .union([z.record(z.string(), z.unknown()), z.array(z.record(z.string(), z.unknown()))])
            .optional(),
        ascend: z.number().optional(),
        descend: z.number().optional(),
        snapped_waypoints: z.string().optional(),
    }))
        .optional(),
});
z.object({
    hints: z
        .object({
        'visited_nodes.sum': z.number().optional(),
        'visited_nodes.average': z.number().optional(),
    })
        .optional(),
    info: z
        .object({
        copyrights: z.array(z.string()).optional(),
        took: z.number().optional(),
        road_data_timestamp: z.string().optional(),
    })
        .optional(),
    paths: z
        .array(z.object({
        distance: z
            .number()
            .register(z.globalRegistry, {
            description: 'Distance in meters',
        })
            .optional(),
        weight: z.number().optional(),
        time: z
            .number()
            .register(z.globalRegistry, {
            description: 'Time in milliseconds',
        })
            .optional(),
        transfers: z.int().optional(),
        points_encoded: z.boolean().optional(),
        bbox: z.tuple([z.number(), z.number(), z.number(), z.number()]).optional(),
        points: z
            .object({
            type: z.enum(['LineString']).optional(),
            coordinates: z.array(z.tuple([z.number(), z.number()])).optional(),
        })
            .register(z.globalRegistry, {
            description: 'GeoJSON LineString with route coordinates',
        })
            .optional(),
        instructions: z
            .array(z.object({
            distance: z.number().optional(),
            heading: z.number().optional(),
            sign: z.int().optional(),
            interval: z.tuple([z.int(), z.int()]).optional(),
            text: z.string().optional(),
            time: z.number().optional(),
            street_name: z.string().optional(),
        }))
            .optional(),
        legs: z.array(z.record(z.string(), z.unknown())).optional(),
        details: z.array(z.record(z.string(), z.unknown())).optional(),
        ascend: z.number().optional(),
        descend: z.number().optional(),
        snapped_waypoints: z
            .object({
            type: z.enum(['LineString']).optional(),
            coordinates: z.array(z.tuple([z.number(), z.number()])).optional(),
        })
            .optional(),
    }))
        .optional(),
});
const zGeocodeBody = z.object({
    q: z.string().register(z.globalRegistry, {
        description: 'Address to geocode',
    }),
    thana: z.enum(['yes', 'no']).optional(),
    district: z.enum(['yes', 'no']).optional(),
    bangla: z.enum(['yes', 'no']).optional(),
});
const zCalculateRouteBody = z.object({
    data: z.object({
        start: z.object({
            latitude: z.number().gte(-90).lte(90),
            longitude: z.number().gte(-180).lte(180),
        }),
        destination: z.object({
            latitude: z.number().gte(-90).lte(90),
            longitude: z.number().gte(-180).lte(180),
        }),
    }),
});
z.object({
    api_key: z.string(),
    source: z.string().register(z.globalRegistry, {
        description: 'Format: latitude,longitude',
    }),
    destination: z.string().register(z.globalRegistry, {
        description: 'Format: latitude,longitude',
    }),
    profile: z.enum(['car', 'bike', 'foot', 'motorcycle']).optional().default('car'),
    geo_points: z
        .array(z.object({
        id: z.int(),
        point: z.string().register(z.globalRegistry, {
            description: 'Format: latitude,longitude',
        }),
    }))
        .min(1)
        .max(50),
});
z.object({
    message: z.string().optional(),
    status: z.int().optional(),
    data: z
        .object({
        id: z.string().optional(),
        name: z.string().optional(),
        radius: z.string().optional(),
        latitude: z.string().optional(),
        longitude: z.string().optional(),
        user_id: z.int().optional(),
    })
        .optional(),
});
z.object({
    message: z.string().optional(),
    status: z.int().optional(),
});
z.object({
    message: z.string().optional(),
    status: z.int().optional(),
});
z.object({
    message: z.string().optional(),
    status: z.int().optional(),
});
z.object({
    message: z.string().optional(),
    status: z.int().optional(),
});
z.string();
/**
 * Returned route geometry format. Expected values: polyline, polyline6, geojson
 */
z
    .enum(['polyline', 'polyline6', 'geojson'])
    .register(z.globalRegistry, {
    description: 'Returned route geometry format. Expected values: polyline, polyline6, geojson',
})
    .default('polyline');
/**
 * Place code from search results
 */
z.string().register(z.globalRegistry, {
    description: 'Place code from search results',
});
/**
 * Session ID from search-place endpoint
 */
z.uuid().register(z.globalRegistry, {
    description: 'Session ID from search-place endpoint',
});
/**
 * Format: latitude,longitude
 */
z.string().register(z.globalRegistry, {
    description: 'Format: latitude,longitude',
});
/**
 * Format: lon,lat;lon,lat
 */
z.string().register(z.globalRegistry, {
    description: 'Format: lon,lat;lon,lat',
});
/**
 * Search radius in kilometers
 */
z.number().gte(0.1).lte(100).register(z.globalRegistry, {
    description: 'Search radius in kilometers',
});
/**
 * Maximum number of results
 */
z.int().gte(1).lte(100).register(z.globalRegistry, {
    description: 'Maximum number of results',
});
/**
 * Route calculation type
 */
z.enum(['gh']).register(z.globalRegistry, {
    description: 'Route calculation type',
});
const zReverseGeocodeQuery = z.object({
    api_key: z.string(),
    longitude: z.number(),
    latitude: z.number(),
    country_code: z.string().optional(),
    country: z.boolean().optional(),
    district: z.boolean().optional(),
    post_code: z.boolean().optional(),
    sub_district: z.boolean().optional(),
    union: z.boolean().optional(),
    pauroshova: z.boolean().optional(),
    location_type: z.boolean().optional(),
    division: z.boolean().optional(),
    address: z.boolean().optional(),
    area: z.boolean().optional(),
    bangla: z.boolean().optional(),
    thana: z.boolean().optional(),
});
const zAutocompleteQuery = z.object({
    api_key: z.string(),
    q: z.string().min(1),
    bangla: z
        .boolean()
        .register(z.globalRegistry, {
        description: 'Return Bangla fields in the response.',
    })
        .optional()
        .default(true),
});
const zGeocodeBody2 = zGeocodeBody;
const zGeocodeQuery = z.object({
    api_key: z.string(),
});
const zRouteOverviewPath = z.object({
    coordinates: z.string().register(z.globalRegistry, {
        description: 'Format: lon,lat;lon,lat',
    }),
});
const zRouteOverviewQuery = z.object({
    api_key: z.string(),
    geometries: z
        .enum(['polyline', 'polyline6', 'geojson'])
        .register(z.globalRegistry, {
        description: 'Returned route geometry format. Expected values: polyline, polyline6, geojson',
    })
        .optional()
        .default('polyline'),
    profile: z.enum(['car', 'foot']).optional(),
});
const zCalculateRouteBody2 = zCalculateRouteBody;
const zCalculateRouteQuery = z.object({
    api_key: z.string(),
    type: z.enum(['gh']).register(z.globalRegistry, {
        description: 'Route calculation type',
    }),
    profile: z.enum(['car', 'bike', 'motorcycle']).optional(),
});
const zSearchPlaceQuery = z.object({
    api_key: z.string(),
    q: z.string().min(1),
});
const zPlaceDetailsQuery = z.object({
    api_key: z.string(),
    place_code: z.string().register(z.globalRegistry, {
        description: 'Place code from search results',
    }),
    session_id: z.uuid().register(z.globalRegistry, {
        description: 'Session ID from search-place endpoint',
    }),
});
const zSnapToRoadQuery = z.object({
    api_key: z.string(),
    point: z.string().register(z.globalRegistry, {
        description: 'Format: latitude,longitude',
    }),
});
const zNearbyPath = z.object({
    radius: z.number().gte(0.1).lte(100).register(z.globalRegistry, {
        description: 'Search radius in kilometers',
    }),
    limit: z.int().gte(1).lte(100).register(z.globalRegistry, {
        description: 'Maximum number of results',
    }),
});
const zNearbyQuery = z.object({
    api_key: z.string(),
    longitude: z.number(),
    latitude: z.number(),
});
const zCheckNearbyQuery = z.object({
    api_key: z.string(),
    destination_latitude: z.number(),
    destination_longitude: z.number(),
    radius: z.int().gte(10).lte(1000).register(z.globalRegistry, {
        description: 'Search radius in meters',
    }),
    current_latitude: z.number(),
    current_longitude: z.number(),
});

// This file is auto-generated by @hey-api/openapi-ts
/**
 * Reverse Geocoding
 *
 * This API endpoint performs reverse geocoding to convert geographical coordinates (longitude and latitude) into a human-readable address. It provides detailed location information including the address in both English and Bangla, along with other administrative details such as district, division, and more.
 *
 * **IMPORTANT:** ⚠️ Enabling **all** optional parameters will trigger multiple internal API calls, which will consume more of your API credits. To optimize performance and reduce credit usage, only request the parameters that are essential for your use case.
 */
const reverseGeocode = (options) => (options.client ?? client).get({
    requestValidator: async (data) => await z
        .object({
        body: z.never().optional(),
        path: z.never().optional(),
        query: zReverseGeocodeQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/v2/api/search/reverse/geocode',
    ...options,
});
/**
 * Autocomplete
 *
 * Barikoi Autocomplete API endpoint provides autocomplete suggestions for place names based on a query string. It returns a list of matching places with detailed information including addresses in both English and Bangla, as well as geographic coordinates. Barikoi Autocomplete API is useful for providing real-time, location-based search suggestions to users as they type, enhancing the user experience by quickly narrowing down potential matches based on partial input.
 */
const autocomplete = (options) => (options.client ?? client).get({
    requestValidator: async (data) => await z
        .object({
        body: z.never().optional(),
        path: z.never().optional(),
        query: zAutocompleteQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/v2/api/search/autocomplete/place',
    ...options,
});
/**
 * Geocode (Rupantor)
 *
 * Rupantor Geocoder API for Developers. It formats the given address and searches for the address and gives a status if the address is complete or not. Rupantor Geocoder only supports FormData. So use FormData object to send your data. Rupantor Geocoder needs Geocode API to function properly. One Rupantor Geocoder request requires two Geocode API requests.
 */
const geocode = (options) => (options.client ?? client).post({
    ...urlSearchParamsBodySerializer,
    requestValidator: async (data) => await z
        .object({
        body: zGeocodeBody2,
        path: z.never().optional(),
        query: zGeocodeQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/v2/api/search/rupantor/geocode',
    ...options,
    headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        ...options.headers,
    },
});
/**
 * Route Overview
 *
 * This API endpoint retrieves route information between two geographical points specified by their longitude and latitude coordinates. The response includes details such as the geometry of the route, distance, duration, and waypoints.
 */
const routeOverview = (options) => (options.client ?? client).get({
    requestValidator: async (data) => await z
        .object({
        body: z.never().optional(),
        path: zRouteOverviewPath,
        query: zRouteOverviewQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/v2/api/route/{coordinates}',
    ...options,
});
/**
 * Calculate Route
 *
 * This API response is intended for use in applications requiring detailed route information and navigation instructions. Such applications might include: GPS navigation systems, Mapping services, Route optimization tools for logistics and delivery, Travel planning apps.These can guide users from their starting point to their destination, providing clear, step-by-step directions, estimated travel times, and costs associated with the journey.
 */
const calculateRoute = (options) => (options.client ?? client).post({
    requestValidator: async (data) => await z
        .object({
        body: zCalculateRouteBody2,
        path: z.never().optional(),
        query: zCalculateRouteQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/v2/api/routing',
    ...options,
    headers: {
        'Content-Type': 'application/json',
        ...options.headers,
    },
});
/**
 * Search Place
 *
 * This API endpoint searches for places that match a given query string. It returns a list of matching places, including their addresses and unique place codes. This API is useful for searching and retrieving detailed information about places based on a given query string, which can be helpful for location-based services, mapping, and navigation applications.
 *
 * **Note: Each request to this API generates a new session ID. The session ID is crucial for testing and tracking API interactions. Make sure to include the session ID in** [<b>Get Place Details</b>](https://docs.barikoi.com/api#tag/v2.0/operation/Search_PlGet_Place_Detailsace) **API request to ensure proper functionality.**
 */
const searchPlace = (options) => (options.client ?? client).get({
    requestValidator: async (data) => await z
        .object({
        body: z.never().optional(),
        path: z.never().optional(),
        query: zSearchPlaceQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/api/v2/search-place',
    ...options,
});
/**
 * Place Details
 *
 * This API endpoint retrieves information about a specific place identified by the place code (in this case "BKOI2017") from the Barikoi platform. It returns essential details such as the address and geographic coordinates of the requested place, which can be useful for various location-based applications or services.
 *
 * **Note: It requires the place code for the desired location and utilizes the session ID generated from the previous** [<b>Search Place</b>](https://docs.barikoi.com/api#tag/v2.0/operation/Search_Place) **request for maintaining session continuity.**
 */
const placeDetails = (options) => (options.client ?? client).get({
    requestValidator: async (data) => await z
        .object({
        body: z.never().optional(),
        path: z.never().optional(),
        query: zPlaceDetailsQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/api/v2/places',
    ...options,
});
/**
 * Snap to Road
 *
 * Snap to Road API endpoint retrieves the nearest point on the road network to a specified geographical point (latitude and longitude). It returns the coordinates of the nearest point and the distance from the specified point to this nearest point. Snap to Road API is useful for finding the closest road location to a given geographic point, which can be used in various applications such as route planning, geofencing, and location-based services.
 */
const snapToRoad = (options) => (options.client ?? client).get({
    requestValidator: async (data) => await z
        .object({
        body: z.never().optional(),
        path: z.never().optional(),
        query: zSnapToRoadQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/v2/api/routing/nearest',
    ...options,
});
/**
 * Nearby Places
 *
 * Finds nearby places within a radius and limit using latitude/longitude.
 */
const nearby = (options) => (options.client ?? client).get({
    requestValidator: async (data) => await z
        .object({
        body: z.never().optional(),
        path: zNearbyPath,
        query: zNearbyQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/v2/api/search/nearby/{radius}/{limit}',
    ...options,
});
/**
 * Check Nearby
 *
 * Checks whether a destination point is within a given radius of a current point.
 */
const checkNearby = (options) => (options.client ?? client).get({
    requestValidator: async (data) => await z
        .object({
        body: z.never().optional(),
        path: z.never().optional(),
        query: zCheckNearbyQuery,
    })
        .parseAsync(data),
    security: [
        {
            in: 'query',
            name: 'api_key',
            type: 'apiKey',
        },
    ],
    url: '/v2/api/check/nearby',
    ...options,
});

class BarikoiError extends Error {
    constructor(message, statusCode, code, details) {
        super(message);
        this.statusCode = statusCode;
        this.code = code;
        this.details = details;
        this.name = 'BarikoiError';
        Error.captureStackTrace?.(this, this.constructor);
    }
    isAuthError() {
        return this.statusCode === 401 || this.statusCode === 403;
    }
    isRateLimitError() {
        return this.statusCode === 429;
    }
    isServerError() {
        return this.statusCode ? this.statusCode >= 500 : false;
    }
}
class ValidationError extends BarikoiError {
    constructor(message, details) {
        super(message, 400, 'VALIDATION_ERROR', details);
        this.name = 'ValidationError';
    }
}
class TimeoutError extends BarikoiError {
    constructor(message = 'Request timeout') {
        super(message, 408, 'TIMEOUT_ERROR');
        this.name = 'TimeoutError';
    }
}

/**
 * Parameter Schemas for Barikoi SDK Methods
 * These schemas define and validate the input parameters for each SDK method
 */
// ============================================================
// AUTOCOMPLETE
// ============================================================
const autocompleteParamsSchema = z$1.object({
    q: z$1.string().min(1, 'Search query is required'),
    bangla: z$1.boolean().optional().default(true),
});
// ============================================================
// REVERSE GEOCODE
// ============================================================
const reverseGeocodeParamsSchema = z$1.object({
    latitude: z$1.number().min(-90).max(90),
    longitude: z$1.number().min(-180).max(180),
    country_code: z$1.string().optional().default('BD'),
    country: z$1.boolean().optional(),
    district: z$1.boolean().optional(),
    post_code: z$1.boolean().optional(),
    sub_district: z$1.boolean().optional(),
    union: z$1.boolean().optional(),
    pauroshova: z$1.boolean().optional(),
    location_type: z$1.boolean().optional(),
    division: z$1.boolean().optional(),
    address: z$1.boolean().optional(),
    area: z$1.boolean().optional(),
    bangla: z$1.boolean().optional(),
    thana: z$1.boolean().optional(),
});
// ============================================================
// GEOCODE (Rupantor)
// ============================================================
const geocodeParamsSchema = z$1.object({
    q: z$1.string().min(1, 'Address to geocode is required'),
    thana: z$1.enum(['yes', 'no']).optional(),
    district: z$1.enum(['yes', 'no']).optional(),
    bangla: z$1.enum(['yes', 'no']).optional(),
});
// ============================================================
// SEARCH PLACE
// ============================================================
const searchPlaceParamsSchema = z$1.object({
    q: z$1.string().min(1, 'Search query is required'),
});
// ============================================================
// PLACE DETAILS
// ============================================================
const placeDetailsParamsSchema = z$1.object({
    place_code: z$1.string().min(1, 'Place code is required'),
    session_id: z$1.string().min(1, 'Session ID is required'), // UUID format validated by API
});
// ============================================================
// NEARBY
// ============================================================
const nearbyParamsSchema = z$1.object({
    latitude: z$1.number().min(-90).max(90),
    longitude: z$1.number().min(-180).max(180),
    radius: z$1.number().min(0.1).max(100).optional().default(0.5),
    limit: z$1.number().int().min(1).max(100).optional().default(10),
});
// ============================================================
// CHECK NEARBY
// ============================================================
const checkNearbyParamsSchema = z$1.object({
    current_latitude: z$1.number().min(-90).max(90),
    current_longitude: z$1.number().min(-180).max(180),
    destination_latitude: z$1.number().min(-90).max(90),
    destination_longitude: z$1.number().min(-180).max(180),
    radius: z$1.number().int().min(1).max(1000),
});
// ============================================================
// SNAP TO ROAD
// ============================================================
const snapToRoadParamsSchema = z$1.object({
    point: z$1
        .string()
        .regex(/^-?\d+\.?\d*,-?\d+\.?\d*$/, 'Point must be in format: latitude,longitude'),
});
// ============================================================
// ROUTE OVERVIEW
// ============================================================
const routeOverviewParamsSchema = z$1.object({
    coordinates: z$1
        .string()
        .regex(/^-?\d+\.?\d*,-?\d+\.?\d*(;-?\d+\.?\d*,-?\d+\.?\d*)+$/, 'Coordinates must be in format: lon,lat;lon,lat'),
    geometries: z$1.enum(['polyline', 'polyline6', 'geojson']).optional().default('polyline'),
    profile: z$1.enum(['car', 'foot']).optional().default('car'),
});
// ============================================================
// CALCULATE ROUTE
// ============================================================
const calculateRouteParamsSchema = z$1.object({
    data: z$1.object({
        start: z$1.object({
            latitude: z$1.number().min(-90).max(90),
            longitude: z$1.number().min(-180).max(180),
        }),
        destination: z$1.object({
            latitude: z$1.number().min(-90).max(90),
            longitude: z$1.number().min(-180).max(180),
        }),
    }),
});
// ============================================================
// OPTIMIZE ROUTE
// ============================================================
const geoPointSchema = z$1.object({
    id: z$1.number().int(),
    point: z$1
        .string()
        .regex(/^-?\d+\.?\d*,-?\d+\.?\d*$/, 'Point must be in format: latitude,longitude'),
});
z$1.object({
    source: z$1
        .string()
        .regex(/^-?\d+\.?\d*,-?\d+\.?\d*$/, 'Source must be in format: latitude,longitude'),
    destination: z$1
        .string()
        .regex(/^-?\d+\.?\d*,-?\d+\.?\d*$/, 'Destination must be in format: latitude,longitude'),
    profile: z$1.enum(['car', 'bike', 'foot', 'motorcycle']).optional().default('car'),
    geo_points: z$1.array(geoPointSchema).min(1).max(50),
});
// ============================================================
// VALIDATION HELPERS
// ============================================================
/**
 * Validate autocomplete params
 */
const validateAutocompleteParams = (data) => {
    return autocompleteParamsSchema.parse(data);
};
/**
 * Validate reverse geocode params
 */
const validateReverseGeocodeParams = (data) => {
    return reverseGeocodeParamsSchema.parse(data);
};
/**
 * Validate geocode params
 */
const validateGeocodeParams = (data) => {
    return geocodeParamsSchema.parse(data);
};
/**
 * Validate search place params
 */
const validateSearchPlaceParams = (data) => {
    return searchPlaceParamsSchema.parse(data);
};
/**
 * Validate place details params
 */
const validatePlaceDetailsParams = (data) => {
    return placeDetailsParamsSchema.parse(data);
};
/**
 * Validate nearby params
 */
const validateNearbyParams = (data) => {
    return nearbyParamsSchema.parse(data);
};
/**
 * Validate check nearby params
 */
const validateCheckNearbyParams = (data) => {
    return checkNearbyParamsSchema.parse(data);
};
/**
 * Validate snap to road params
 */
const validateSnapToRoadParams = (data) => {
    return snapToRoadParamsSchema.parse(data);
};
/**
 * Validate route overview params
 */
const validateRouteOverviewParams = (data) => {
    return routeOverviewParamsSchema.parse(data);
};
/**
 * Validate calculate route params
 */
const validateCalculateRouteParams = (data) => {
    return calculateRouteParamsSchema.parse(data);
};

/**
 * Barikoi API Client
 * A TypeScript SDK for Barikoi Location APIs
 */
class BarikoiClient {
    /** @internal reset for tests */
    static _resetBrowserWarnFlagForTests() {
        BarikoiClient.warnedBrowser = false;
    }
    constructor(config) {
        this.apiKey = config.apiKey;
        this.timeout = config.timeout ?? 30000; // Default 30 seconds
        // One-time runtime nudge for direct browser usage
        if (typeof window !== 'undefined' && !config.allowBrowser && !BarikoiClient.warnedBrowser) {
            BarikoiClient.warnedBrowser = true;
            console.warn('Barikoi SDK: running in a browser with an embedded API key exposes the key to visitors. ' +
                'Route requests through your own backend proxy when possible, or set `allowBrowser: true` to suppress this warning.');
        }
        // Validate baseUrl (H-2/M-1: SSRF + cleartext exfil sink).
        // Default to the canonical host when unspecified; refuse garbage or http://.
        const baseUrl = this.resolveBaseUrl(config.baseUrl, config.allowInsecure);
        // Configure the global client with timeout
        client.setConfig({
            baseUrl,
            fetch: this.createFetchWithTimeout(),
        });
    }
    resolveBaseUrl(baseUrl, allowInsecure) {
        const candidate = baseUrl ?? 'https://barikoi.xyz';
        let parsed;
        try {
            parsed = new URL(candidate);
        }
        catch {
            throw new BarikoiError(`Invalid baseUrl: ${candidate}`);
        }
        if (parsed.protocol !== 'https:' && !allowInsecure) {
            throw new BarikoiError(`baseUrl must use https:// (got ${parsed.protocol}). Set allowInsecure: true to permit http://.`);
        }
        return parsed.toString().replace(/\/$/, '');
    }
    /**
     * Creates a fetch function with timeout support
     */
    createFetchWithTimeout() {
        return async (input, init) => {
            const controller = new AbortController();
            const timeoutId = setTimeout(() => controller.abort(), this.timeout);
            try {
                const response = await fetch(input, {
                    ...init,
                    signal: controller.signal,
                });
                clearTimeout(timeoutId);
                return response;
            }
            catch (error) {
                clearTimeout(timeoutId);
                if (error instanceof Error && error.name === 'AbortError') {
                    throw new TimeoutError(`Request timed out after ${this.timeout}ms`);
                }
                throw error;
            }
        };
    }
    /**
     * Set API key
     */
    setApiKey(apiKey) {
        this.apiKey = apiKey;
    }
    /**
     * Get current API key
     */
    getApiKey() {
        return this.apiKey;
    }
    /**
     * Set timeout for API requests
     * @param timeout - Timeout in milliseconds
     */
    setTimeout(timeout) {
        this.timeout = timeout;
        // Reconfigure client with new timeout
        client.setConfig({
            fetch: this.createFetchWithTimeout(),
        });
    }
    /**
     * Get current timeout setting
     */
    getTimeout() {
        return this.timeout;
    }
    /**
     * Reverse Geocoding - Convert coordinates to address
     */
    async reverseGeocode(params) {
        // Validate params with Zod schema
        const validatedParams = validateReverseGeocodeParams(params);
        return reverseGeocode({
            query: {
                ...validatedParams,
                api_key: this.apiKey,
            },
        });
    }
    /**
     * Autocomplete - Search for places
     */
    async autocomplete(params) {
        // Validate params with Zod schema
        const validatedParams = validateAutocompleteParams(params);
        return autocomplete({
            query: {
                ...validatedParams,
                api_key: this.apiKey,
            },
        });
    }
    /**
     * Geocode - Format and geocode addresses
     */
    async geocode(params) {
        // Validate params with Zod schema
        const validatedParams = validateGeocodeParams(params);
        return geocode({
            query: {
                api_key: this.apiKey,
            },
            body: validatedParams,
        });
    }
    /**
     * Search Place
     */
    async searchPlace(params) {
        // Validate params with Zod schema
        const validatedParams = validateSearchPlaceParams(params);
        return searchPlace({
            query: {
                ...validatedParams,
                api_key: this.apiKey,
            },
        });
    }
    /**
     * Place Details - get place info
     */
    async placeDetails(params) {
        // Validate params with Zod schema
        const validatedParams = validatePlaceDetailsParams(params);
        return placeDetails({
            query: {
                ...validatedParams,
                api_key: this.apiKey,
            },
        });
    }
    /**
     * Nearby - Find nearby places
     */
    async nearby(params) {
        // Validate params with Zod schema
        const validatedParams = validateNearbyParams(params);
        const { radius = 0.5, limit = 10, ...queryParams } = validatedParams;
        return nearby({
            path: {
                radius,
                limit,
            },
            query: {
                ...queryParams,
                api_key: this.apiKey,
            },
        });
    }
    /**
     * Check nearby - verify proximity
     */
    async checkNearby(params) {
        // Validate params with Zod schema
        const validatedParams = validateCheckNearbyParams(params);
        return checkNearby({
            query: {
                ...validatedParams,
                api_key: this.apiKey,
            },
        });
    }
    /**
     * Calculate Route
     */
    async calculateRoute(params) {
        // Validate body params with Zod schema (type and profile are query params, not in body)
        const { start, destination, type = 'gh', profile } = params;
        const validatedBody = validateCalculateRouteParams({ data: { start, destination } });
        return calculateRoute({
            query: {
                api_key: this.apiKey,
                type,
                ...(profile ? { profile } : {}),
            },
            body: validatedBody,
        });
    }
    /**
     * Snap to Road
     */
    async snapToRoad(params) {
        // Validate params with Zod schema
        const validatedParams = validateSnapToRoadParams(params);
        return snapToRoad({
            query: {
                ...validatedParams,
                api_key: this.apiKey,
            },
        });
    }
    /**
     * Optimize Route - optimize waypoints
     */
    // async optimizeRoute(params: Omit<OptimizeRouteData['body'], 'api_key'>) {
    //   // Validate source and destination coordinates
    //   validatePointString(params.source, 'source')
    //   validatePointString(params.destination, 'destination')
    //   // Validate geo_points array
    //   validatePointArray(params.geo_points, 'geo_points')
    //   return optimizeRoute({
    //     body: {
    //       api_key: this.apiKey,
    //       ...params,
    //     },
    //   })
    // }
    /**
     * Route Overview - basic route info
     */
    async routeOverview(params) {
        // Validate params with Zod schema
        const validatedParams = validateRouteOverviewParams(params);
        const { coordinates, ...queryParams } = validatedParams;
        return routeOverview({
            path: {
                coordinates,
            },
            query: {
                ...queryParams,
                api_key: this.apiKey,
            },
        });
    }
    /**
     * Get client instance with API key pre-configured
     */
    getConfiguredClient() {
        return client;
    }
}
BarikoiClient.warnedBrowser = false;
/**
 * Create a new Barikoi client instance
 *
 * @example
 * ```typescript
 * const barikoi = createBarikoiClient({
 *   apiKey: 'your-api-key'
 * })
 *
 * const result = await barikoi.autocomplete({
 *   q: 'Dhaka',
 *   bangla: true
 * })
 * ```
 */
function createBarikoiClient(config) {
    return new BarikoiClient(config);
}

export { BarikoiClient, BarikoiError, TimeoutError, ValidationError, createBarikoiClient };
//# sourceMappingURL=index.js.map