// engine/registry/http-client.ts — Fetch-based HTTP client for the Planu spec registry.
// Used by registry tools (search, install, publish) with graceful fallback to stubs.
const DEFAULT_REGISTRY_URL = 'https://registry.planu.dev';
/** Return the registry base URL from env var or default. */
export function getRegistryUrl() {
    return process.env.PLANU_REGISTRY_URL ?? DEFAULT_REGISTRY_URL;
}
/** Fetch search results from the backend. Returns null on any error so caller can fall back. */
export async function fetchRegistrySearch(filters) {
    try {
        const url = new URL('/api/specs', getRegistryUrl());
        if (filters.query) {
            url.searchParams.set('q', filters.query);
        }
        if (filters.category) {
            url.searchParams.set('category', filters.category);
        }
        if (filters.stack) {
            url.searchParams.set('stack', Array.isArray(filters.stack) ? filters.stack.join(',') : filters.stack);
        }
        if (filters.sort) {
            url.searchParams.set('sort', filters.sort);
        }
        if (filters.page !== undefined) {
            url.searchParams.set('page', String(filters.page));
        }
        if (filters.limit !== undefined) {
            url.searchParams.set('limit', String(filters.limit));
        }
        const response = await fetch(url.toString(), {
            signal: AbortSignal.timeout(5000),
        });
        if (!response.ok) {
            return null;
        }
        return (await response.json());
    }
    catch {
        return null;
    }
}
/** Download a spec by name + version. Returns YAML string or null on error. */
export async function fetchRegistrySpec(name, version) {
    try {
        const resolvedVersion = version ?? 'latest';
        const url = new URL(`/api/specs/${encodeURIComponent(name)}/versions/${encodeURIComponent(resolvedVersion)}`, getRegistryUrl());
        const response = await fetch(url.toString(), {
            signal: AbortSignal.timeout(10000),
        });
        if (!response.ok) {
            return null;
        }
        return await response.text();
    }
    catch {
        return null;
    }
}
/** Publish a spec to the registry. Requires auth token. Never throws. */
export async function publishToRegistry(yamlContent, token) {
    try {
        const url = new URL('/api/specs', getRegistryUrl());
        const response = await fetch(url.toString(), {
            method: 'POST',
            headers: {
                'Content-Type': 'application/yaml',
                Authorization: `Bearer ${token}`,
            },
            body: yamlContent,
            signal: AbortSignal.timeout(10000),
        });
        if (!response.ok) {
            const text = await response.text();
            return { ok: false, error: `${response.status}: ${text.slice(0, 200)}` };
        }
        const data = (await response.json());
        return { ok: true, specId: data.specId };
    }
    catch (err) {
        return { ok: false, error: err instanceof Error ? err.message : String(err) };
    }
}
//# sourceMappingURL=http-client.js.map