fetch.ts 2.5 KB
Newer Older
1
import queryString from 'query-string';
2

3 4
const API_TOKEN_KEY: string = import.meta.env.SNOWPACK_PUBLIC_API_TOKEN_KEY;
const API_URL: string = import.meta.env.SNOWPACK_PUBLIC_API_URL;
5

6 7
const API_TOKEN_HEADER = 'X-VisualDL-Instance-ID';

8
const instanceId = API_TOKEN_KEY ? queryString.parse(window.location.search)[API_TOKEN_KEY] : '';
9 10 11 12 13

export function getApiToken(): string | string[] | null {
    return instanceId ?? null;
}

14
function addApiToken(options?: RequestInit): RequestInit | undefined {
15 16
    const id = getApiToken();
    if (!API_TOKEN_KEY || !id) {
17 18 19
        return options;
    }
    const {headers, ...rest} = options || {};
20 21 22 23 24 25
    const newHeaders = new Headers(headers);
    if (Array.isArray(id)) {
        id.forEach(value => newHeaders.append(API_TOKEN_HEADER, value));
    } else {
        newHeaders.append(API_TOKEN_HEADER, id);
    }
26 27
    return {
        ...rest,
28
        headers: newHeaders
29 30 31 32
    };
}

export const fetcher = async <T = unknown>(url: string, options?: RequestInit): Promise<T> => {
33
    const res = await fetch(API_URL + url, addApiToken(options));
34 35 36 37 38
    const response = await res.json();

    return response && 'data' in response ? response.data : response;
};

39 40 41
export type BlobResponse = {
    data: Blob;
    type: string | null;
42
    filename: string | null;
43 44
};

45
export const blobFetcher = async (url: string, options?: RequestInit): Promise<BlobResponse> => {
46
    const res = await fetch(API_URL + url, addApiToken(options));
47
    const data = await res.blob();
48
    const disposition = res.headers.get('Content-Disposition');
P
Peter Pan 已提交
49 50 51 52 53 54 55 56 57 58 59
    // support safari
    if (!data.arrayBuffer) {
        data.arrayBuffer = async () =>
            new Promise<ArrayBuffer>((resolve, reject) => {
                const fileReader = new FileReader();
                fileReader.addEventListener('load', e =>
                    e.target ? resolve(e.target.result as ArrayBuffer) : reject()
                );
                fileReader.readAsArrayBuffer(data);
            });
    }
60 61 62 63 64 65 66 67
    let filename: string | null = null;
    if (disposition && disposition.indexOf('attachment') !== -1) {
        const matches = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/.exec(disposition);
        if (matches != null && matches[1]) {
            filename = matches[1].replace(/['"]/g, '');
        }
    }
    return {data, type: res.headers.get('Content-Type'), filename};
P
Peter Pan 已提交
68 69
};

70
export const cycleFetcher = async <T = unknown>(urls: string[], options?: RequestInit): Promise<T[]> => {
P
Peter Pan 已提交
71
    return await Promise.all(urls.map(url => fetcher<T>(url, options)));
72
};