{
  "version": 3,
  "sources": ["../../../src/metrics/publisher/rest.ts"],
  "sourcesContent": ["import type { PublishCommand } from './types.ts';\nimport { Metrics } from '../../../types/metrics/api';\nimport type { Logger } from '../../../types/logging/api';\nimport type { RestPublisherConfig } from '../../../types/metrics/publisher/rest';\n\nasync function discardResponseBody(response: Response) {\n    if (!response.bodyUsed) {\n        await response.blob();\n    }\n}\n\nconst SUCCESS_STATUSES = new Set<number>([200/*OK*/, 201/*CREATED*/, 202/*ACCEPTED*/]);\n\nfunction basicAuthCredentials({user, password}: { user: string; password: string }) {\n    const data = `${user}:${password}`;\n    if (typeof process !== 'undefined') {\n        return Buffer.from(data).toString('base64');\n    } else {\n        return globalThis.btoa(data);\n    }\n}\n\nexport const name = 'rest';\n\nasync function login(url: URL, {logger, fetch: fetchFn, headers, timeout}: HandleContext) {\n\n    if (logger.enabledFor('debug')) {\n        logger.debug(`sending initial GET to do auth dance. url: ${url}`);\n    }\n    try {\n        const response = await fetchFn(url, initRequest(timeout, headers));\n        if (response.ok) {\n            logger.info(`initial GET request completed successfully.`);\n            if (logger.enabledFor('debug')) {\n                const setCookie = response.headers.getSetCookie();\n                if (setCookie.length > 0) {\n                    if (logger.enabledFor('debug')) {\n                        logger.debug(`will set following cookies: ${setCookie}`);\n                    }\n                }\n            }\n        } else {\n            logger.warn(`initial GET request did not completed successfully. Status: ${response.status}`);\n        }\n    } catch (e) {\n        logger.warn(`error executing initial GET request`, e);\n        throw e;\n    }\n}\n\nasync function handleStart(auth: RestPublisherConfig['authentication'], context: HandleContext) {\n    if (!isBasicAuthorization(auth) && auth !== false) {\n        const url = new context.URL(context.endpoint);\n        if (auth?.path) {\n            url.pathname = auth.path;\n        }\n        await login(url, context)\n    }\n    context.logger.info('rest publisher started');\n}\n\nfunction handleStop({logger}: HandleContext) {\n    logger.info('rest publisher stopped');\n}\n\nfunction initRequest(timeout: number, headers: Headers, m?: Metrics.Update): RequestInit {\n    return m ?\n        {\n            method: 'POST',\n            redirect: 'manual',\n            credentials: 'include',\n            signal: AbortSignal.timeout(timeout),\n            headers,\n            body: JSON.stringify(m)\n        }\n        :\n        {\n            method: 'GET',\n            redirect: 'follow',\n            credentials: 'include',\n            signal: AbortSignal.timeout(timeout),\n            headers\n        }\n}\n\n// a helper type to track state changes\n// good -> bad\n// bad -> good\ntype PublisherState = {\n    // indicates if the previous state was healthy\n    prev: boolean\n    // indicates\n    now: boolean\n};\n\nasync function handleUpdate(m: Metrics.Update, state: PublisherState, {\n    endpoint,\n    headers,\n    timeout,\n    fetch: fetchFn,\n    logger\n}: HandleContext) {\n    const request = initRequest(timeout, headers, m);\n\n    try {\n        let response = await fetchFn(endpoint, request);\n        if (response.redirected) {\n            logger.info(`Redirect detected will do GET to allow auth dance and re-POST`);\n            await discardResponseBody(response);\n            const getResponse = await fetchFn(endpoint, initRequest(timeout, headers));\n            await discardResponseBody(getResponse);\n            if (getResponse.ok) {\n                response = await fetchFn(endpoint, request);\n            } else {\n                logger.error(`GET failed with status: ${getResponse.status} headers: ${JSON.stringify(getResponse.headers)}`);\n            }\n        }\n        await discardResponseBody(response);\n        state.prev = state.now;\n        state.now = SUCCESS_STATUSES.has(response.status);\n        if (state.prev && !state.now) {\n            logger.error(`Unable to publish metrics. status ${response.status} headers: ${JSON.stringify(response.headers)} msg: ${JSON.stringify(m)}`);\n        } else if (state.now && !state.prev) {\n            logger.info(`Publishing metrics.`);\n        }\n    } catch (e) {\n        const logError = state.now;\n        state.prev = state.now;\n        state.now = false;\n        if (logError) {\n            logger.error(`Unable to publish metrics. msg ${JSON.stringify(m)}`, e);\n        }\n    }\n}\n\ntype HandleContext = {\n    endpoint: string | URL\n    headers: Headers\n    timeout: number\n    fetch: typeof fetch\n    URL: typeof URL\n    logger: Logger\n}\n\nfunction isBasicAuthorization(auth?: RestPublisherConfig['authentication']): auth is {user: string, password: string} {\n    return auth !== undefined && auth && (auth['user'] !== undefined);\n}\n\nexport async function create(cfg: RestPublisherConfig, logger: Logger) {\n    const endpoint = cfg.endpoint;\n    const timeout = cfg.timeout ?? 1000;\n    const HeadersCtor: typeof Headers = cfg.Headers ?? globalThis.Headers ?? Headers;\n    const headers = new HeadersCtor(cfg.headers);\n    if (!headers.has('Content-Type')) {\n        headers.set('Content-Type', 'application/json');\n    }\n    if (!headers.has('User-Agent')) {\n        headers.set('User-Agent', cfg['user-agent'] ?? 'metrics-rest/0.2.x');\n    }\n    if (isBasicAuthorization(cfg.authentication) && !headers.has('Authorization')) {\n        headers.set('Authorization', `Basic ${basicAuthCredentials(cfg.authentication)}`);\n    }\n\n    const fetchFn: typeof fetch = cfg.fetch ?? globalThis.fetch ?? fetch;\n    const URLCtor: typeof URL = cfg.URL ?? globalThis.URL ?? URL;\n    const state = { prev: false, now: true };\n    const context: HandleContext = {endpoint, headers, timeout, fetch: fetchFn, URL: URLCtor, logger};\n    return async (m: PublishCommand) => {\n        if (logger.enabledFor('debug')) {\n            logger.debug(`handling publish request: ${JSON.stringify(m)}`);\n        }\n        switch (m) {\n            case 'start': {\n                await handleStart(cfg.authentication, context);\n                break;\n            }\n            case 'stop': {\n                handleStop(context);\n                break;\n            }\n            default: {\n                await handleUpdate(m, state, context);\n                break;\n            }\n        }\n    }\n}\n"],
  "mappings": "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",
  "names": ["rest_exports", "__export", "create", "name", "__toCommonJS", "discardResponseBody", "response", "SUCCESS_STATUSES", "basicAuthCredentials", "user", "password", "data", "login", "url", "logger", "fetchFn", "headers", "timeout", "initRequest", "setCookie", "e", "handleStart", "auth", "context", "isBasicAuthorization", "handleStop", "m", "handleUpdate", "state", "endpoint", "request", "getResponse", "logError", "cfg", "HeadersCtor", "URLCtor"]
}
