<commit_before>import { mix } from "./mix"
import conf from "./config"
import { resolver, WretcherError, ResponseChain } from "./resolver"
import { ConfiguredMiddleware } from "./middleware"

export type WretcherOptions = RequestInit & {
    [key: string]: any
}

/**
 * The Wretcher class used to perform easy fetch requests.
 *
 * Immutability : almost every method of this class return a fresh Wretcher object.
 */
export class Wretcher {

    protected constructor(
        public _url: string,
        public _options: WretcherOptions,
        public _catchers: Map<number | string, (error: WretcherError, originalRequest: Wretcher) => void> = new Map(),
        public _resolvers: Array<(resolver: ResponseChain, originalRequest: Wretcher) => any> = [],
        public _middlewares: ConfiguredMiddleware[] = []) {}

    static factory(url = "", opts: WretcherOptions = {}) { return new Wretcher(url, opts) }
    private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,
                resolvers = this._resolvers, middlewares = this._middlewares } = {}) {
        return new Wretcher(url, options, catchers, resolvers, middlewares)
    }

    /**
     * Sets the default fetch options used for every subsequent fetch call.
     * @param opts New default options
     * @param mixin If true, mixes in instead of replacing the existing options
     */
    defaults(opts: WretcherOptions, mixin = false) {
        conf.defaults = mixin ? mix(conf.defaults, opts) : opts
        return this
    }

    /**
     * Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error.
     *
     * Persists for every subsequent requests.
     *
     * Default is "text".
     */
    errorType(method: "text" | "json") {
        conf.errorType = method
        return this
    }

    /**
     * Sets the non-global polyfills which will be used for every subsequent calls.
     *
     * Needed for libraries like [fetch-ponyfill](https://github.com/qubyte/fetch-ponyfill).
     *
     * @param polyfills An object containing the polyfills.
     */
    polyfills(polyfills: Partial<typeof conf.polyfills>) {
        conf.polyfills = { ...conf.polyfills, ...polyfills }
        return this
    }

    /**
     * Returns a new Wretcher object with the argument url appended and the same options.
     * @param url String url
     * @param replace Boolean If true, replaces the current url instead of appending
     */
    url(url: string, replace = false) {
        if(replace)
            return this.selfFactory({ url })
        const split = this._url.split("?")
        return this.selfFactory({
            url: split.length > 1 ?
                split[0] + url + split[1] :
                this._url + url
        })<commit_msg>:bug: Fix .url call when the url contains query parameters<commit_after>import { mix } from "./mix"
import conf from "./config"
import { resolver, WretcherError, ResponseChain } from "./resolver"
import { ConfiguredMiddleware } from "./middleware"

export type WretcherOptions = RequestInit & {
    [key: string]: any
}

/**
 * The Wretcher class used to perform easy fetch requests.
 *
 * Immutability : almost every method of this class return a fresh Wretcher object.
 */
export class Wretcher {

    protected constructor(
        public _url: string,
        public _options: WretcherOptions,
        public _catchers: Map<number | string, (error: WretcherError, originalRequest: Wretcher) => void> = new Map(),
        public _resolvers: Array<(resolver: ResponseChain, originalRequest: Wretcher) => any> = [],
        public _middlewares: ConfiguredMiddleware[] = []) {}

    static factory(url = "", opts: WretcherOptions = {}) { return new Wretcher(url, opts) }
    private selfFactory({ url = this._url, options = this._options, catchers = this._catchers,
                resolvers = this._resolvers, middlewares = this._middlewares } = {}) {
        return new Wretcher(url, options, catchers, resolvers, middlewares)
    }

    /**
     * Sets the default fetch options used for every subsequent fetch call.
     * @param opts New default options
     * @param mixin If true, mixes in instead of replacing the existing options
     */
    defaults(opts: WretcherOptions, mixin = false) {
        conf.defaults = mixin ? mix(conf.defaults, opts) : opts
        return this
    }

    /**
     * Sets the method (text, json ...) used to parse the data contained in the response body in case of an HTTP error.
     *
     * Persists for every subsequent requests.
     *
     * Default is "text".
     */
    errorType(method: "text" | "json") {
        conf.errorType = method
        return this
    }

    /**
     * Sets the non-global polyfills which will be used for every subsequent calls.
     *
     * Needed for libraries like [fetch-ponyfill](https://github.com/qubyte/fetch-ponyfill).
     *
     * @param polyfills An object containing the polyfills.
     */
    polyfills(polyfills: Partial<typeof conf.polyfills>) {
        conf.polyfills = { ...conf.polyfills, ...polyfills }
        return this
    }

    /**
     * Returns a new Wretcher object with the argument url appended and the same options.
     * @param url String url
     * @param replace Boolean If true, replaces the current url instead of appending
     */
    url(url: string, replace = false) {
        if(replace)
            return this.selfFactory({ url })
        const split = this._url.split("?")
        return this.selfFactory({
            url: split.length > 1 ?
                split[0] + url + "?" + split[1] :
                this._url + url
        })
{'fraction_non_alphanumeric': 0.10467784642541925, 'fraction_numerical': 0.001059135039717564, 'mean_word_length': 2.543464665415885, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 15, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3987310', 'n_tokens_mistral': 1593, 'n_tokens_neox': 1552, 'n_words': 535}