/**
 * Fetcher<Query, Data> — the three-step Transform/Extract/Transform (TET)
 * contract every trading data provider implements.
 *
 * Named after OpenBB's provider abstraction but reduced to the shape that
 * actually pays rent in a single-language TypeScript codebase:
 *
 *   1. `transformQuery(input)` — normalize caller input (ticker casing,
 *      default values, clamping) into the provider's expected query.
 *   2. `fetchData(query)` — hit the provider's API, return raw payload or a
 *      ProviderError.
 *   3. `transformData(raw, query)` — coerce the raw payload into the
 *      standard data type the rest of the codebase consumes.
 *
 * Keeping these three steps separate makes providers testable in isolation:
 * you can feed a canned raw payload into `transformData` without mocking
 * HTTP. It also keeps the provider code free of formatting concerns —
 * rendering is views' job, not fetchers'.
 */
/**
 * Helper: run a fetcher end-to-end with the default composition. Providers
 * that want caching, retries, or parallel fan-out can skip this and write
 * their own `run`. Kept as a plain function so callers don't depend on
 * object-oriented glue.
 */
export async function runFetcher(fetcher, input) {
    try {
        if (fetcher.run)
            return fetcher.run(input);
        const query = fetcher.transformQuery(input);
        const raw = await fetcher.fetchData(query);
        if (isProviderErrorLike(raw))
            return raw;
        return fetcher.transformData(raw, query);
    }
    catch (err) {
        return {
            kind: 'unknown',
            message: err instanceof Error ? err.message : String(err),
        };
    }
}
function isProviderErrorLike(v) {
    return typeof v === 'object' && v !== null && 'kind' in v && 'message' in v;
}
