{"version":3,"file":"index-BPCxWKi1.js","sources":["../../Client/api/Fetch/index.ts"],"sourcesContent":["import { ApiCallMessage } from '@shared/Models';\r\nimport dayjs from 'dayjs';\r\n\r\nconst defaultContentType = 'application/json; charset=UTF-8';\r\n\r\nexport async function fetchAndLog<TModel = void>(\r\n    info: RequestInfo | URL,\r\n    actionToLog: string,\r\n    request?: RequestInit,\r\n    parseError?: boolean\r\n): Promise<TModel> {\r\n    const response = await fetchAndLogWithResponse(info, actionToLog, request);\r\n\r\n    if (!response.ok) {\r\n        if (parseError) {\r\n            let errorToThrow = response;\r\n\r\n            try {\r\n                errorToThrow = await response.json();\r\n            } catch {}\r\n\r\n            throw errorToThrow;\r\n        } else {\r\n            throw response;\r\n        }\r\n    }\r\n\r\n    const text = await response.text();\r\n    return text?.length ? JSON.parse(text) : (undefined as TModel);\r\n}\r\n\r\nexport async function fetchAndLogWithResponse(\r\n    info: RequestInfo | URL,\r\n    actionToLog: string,\r\n    request?: RequestInit\r\n): Promise<Response> {\r\n    const headers = getDefaultHeaders(request?.headers);\r\n\r\n    if (!request) request = { method: 'GET' };\r\n\r\n    request.headers = { ...headers, ...request.headers };\r\n\r\n    const start = dayjs(),\r\n        response = await fetch(info, request),\r\n        elapsed = dayjs().diff(start, 'millisecond');\r\n\r\n    await logApiCall(actionToLog, request, info.toString(), elapsed);\r\n\r\n    return response;\r\n}\r\n\r\n/** Handles uploading files properly using a FormData object, which encodes as multipart/form-data:\r\n * 1. Submit a POST request with a body of FormData\r\n * 2. If submitting an HTML form, set the encType attribute to multipart/form-data\r\n * 3. The request headers can not be set manually, because that overrides the Content-Type and the Content-Type boundary which is automatically set by the browser for this type of request.\r\n * See https://stackoverflow.com/questions/72715243/boundary-value-of-the-header-content-type-is-not-applied-to-request-payload-and\r\n * */\r\nexport async function uploadAndLogWithResponse(\r\n    info: RequestInfo | URL,\r\n    actionToLog: string,\r\n    formData: FormData\r\n): Promise<Response> {\r\n    const start = dayjs(),\r\n        request = {\r\n            method: 'POST',\r\n            body: formData,\r\n        },\r\n        response = await fetch(info, request),\r\n        elapsed = dayjs().diff(start, 'millisecond');\r\n\r\n    await logApiCall(actionToLog, request, info.toString(), elapsed);\r\n\r\n    return response;\r\n}\r\n\r\nfunction getDefaultHeaders(headers: HeadersInit | undefined) {\r\n    headers = headers || {};\r\n\r\n    if (!headers['Content-Type']) headers['Content-Type'] = defaultContentType;\r\n\r\n    return headers;\r\n}\r\n\r\n// Creates an RFC4122 compliant GUID using random values from the built-in crypto module.\r\nexport function uuidV4() {\r\n    return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, c =>\r\n        (+c ^ (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4)))).toString(16)\r\n    );\r\n}\r\n\r\nasync function logApiCall(actionToLog: string, request: RequestInit | undefined, info: string, elapsed: number) {\r\n    const log: ApiCallMessage = {\r\n        ApiCall: actionToLog,\r\n        Details: (request?.method === 'POST' && request?.body\r\n            ? JSON.stringify(request?.body)\r\n            : info.toString()\r\n        ).substring(0, 100),\r\n        ElapsedMilliseconds: elapsed,\r\n    };\r\n\r\n    // Don't await this fetch to prevent blocking while logging call occurs.\r\n    fetch('/api/log/apicall', {\r\n        method: 'POST',\r\n        body: JSON.stringify(log),\r\n        headers: {\r\n            'Content-Type': defaultContentType,\r\n        },\r\n    });\r\n}\r\n"],"names":["defaultContentType","fetchAndLog","info","actionToLog","request","parseError","response","fetchAndLogWithResponse","errorToThrow","text","headers","getDefaultHeaders","start","dayjs","elapsed","logApiCall","uuidV4","c","log"],"mappings":"iCAGA,MAAMA,EAAqB,kCAE3B,eAAsBC,EAClBC,EACAC,EACAC,EACAC,EACe,CACf,MAAMC,EAAW,MAAMC,EAAwBL,EAAMC,EAAaC,CAAO,EAErE,GAAA,CAACE,EAAS,GACV,GAAID,EAAY,CACZ,IAAIG,EAAeF,EAEf,GAAA,CACeE,EAAA,MAAMF,EAAS,KAAK,CAAA,MAC/B,CAAA,CAEF,MAAAE,CAAA,KAEA,OAAAF,EAIR,MAAAG,EAAO,MAAMH,EAAS,KAAK,EACjC,OAAOG,GAAA,MAAAA,EAAM,OAAS,KAAK,MAAMA,CAAI,EAAK,MAC9C,CAEsB,eAAAF,EAClBL,EACAC,EACAC,EACiB,CACX,MAAAM,EAAUC,EAAkBP,GAAA,YAAAA,EAAS,OAAO,EAE7CA,IAAmBA,EAAA,CAAE,OAAQ,KAAM,GAExCA,EAAQ,QAAU,CAAE,GAAGM,EAAS,GAAGN,EAAQ,OAAQ,EAEnD,MAAMQ,EAAQC,EAAA,EACVP,EAAW,MAAM,MAAMJ,EAAME,CAAO,EACpCU,EAAUD,EAAA,EAAQ,KAAKD,EAAO,aAAa,EAE/C,aAAMG,EAAWZ,EAAaC,EAASF,EAAK,WAAYY,CAAO,EAExDR,CACX,CA0BA,SAASK,EAAkBD,EAAkC,CACzD,OAAAA,EAAUA,GAAW,CAAC,EAEjBA,EAAQ,cAAc,IAAGA,EAAQ,cAAc,EAAIV,GAEjDU,CACX,CAGO,SAASM,GAAS,CACrB,MAAO,uCAAuC,QAAQ,aACjD,CAACC,EAAK,OAAO,gBAAgB,IAAI,WAAW,CAAC,CAAC,EAAE,CAAC,EAAK,IAAO,CAACA,EAAI,GAAM,SAAS,EAAE,CACxF,CACJ,CAEA,eAAeF,EAAWZ,EAAqBC,EAAkCF,EAAcY,EAAiB,CAC5G,MAAMI,EAAsB,CACxB,QAASf,EACT,UAAUC,GAAA,YAAAA,EAAS,UAAW,SAAUA,GAAA,MAAAA,EAAS,MAC3C,KAAK,UAAUA,GAAA,YAAAA,EAAS,IAAI,EAC5BF,EAAK,SACT,GAAA,UAAU,EAAG,GAAG,EAClB,oBAAqBY,CACzB,EAGA,MAAM,mBAAoB,CACtB,OAAQ,OACR,KAAM,KAAK,UAAUI,CAAG,EACxB,QAAS,CACL,eAAgBlB,CAAA,CACpB,CACH,CACL"}