helpers.ts (4815B)
1 import type { FieldRecord, IHttpOpts, IHttpOptsData, IHttpResponse, NotifyMessage } from "./types.js"; 2 3 const is_record = (value: unknown): value is Record<string, unknown> => { 4 return typeof value === "object" && value !== null; 5 }; 6 7 export const is_err_response = (response: unknown): response is { err: string } => { 8 if (!is_record(response)) return false; 9 const err = response["err"]; 10 return typeof err === "string"; 11 }; 12 13 export const is_pass_response = (response: unknown): response is { pass: true } => { 14 if (!is_record(response)) return false; 15 return response["pass"] === true; 16 }; 17 18 export const is_result_response = (response: unknown): response is { result: string } => { 19 if (!is_record(response)) return false; 20 const result = response["result"]; 21 return typeof result === "string"; 22 }; 23 24 export const is_results_response = (response: unknown): response is { results: string[] } => { 25 if (!is_record(response)) return false; 26 const results = response["results"]; 27 return Array.isArray(results) && results.every((value) => typeof value === "string"); 28 }; 29 30 export const is_error_response = (response: unknown): response is { error: string } => { 31 if (!is_record(response)) return false; 32 const error = response["error"]; 33 return typeof error === "string"; 34 }; 35 36 export const is_message_response = (response: unknown): response is NotifyMessage => { 37 if (!is_record(response)) return false; 38 const message = response["message"]; 39 const ok = response["ok"]; 40 const cancel = response["cancel"]; 41 return ( 42 typeof message === "string" && 43 (ok === undefined || typeof ok === "string") && 44 (cancel === undefined || typeof cancel === "string") 45 ); 46 }; 47 48 export const lib_http_to_bodyinit = (data: IHttpOptsData): RequestInit["body"] => { 49 if (typeof data === "string") return data; 50 if (data instanceof FormData) return data; 51 if (data instanceof Blob) return data; 52 if (data instanceof ArrayBuffer) return data; 53 if (data instanceof URLSearchParams) return data; 54 return JSON.stringify(data); 55 }; 56 57 export const lib_http_parse_headers = (headers: Headers): FieldRecord => { 58 const acc: FieldRecord = {}; 59 headers.forEach((value, key) => acc[key] = value); 60 return acc; 61 }; 62 63 export const http_fetch_opts = (opts: IHttpOpts): { url: string; options: RequestInit; } => { 64 const { url } = opts; 65 const method = opts.method ? opts.method.toUpperCase() : "GET"; 66 const headers = new Headers(); 67 if (method === "POST") headers.append("Content-Type", "application/json"); 68 if (opts.authorization) headers.append("Authorization", `Bearer ${encodeURIComponent(opts.authorization)}`); 69 if (opts.headers) Object.entries(opts.headers).forEach(([key, value]) => headers.append(key, value)); 70 const options: RequestInit = { 71 method, 72 headers, 73 }; 74 if (opts.data) options.body = lib_http_to_bodyinit(opts.data); 75 if (opts.data_bin) options.body = opts.data_bin; 76 return { 77 url, 78 options 79 }; 80 }; 81 82 export const lib_http_parse_response = async (res: Response): Promise<IHttpResponse> => { 83 let data: unknown = null; 84 try { 85 const res_json: unknown = await res.clone().json(); 86 if (typeof res_json === "string") { 87 try { 88 const parsed: unknown = JSON.parse(res_json); 89 data = parsed; 90 } catch { 91 data = res_json; 92 } 93 } else { 94 data = res_json; 95 } 96 } catch { } 97 if (!data) { 98 try { 99 data = await res.text(); 100 } catch { } 101 } 102 return { 103 status: res.status, 104 url: res.url, 105 data: res.ok && data ? data : null, 106 error: !res.ok && is_error_response(data) ? data.error : undefined, 107 message: res.ok && is_message_response(data) ? data : undefined, 108 headers: lib_http_parse_headers(res.headers) 109 }; 110 }; 111 112 export const http_fetch = async (opts: IHttpOpts): Promise<IHttpResponse> => { 113 const { url, options } = http_fetch_opts(opts); 114 const response = await fetch(url, options); 115 let data: unknown = null; 116 try { 117 const res_json: unknown = await response.json(); 118 if (typeof res_json === "string") { 119 try { 120 const parsed: unknown = JSON.parse(res_json); 121 data = parsed; 122 } catch { 123 data = res_json; 124 } 125 } else { 126 data = res_json; 127 } 128 } catch { } 129 if (!data) { 130 try { 131 const res_text = await response.text(); 132 data = res_text; 133 } catch { } 134 } 135 return { 136 status: response.status, 137 url: response.url, 138 data, 139 headers: lib_http_parse_headers(response.headers) 140 }; 141 };