web_lib

Common web application libraries
git clone https://radroots.dev/git/web_lib.git
Log | Files | Refs | LICENSE

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 };