"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.BaseRuleBuilder = void 0;
const lodash_1 = require("lodash");
const types_1 = require("../types");
const completion_checkers_1 = require("./completion-checkers");
const matchers_1 = require("./matchers");
/**
 * @class BaseRuleBuilder
 *
 * Defines the base matching & completion methods, used for both normal
 * and websocket request handling, but excluding the handling itself
 * which differs between the two cases.
 */
class BaseRuleBuilder {
    /**
     * Mock rule builders should be constructed through the Mockttp instance you're
     * using, not directly. You shouldn't ever need to call this constructor.
     */
    constructor() {
        this.matchers = [];
        this.priority = types_1.RulePriority.DEFAULT;
    }
    buildBaseRuleData() {
        return {
            priority: this.priority,
            matchers: this.matchers,
            completionChecker: this.completionChecker
        };
    }
    /**
     * Set the rule priority. Any matching rule with a higher priority will always
     * take precedence over a matching lower-priority rule, unless the higher rule
     * has an explicit completion check (like `.once()`) that has already been
     * completed.
     *
     * The RulePriority enum defines the standard values useful for most cases,
     * but any positive number may be used for advanced configurations.
     *
     * In many cases it may be simpler to use forUnmatchedRequest() to set a fallback
     * rule explicitly, rather than manually setting the priority here.
     */
    asPriority(priority) {
        this.priority = priority;
        return this;
    }
    /**
     * Match only requests sent to the given host, i.e. the full hostname plus
     * port included in the request.
     *
     * This can behave somewhat confusingly when matching against the default
     * ports for a protocol (i.e. 80/443), or when specifying a hostname here
     * without specifying the port. In those cases it's usually better to use
     * forHostname and/or forPort instead to explicit match the content you're
     * interested in.
     *
     * @category Matching
     */
    forHost(host) {
        this.matchers.push(new matchers_1.HostMatcher(host));
        return this;
    }
    /**
     * Match only requests sent to the given hostname, ignoring the port.
     *
     * @category Matching
     */
    forHostname(hostname) {
        this.matchers.push(new matchers_1.HostnameMatcher(hostname));
        return this;
    }
    /**
     * Match only requests sent to the given port.
     *
     * @category Matching
     */
    forPort(port) {
        this.matchers.push(new matchers_1.PortMatcher(port));
        return this;
    }
    /**
     * Match only requests that include the given headers.
     * @category Matching
     */
    withHeaders(headers) {
        this.matchers.push(new matchers_1.HeaderMatcher(headers));
        return this;
    }
    /**
     * Match only requests that include the given query parameters.
     * @category Matching
     */
    withQuery(query) {
        this.matchers.push(new matchers_1.QueryMatcher(query));
        return this;
    }
    /**
     * Match only requests that include the exact query string provided.
     * The query string must start with a ? or be entirely empty.
     * @category Matching
     */
    withExactQuery(query) {
        this.matchers.push(new matchers_1.ExactQueryMatcher(query));
        return this;
    }
    /**
     * Match only requests whose bodies include the given URL-encoded form data.
     * @category Matching
     */
    withForm(formData) {
        this.matchers.push(new matchers_1.FormDataMatcher(formData));
        return this;
    }
    /**
     * Match only requests whose bodies include the given multipart form data.
     *
     * This can take any number of form parts to look for. Each part is specified
     * with {@link MultipartFieldMatchCondition} object containing one or more of
     * `name` (string), `filename` (string) and `content` (string or buffer) as
     * fields to match against in the form data.
     *
     * Requests are matched if all conditions match at least one part in the
     * request's form data.
     *
     * @category Matching
     */
    withMultipartForm(...matchConditions) {
        this.matchers.push(new matchers_1.MultipartFormDataMatcher(matchConditions));
        return this;
    }
    /**
     * Match only requests whose bodies either exactly match the given string
     * (if a string is passed) or whose bodies match a regular expression
     * (if a regex is passed).
     * @category Matching
     */
    withBody(content) {
        this.matchers.push((0, lodash_1.isString)(content)
            ? new matchers_1.RawBodyMatcher(content)
            : new matchers_1.RegexBodyMatcher(content));
        return this;
    }
    /**
     * Match only requests whose bodies include the given string.
     * @category Matching
     */
    withBodyIncluding(content) {
        this.matchers.push(new matchers_1.RawBodyIncludesMatcher(content));
        return this;
    }
    /**
     * Match only requests whose bodies exactly match the given
     * object, when parsed as JSON.
     *
     * Note that this only tests that the body can be parsed
     * as JSON - it doesn't require a content-type header.
     * @category Matching
     */
    withJsonBody(json) {
        this.matchers.push(new matchers_1.JsonBodyMatcher(json));
        return this;
    }
    /**
     * Match only requests whose bodies match (contain equivalent
     * values, ignoring extra values) the given object, when
     * parsed as JSON. Matching behaviour is the same as Lodash's
     * _.isMatch method.
     *
     * Note that this only tests that the body can be parsed
     * as JSON - it doesn't require a content-type header.
     * @category Matching
     */
    withJsonBodyIncluding(json) {
        this.matchers.push(new matchers_1.JsonBodyFlexibleMatcher(json));
        return this;
    }
    /**
     * Match only requests that include the given cookies
     * @category Matching
     */
    withCookie(cookie) {
        this.matchers.push(new matchers_1.CookieMatcher(cookie));
        return this;
    }
    /**
     * Match only requests sent with the given protocol.
     * @category Matching
     */
    withProtocol(protocol) {
        this.matchers.push(new matchers_1.ProtocolMatcher(protocol));
        return this;
    }
    /**
     * Match only requests whose absolute url matches the given RegExp.
     * @category Matching
     */
    withUrlMatching(pattern) {
        this.matchers.push(new matchers_1.RegexUrlMatcher(pattern));
        return this;
    }
    /**
     * Match only requests when the callback returns true
     * @category Matching
     */
    matching(content) {
        this.matchers.push(new matchers_1.CallbackMatcher(content));
        return this;
    }
    /**
     * Run this rule forever, for all matching requests
     * @category Completion
     */
    always() {
        this.completionChecker = new completion_checkers_1.Always();
        return this;
    }
    /**
     * Run this rule only once, for the first matching request
     * @category Completion
     */
    once() {
        this.completionChecker = new completion_checkers_1.Once();
        return this;
    }
    /**
     * Run this rule twice, for the first two matching requests
     * @category Completion
     */
    twice() {
        this.completionChecker = new completion_checkers_1.Twice();
        return this;
    }
    /**
     * Run this rule three times, for the first three matching requests
     * @category Completion
     */
    thrice() {
        this.completionChecker = new completion_checkers_1.Thrice();
        return this;
    }
    /**
     * Run this rule the given number of times, for the first matching requests
     * @category Completion
     */
    times(n) {
        this.completionChecker = new completion_checkers_1.NTimes(n);
        return this;
    }
}
exports.BaseRuleBuilder = BaseRuleBuilder;
//# sourceMappingURL=base-rule-builder.js.map