{"version":3,"sources":["jsdelivr-header.js","/npm/@fal-ai/server-proxy@1.2.1/src/index.js"],"names":[],"mappings":"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","file":"/npm/@fal-ai/server-proxy@1.2.1/src/index.js","sourceRoot":"","sourcesContent":["/**\n * Minified by jsDelivr using Terser v5.39.0.\n * Original file: /npm/@fal-ai/server-proxy@1.2.1/src/index.js\n *\n * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files\n */\n","\"use strict\";\nObject.defineProperty(exports, \"__esModule\", { value: true });\nexports.resolveApiKeyFromEnv = exports.responsePassthrough = exports.DEFAULT_PROXY_ROUTE = exports.TARGET_URL_HEADER = exports.resolveProxyConfig = exports.DEFAULT_ALLOWED_URL_PATTERNS = exports.createUrlMatcher = void 0;\nexports.isAllowedUrl = isAllowedUrl;\nexports.getEndpoint = getEndpoint;\nexports.isAllowedEndpoint = isAllowedEndpoint;\nexports.handleRequest = handleRequest;\nexports.fromHeaders = fromHeaders;\nconst config_1 = require(\"./config\");\nconst utils_1 = require(\"./utils\");\nvar config_2 = require(\"./config\");\nObject.defineProperty(exports, \"createUrlMatcher\", { enumerable: true, get: function () { return config_2.createUrlMatcher; } });\nObject.defineProperty(exports, \"DEFAULT_ALLOWED_URL_PATTERNS\", { enumerable: true, get: function () { return config_2.DEFAULT_ALLOWED_URL_PATTERNS; } });\nObject.defineProperty(exports, \"resolveProxyConfig\", { enumerable: true, get: function () { return config_2.resolveProxyConfig; } });\nexports.TARGET_URL_HEADER = \"x-fal-target-url\";\nexports.DEFAULT_PROXY_ROUTE = \"/api/fal/proxy\";\nconst FAL_KEY = process.env.FAL_KEY;\nconst FAL_KEY_ID = process.env.FAL_KEY_ID;\nconst FAL_KEY_SECRET = process.env.FAL_KEY_SECRET;\n// Default matcher using the default allowed URL patterns\nconst defaultUrlMatcher = (0, config_1.createUrlMatcher)(config_1.DEFAULT_ALLOWED_URL_PATTERNS);\n/**\n * Checks if a URL matches any of the allowed URL patterns.\n *\n * @param url the URL to check (without scheme, e.g., \"fal.run/path\").\n * @param patterns the allowed URL patterns (glob-style). If not provided, uses default patterns.\n * @returns whether the URL is allowed.\n */\nfunction isAllowedUrl(url, patterns) {\n    if (patterns) {\n        return (0, config_1.createUrlMatcher)(patterns)(url);\n    }\n    return defaultUrlMatcher(url);\n}\n/**\n * Extracts the URL without the scheme for validation purposes.\n * @param targetUrl the full URL including scheme.\n * @returns the URL without the scheme (host + path + query).\n */\nfunction getUrlWithoutScheme(targetUrl) {\n    const url = new URL(targetUrl);\n    return `${url.host}${url.pathname}${url.search}`;\n}\n/**\n * Checks if the URL is on the fal.ai domain or any of its subdomains.\n * @param targetUrl the full URL including scheme.\n * @returns true if the URL is on *.fal.ai domain.\n */\nfunction isFalAiDomain(targetUrl) {\n    const url = new URL(targetUrl);\n    return url.host === \"fal.ai\" || url.host.endsWith(\".fal.ai\");\n}\n/**\n * Extracts the endpoint from a URL (path without leading slash).\n * @param targetUrl the full URL including scheme.\n * @returns the endpoint (path without leading slash).\n */\nfunction getEndpoint(targetUrl) {\n    const url = new URL(targetUrl);\n    // Remove leading slash from pathname\n    return url.pathname.replace(/^\\//, \"\");\n}\n/**\n * Checks if an endpoint matches any of the allowed endpoint patterns.\n *\n * @param endpoint the endpoint to check (path without leading slash).\n * @param patterns the allowed endpoint patterns (glob-style).\n * @returns whether the endpoint is allowed.\n */\nfunction isAllowedEndpoint(endpoint, patterns) {\n    // Empty array means all endpoints are allowed (backwards compatibility)\n    if (patterns.length === 0) {\n        return true;\n    }\n    return (0, config_1.createUrlMatcher)(patterns)(endpoint);\n}\nfunction getFalKey() {\n    if (FAL_KEY) {\n        return FAL_KEY;\n    }\n    if (FAL_KEY_ID && FAL_KEY_SECRET) {\n        return `${FAL_KEY_ID}:${FAL_KEY_SECRET}`;\n    }\n    return undefined;\n}\nconst EXCLUDED_HEADERS = [\"content-length\", \"content-encoding\"];\n/**\n * A request handler that proxies the request to the fal API\n * endpoint. This is useful so client-side calls to the fal endpoint\n * can be made without CORS issues and the correct credentials can be added\n * effortlessly.\n *\n * @param behavior the request proxy behavior.\n * @param config the proxy configuration. Can be a partial config (will be resolved internally)\n *               or a pre-resolved config from `resolveProxyConfig` to avoid per-request warnings.\n * @returns Promise<any> the promise that will be resolved once the request is done.\n */\nasync function handleRequest(behavior, config = {}) {\n    const targetUrl = (0, utils_1.singleHeaderValue)(behavior.getHeader(exports.TARGET_URL_HEADER));\n    if (!targetUrl) {\n        return behavior.respondWith(400, \"Invalid request\");\n    }\n    // Check if config is already resolved (has all required fields with non-undefined values)\n    const isResolved = config.isAuthenticated !== undefined &&\n        config.resolveFalAuth !== undefined &&\n        config.allowUnauthorizedRequests !== undefined &&\n        config.allowedUrlPatterns !== undefined;\n    const resolvedConfig = isResolved\n        ? config\n        : (0, config_1.applyProxyConfig)(config);\n    const urlToValidate = getUrlWithoutScheme(targetUrl);\n    if (!isAllowedUrl(urlToValidate, resolvedConfig.allowedUrlPatterns)) {\n        return behavior.respondWith(400, \"Invalid request\");\n    }\n    // Check allowed endpoints for POST requests only, skip for *.fal.ai domains\n    if (behavior.method?.toUpperCase() === \"POST\" && !isFalAiDomain(targetUrl)) {\n        const endpoint = getEndpoint(targetUrl);\n        if (!isAllowedEndpoint(endpoint, resolvedConfig.allowedEndpoints ?? [])) {\n            return behavior.respondWith(400, \"Invalid request\");\n        }\n    }\n    const isAuthenticated = (await resolvedConfig.isAuthenticated?.(behavior)) ?? false;\n    if (!isAuthenticated && !resolvedConfig.allowUnauthorizedRequests) {\n        return behavior.respondWith(401, \"Unauthorized\");\n    }\n    const authorization = (await resolvedConfig.resolveFalAuth?.(behavior)) ??\n        (await behavior.resolveApiKey?.());\n    if (!authorization) {\n        return behavior.respondWith(401, \"Unauthorized\");\n    }\n    // pass over headers prefixed with x-fal-*\n    const headers = {};\n    Object.keys(behavior.getHeaders()).forEach((key) => {\n        if (key.toLowerCase().startsWith(\"x-fal-\")) {\n            headers[key.toLowerCase()] = behavior.getHeader(key);\n        }\n    });\n    const proxyUserAgent = `@fal-ai/server-proxy/${behavior.id}`;\n    const userAgent = (0, utils_1.singleHeaderValue)(behavior.getHeader(\"user-agent\"));\n    const res = await fetch(targetUrl, {\n        method: behavior.method,\n        headers: {\n            ...headers,\n            authorization,\n            accept: \"application/json\",\n            \"content-type\": \"application/json\",\n            \"user-agent\": userAgent,\n            \"x-fal-client-proxy\": proxyUserAgent,\n        },\n        body: behavior.method?.toUpperCase() === \"GET\"\n            ? undefined\n            : await behavior.getRequestBody(),\n    });\n    // copy headers from fal to the proxied response\n    res.headers.forEach((value, key) => {\n        if (!EXCLUDED_HEADERS.includes(key.toLowerCase())) {\n            behavior.sendHeader(key, value);\n        }\n    });\n    return behavior.sendResponse(res);\n}\nfunction fromHeaders(headers) {\n    // TODO once Header.entries() is available, use that instead\n    // Object.fromEntries(headers.entries());\n    const result = {};\n    headers.forEach((value, key) => {\n        result[key] = value;\n    });\n    return result;\n}\nconst responsePassthrough = (res) => Promise.resolve(res);\nexports.responsePassthrough = responsePassthrough;\nconst resolveApiKeyFromEnv = () => Promise.resolve(getFalKey());\nexports.resolveApiKeyFromEnv = resolveApiKeyFromEnv;\n"]}