const g = (typeof globalThis !== 'undefined' && globalThis) || (typeof self !== 'undefined' && self) || (typeof global !== 'undefined' && global) || {};
const support = {
    searchParams: 'URLSearchParams' in g,
    iterable: 'Symbol' in g && 'iterator' in Symbol,
    blob: 'FileReader' in g &&
        'Blob' in g &&
        (() => {
            try {
                new Blob();
                return true;
            }
            catch (e) {
                return false;
            }
        })(),
    formData: 'FormData' in g,
    arrayBuffer: 'ArrayBuffer' in g,
};
function isDataView(obj) {
    return obj && DataView.prototype.isPrototypeOf(obj);
}
let isArrayBufferView;
if (support.arrayBuffer) {
    const viewClasses = ['[object Int8Array]', '[object Uint8Array]', '[object Uint8ClampedArray]', '[object Int16Array]', '[object Uint16Array]', '[object Int32Array]', '[object Uint32Array]', '[object Float32Array]', '[object Float64Array]'];
    isArrayBufferView =
        ArrayBuffer.isView ||
            ((obj) => {
                return obj && viewClasses.indexOf(Object.prototype.toString.call(obj)) > -1;
            });
}
function normalizeName(name) {
    if (typeof name !== 'string') {
        name = String(name);
    }
    if (/[^a-z0-9\-#$%&'*+.^_`|~!]/i.test(name) || name === '') {
        throw new TypeError('Invalid character in header field name: "' + name + '"');
    }
    return name.toLowerCase();
}
function normalizeValue(value) {
    if (typeof value !== 'string') {
        value = String(value);
    }
    return value;
}
// Build a destructive iterator for the value list
function iteratorFor(items) {
    const iterator = {
        next: () => {
            const value = items.shift();
            return { done: value === undefined, value };
        },
    };
    if (support.iterable) {
        iterator[Symbol.iterator] = () => iterator;
    }
    return iterator;
}
export class Headers {
    constructor(headers) {
        this.map = {};
        if (headers instanceof Headers) {
            headers.forEach((value, name) => {
                this.append(name, value);
            });
        }
        else if (Array.isArray(headers)) {
            headers.forEach((header) => {
                if (header.length !== 2) {
                    throw new TypeError('Headers constructor: expected name/value pair to be length 2, found ' + header.length);
                }
                this.append(header[0], header[1]);
            });
        }
        else if (headers) {
            Object.getOwnPropertyNames(headers).forEach((name) => {
                this.append(name, headers[name]);
            });
        }
    }
    append(name, value) {
        name = normalizeName(name);
        value = normalizeValue(value);
        const oldValue = this.map[name];
        this.map[name] = oldValue ? oldValue + ', ' + value : value;
    }
    delete(name) {
        delete this.map[normalizeName(name)];
    }
    get(name) {
        name = normalizeName(name);
        return this.has(name) ? this.map[name] : null;
    }
    has(name) {
        return Object.prototype.hasOwnProperty.call(this.map, normalizeName(name));
    }
    set(name, value) {
        this.map[normalizeName(name)] = normalizeValue(value);
    }
    forEach(callback, thisArg) {
        for (const name in this.map) {
            if (Object.prototype.hasOwnProperty.call(this.map, name)) {
                callback.call(thisArg, this.map[name], name, this);
            }
        }
    }
    keys() {
        const items = [];
        this.forEach((_, name) => items.push(name));
        return iteratorFor(items);
    }
    values() {
        const items = [];
        this.forEach((value) => items.push(value));
        return iteratorFor(items);
    }
    entries() {
        const items = [];
        this.forEach((value, name) => items.push([name, value]));
        return iteratorFor(items);
    }
    [Symbol.iterator]() {
        return this.entries();
    }
}
// Body mixin
export class Body {
    constructor() {
        this.bodyUsed = false;
    }
    _initBody(body) {
        // Ensure bodyUsed property exists
        this.bodyUsed = this.bodyUsed;
        this._bodyInit = body;
        if (!body) {
            this._noBody = true;
            this._bodyText = '';
        }
        else if (typeof body === 'string') {
            this._bodyText = body;
        }
        else if (support.blob && Blob.prototype.isPrototypeOf(body)) {
            this._bodyBlob = body;
        }
        else if (support.formData && FormData.prototype.isPrototypeOf(body)) {
            this._bodyFormData = body;
        }
        else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
            this._bodyText = body.toString();
        }
        else if (support.arrayBuffer && support.blob && isDataView(body)) {
            // @ts-ignore
            this._bodyArrayBuffer = bufferClone(body.buffer);
            this._bodyInit = new Blob([this._bodyArrayBuffer]);
        }
        else if (support.arrayBuffer && (ArrayBuffer.prototype.isPrototypeOf(body) || isArrayBufferView(body))) {
            this._bodyArrayBuffer = bufferClone(body);
        }
        else {
            this._bodyText = body = Object.prototype.toString.call(body);
        }
        // Set Content-Type header if not set
        if (!this.headers.get('content-type')) {
            if (typeof body === 'string') {
                this.headers.set('content-type', 'text/plain;charset=UTF-8');
            }
            else if (this._bodyBlob && this._bodyBlob.type) {
                this.headers.set('content-type', this._bodyBlob.type);
            }
            else if (support.searchParams && URLSearchParams.prototype.isPrototypeOf(body)) {
                this.headers.set('content-type', 'application/x-www-form-urlencoded;charset=UTF-8');
            }
        }
    }
    blob() {
        const rejected = consumed(this);
        if (rejected) {
            return rejected;
        }
        if (this._bodyBlob) {
            return Promise.resolve(this._bodyBlob);
        }
        else if (this._bodyArrayBuffer) {
            return Promise.resolve(new Blob([this._bodyArrayBuffer]));
        }
        else if (this._bodyFormData) {
            throw new Error('could not read FormData body as blob');
        }
        else {
            return Promise.resolve(new Blob([this._bodyText]));
        }
    }
    arrayBuffer() {
        if (this._bodyArrayBuffer) {
            const consumedResult = consumed(this);
            if (consumedResult) {
                return consumedResult;
            }
            else if (ArrayBuffer.isView(this._bodyArrayBuffer)) {
                return Promise.resolve(this._bodyArrayBuffer.buffer.slice(this._bodyArrayBuffer.byteOffset, this._bodyArrayBuffer.byteOffset + this._bodyArrayBuffer.byteLength));
            }
            else {
                return Promise.resolve(this._bodyArrayBuffer);
            }
        }
        else if (support.blob) {
            // @ts-ignore
            return this.blob().then(readBlobAsArrayBuffer);
        }
        else {
            throw new Error('could not read as ArrayBuffer');
        }
    }
    text() {
        const rejected = consumed(this);
        if (rejected) {
            return rejected;
        }
        if (this._bodyBlob) {
            return readBlobAsText(this._bodyBlob);
        }
        else if (this._bodyArrayBuffer) {
            return Promise.resolve(readArrayBufferAsText(this._bodyArrayBuffer));
        }
        else if (this._bodyFormData) {
            throw new Error('could not read FormData body as text');
        }
        else {
            return Promise.resolve(this._bodyText);
        }
    }
    formData() {
        return this.text().then(decode);
    }
    json() {
        return this.text().then(JSON.parse);
    }
}
// Helper functions for Body
function consumed(body) {
    if (body._noBody)
        return;
    if (body.bodyUsed) {
        return Promise.reject(new TypeError('Already read'));
    }
    body.bodyUsed = true;
}
function fileReaderReady(reader) {
    return new Promise((resolve, reject) => {
        reader.onload = () => resolve(reader.result);
        reader.onerror = () => reject(reader.error);
    });
}
function readBlobAsArrayBuffer(blob) {
    const reader = new FileReader();
    const promise = fileReaderReady(reader);
    reader.readAsArrayBuffer(blob);
    return promise;
}
function readBlobAsText(blob) {
    const reader = new FileReader();
    const promise = fileReaderReady(reader);
    const match = /charset=([A-Za-z0-9_-]+)/.exec(blob.type);
    const encoding = match ? match[1] : 'utf-8';
    reader.readAsText(blob, encoding);
    return promise;
}
function readArrayBufferAsText(buf) {
    const view = new Uint8Array(buf);
    const chars = new Array(view.length);
    for (let i = 0; i < view.length; i++) {
        chars[i] = String.fromCharCode(view[i]);
    }
    return chars.join('');
}
function bufferClone(buf) {
    if (buf.slice) {
        return buf.slice(0);
    }
    else {
        const view = new Uint8Array(buf.byteLength);
        view.set(new Uint8Array(buf));
        return view.buffer;
    }
}
// HTTP methods whose capitalization should be normalized
const methods = ['CONNECT', 'DELETE', 'GET', 'HEAD', 'OPTIONS', 'PATCH', 'POST', 'PUT', 'TRACE'];
function normalizeMethod(method) {
    const upcased = method.toUpperCase();
    return methods.indexOf(upcased) > -1 ? upcased : method;
}
export class Request extends Body {
    constructor(input, options = {}) {
        super();
        let body = options.body;
        if (input instanceof Request) {
            if (input.bodyUsed) {
                throw new TypeError('Already read');
            }
            this.url = input.url;
            this.credentials = input.credentials;
            if (!options.headers) {
                this.headers = new Headers(input.headers);
            }
            this.method = input.method;
            this.mode = input.mode;
            this.signal = input.signal;
            if (!body && input._bodyInit != null) {
                body = input._bodyInit;
                input.bodyUsed = true;
            }
        }
        else {
            this.url = String(input);
        }
        this.credentials = options.credentials || this.credentials || 'same-origin';
        if (options.headers || !this.headers) {
            this.headers = new Headers(options.headers);
        }
        this.method = normalizeMethod(options.method || this.method || 'GET');
        this.mode = options.mode || this.mode || null;
        this.signal = options.signal || this.signal || ('AbortController' in g ? new AbortController().signal : undefined);
        this.referrer = null;
        if ((this.method === 'GET' || this.method === 'HEAD') && body) {
            throw new TypeError('Body not allowed for GET or HEAD requests');
        }
        this._initBody(body);
        if (this.method === 'GET' || this.method === 'HEAD') {
            if (options.cache === 'no-store' || options.cache === 'no-cache') {
                const reParamSearch = /([?&])_=[^&]*/;
                if (reParamSearch.test(this.url)) {
                    this.url = this.url.replace(reParamSearch, '$1_=' + new Date().getTime());
                }
                else {
                    const reQueryString = /\?/;
                    this.url += (reQueryString.test(this.url) ? '&' : '?') + '_=' + new Date().getTime();
                }
            }
        }
    }
    clone() {
        return new Request(this, { body: this._bodyInit });
    }
}
// Decode URL-encoded form data
function decode(body) {
    const form = new FormData();
    body
        .trim()
        .split('&')
        .forEach((bytes) => {
        if (bytes) {
            const split = bytes.split('=');
            const name = split.shift().replace(/\+/g, ' ');
            const value = split.join('=').replace(/\+/g, ' ');
            form.append(decodeURIComponent(name), decodeURIComponent(value));
        }
    });
    return form;
}
// Parse raw headers string into Headers
function parseHeaders(rawHeaders) {
    const headers = new Headers();
    const preProcessed = rawHeaders.replace(/\r?\n[\t ]+/g, ' ');
    preProcessed
        .split('\r')
        .map((header) => (header.indexOf('\n') === 0 ? header.substr(1) : header))
        .forEach((line) => {
        const parts = line.split(':');
        const key = parts.shift().trim();
        if (key) {
            const value = parts.join(':').trim();
            try {
                headers.append(key, value);
            }
            catch (err) {
                console.warn('Response ' + err.message);
            }
        }
    });
    return headers;
}
const redirectStatuses = [301, 302, 303, 307, 308];
export class Response extends Body {
    constructor(bodyInit, options = {}) {
        super();
        this.type = 'default';
        this.status = options.status === undefined ? 200 : options.status;
        if (this.status < 200 || this.status > 599) {
            throw new RangeError(`Failed to construct 'Response': The status provided (${this.status}) is outside the range [200, 599].`);
        }
        this.ok = this.status >= 200 && this.status < 300;
        this.statusText = options.statusText === undefined ? '' : String(options.statusText);
        this.headers = new Headers(options.headers);
        this.url = options.url || '';
        this._initBody(bodyInit);
    }
    clone() {
        return new Response(this._bodyInit, {
            status: this.status,
            statusText: this.statusText,
            headers: new Headers(this.headers),
            url: this.url,
        });
    }
    static error() {
        const response = new Response(null, { status: 200, statusText: '' });
        response.ok = false;
        response.status = 0;
        response.type = 'error';
        return response;
    }
    static redirect(url, status) {
        if (!redirectStatuses.includes(status)) {
            throw new RangeError('Invalid status code');
        }
        return new Response(null, { status, headers: { location: url } });
    }
}
// DOMException polyfill
export let DOMException = g.DOMException;
try {
    new g.DOMException();
}
catch (err) {
    DOMException = class {
        constructor(message, name) {
            this.message = message;
            this.name = name;
            const error = new Error(message);
            this.stack = error.stack;
        }
    };
}
// fetch function
export function fetch(input, init) {
    return new Promise((resolve, reject) => {
        const request = new Request(input, init);
        if (request.signal && request.signal.aborted) {
            return reject(new DOMException('Aborted', 'AbortError'));
        }
        const xhr = new XMLHttpRequest();
        function abortXhr() {
            xhr.abort();
        }
        xhr.onload = function () {
            const options = {
                statusText: xhr.statusText,
                headers: parseHeaders(xhr.getAllResponseHeaders() || ''),
            };
            // Local file handling
            if (request.url.startsWith('file://') && (xhr.status < 200 || xhr.status > 599)) {
                options.status = 200;
            }
            else {
                options.status = xhr.status;
            }
            options.url = 'responseURL' in xhr ? xhr.responseURL : options.headers.get('X-Request-URL');
            // @ts-ignore
            const body = 'response' in xhr ? xhr.response : xhr.responseText;
            setTimeout(() => resolve(new Response(body, options)), 0);
        };
        xhr.onerror = function () {
            setTimeout(() => reject(new TypeError('Network request failed')), 0);
        };
        xhr.ontimeout = function () {
            setTimeout(() => reject(new TypeError('Network request timed out')), 0);
        };
        xhr.onabort = function () {
            setTimeout(() => reject(new DOMException('Aborted', 'AbortError')), 0);
        };
        function fixUrl(url) {
            try {
                return url === '' && g.location.href ? g.location.href : url;
            }
            catch (e) {
                return url;
            }
        }
        xhr.open(request.method, fixUrl(request.url), true);
        if (request.credentials === 'include') {
            xhr.withCredentials = true;
        }
        else if (request.credentials === 'omit') {
            xhr.withCredentials = false;
        }
        if ('responseType' in xhr) {
            if (support.blob) {
                xhr.responseType = 'blob';
            }
            else if (support.arrayBuffer) {
                xhr.responseType = 'arraybuffer';
            }
        }
        if (init && typeof init.headers === 'object' && !(init.headers instanceof Headers) && !(g.Headers && init.headers instanceof g.Headers)) {
            const names = [];
            Object.getOwnPropertyNames(init.headers).forEach((name) => {
                names.push(normalizeName(name));
                xhr.setRequestHeader(name, normalizeValue(init.headers[name]));
            });
            request.headers.forEach((value, name) => {
                if (!names.includes(name)) {
                    xhr.setRequestHeader(name, value);
                }
            });
        }
        else {
            request.headers.forEach((value, name) => xhr.setRequestHeader(name, value));
        }
        if (request.signal) {
            request.signal.addEventListener('abort', abortXhr);
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    request.signal.removeEventListener('abort', abortXhr);
                }
            };
        }
        xhr.send(typeof request._bodyInit === 'undefined' ? null : request._bodyInit);
    });
}
// Attach polyfill to globals
fetch.polyfill = true;
if (!g.fetch) {
    g.fetch = fetch;
    g.Headers = Headers;
    g.Request = Request;
    g.Response = Response;
}
//# sourceMappingURL=index.js.map