(path, givenOptions, throwErr)
| 8 | * @returns |
| 9 | */ |
| 10 | const fetchWinstallAPI = async (path, givenOptions, throwErr) => { |
| 11 | const config = await getRuntimeConfig(); |
| 12 | |
| 13 | // Client-side routing logic: |
| 14 | // - All client requests go through proxy (/api/winstall) |
| 15 | // - Server-side: direct API access with auth headers |
| 16 | const isClientSide = typeof window !== 'undefined'; |
| 17 | const useProxy = isClientSide; |
| 18 | |
| 19 | // Client-side always uses proxy, doesn't need apiBase |
| 20 | if (!useProxy && !config.apiBase) { |
| 21 | console.warn(`[fetchWinstallAPI] no API configured, skipping ${path}`); |
| 22 | return { response: null, error: null }; |
| 23 | } |
| 24 | |
| 25 | const url = useProxy ? `/api/winstall${path}` : `${config.apiBase}${path}`; |
| 26 | const isDebug = process.env.WINSTALL_API_DEBUG === "1"; |
| 27 | const timeoutMs = Number(process.env.WINSTALL_API_TIMEOUT_MS || 15000); |
| 28 | const method = givenOptions?.method || "GET"; |
| 29 | |
| 30 | let additionalOptions = { ...givenOptions }; |
| 31 | let headerOptions; |
| 32 | |
| 33 | if (additionalOptions) { |
| 34 | headerOptions = { ...givenOptions?.headers }; |
| 35 | delete additionalOptions["headers"]; |
| 36 | } |
| 37 | |
| 38 | let response, error; |
| 39 | const startedAt = Date.now(); |
| 40 | const controller = new AbortController(); |
| 41 | const timeoutId = setTimeout(() => controller.abort(), timeoutMs); |
| 42 | |
| 43 | try { |
| 44 | if (isDebug) { |
| 45 | console.log(`[fetchWinstallAPI] request ${method} ${url} (timeout ${timeoutMs}ms)`); |
| 46 | } |
| 47 | |
| 48 | const headers = { ...headerOptions }; |
| 49 | |
| 50 | // Only add auth headers on server-side (client uses proxy for authenticated requests) |
| 51 | if (!isClientSide && config.apiKey && config.apiSecret) { |
| 52 | headers.AuthKey = config.apiKey; |
| 53 | headers.AuthSecret = config.apiSecret; |
| 54 | } |
| 55 | |
| 56 | // Use global fetch - smart proxy dispatcher handles NO_PROXY automatically |
| 57 | const res = await fetch(url, { |
| 58 | headers, |
| 59 | ...additionalOptions, |
| 60 | redirect: "follow", |
| 61 | signal: controller.signal, |
| 62 | }); |
| 63 | |
| 64 | if (isDebug) { |
| 65 | const elapsedMs = Date.now() - startedAt; |
| 66 | console.log(`[fetchWinstallAPI] response ${res.status} ${res.statusText} ${url} (${elapsedMs}ms)`); |
| 67 | } |
no test coverage detected