"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
Object.defineProperty(exports, "autoImplementMethods", {
    enumerable: true,
    get: function() {
        return autoImplementMethods;
    }
});
const _http = require("../../../web/http");
const AUTOMATIC_ROUTE_METHODS = [
    'HEAD',
    'OPTIONS'
];
function handleMethodNotAllowedResponse() {
    return new Response(null, {
        status: 405
    });
}
function autoImplementMethods(handlers) {
    // Loop through all the HTTP methods to create the initial methods object.
    // Each of the methods will be set to the 405 response handler.
    const methods = _http.HTTP_METHODS.reduce((acc, method)=>({
            ...acc,
            // If the userland module implements the method, then use it. Otherwise,
            // use the 405 response handler.
            [method]: handlers[method] ?? handleMethodNotAllowedResponse
        }), {});
    // Get all the methods that could be automatically implemented that were not
    // implemented by the userland module.
    const implemented = new Set(_http.HTTP_METHODS.filter((method)=>handlers[method]));
    const missing = AUTOMATIC_ROUTE_METHODS.filter((method)=>!implemented.has(method));
    // Loop over the missing methods to automatically implement them if we can.
    for (const method of missing){
        // If the userland module doesn't implement the HEAD method, then
        // we'll automatically implement it by calling the GET method (if it
        // exists).
        if (method === 'HEAD') {
            if (handlers.GET) {
                // Implement the HEAD method by calling the GET method.
                methods.HEAD = handlers.GET;
                // Mark it as implemented.
                implemented.add('HEAD');
            }
            continue;
        }
        // If OPTIONS is not provided then implement it.
        if (method === 'OPTIONS') {
            // TODO: check if HEAD is implemented, if so, use it to add more headers
            // Get all the methods that were implemented by the userland module.
            const allow = [
                'OPTIONS',
                ...implemented
            ];
            // If the list of methods doesn't include HEAD, but it includes GET, then
            // add HEAD as it's automatically implemented.
            if (!implemented.has('HEAD') && implemented.has('GET')) {
                allow.push('HEAD');
            }
            // Sort and join the list with commas to create the `Allow` header. See:
            // https://httpwg.org/specs/rfc9110.html#field.allow
            const headers = {
                Allow: allow.sort().join(', ')
            };
            // Implement the OPTIONS method by returning a 204 response with the
            // `Allow` header.
            methods.OPTIONS = ()=>new Response(null, {
                    status: 204,
                    headers
                });
            // Mark this method as implemented.
            implemented.add('OPTIONS');
            continue;
        }
        throw Object.defineProperty(new Error(`Invariant: should handle all automatic implementable methods, got method: ${method}`), "__NEXT_ERROR_CODE", {
            value: "E211",
            enumerable: false,
            configurable: true
        });
    }
    return methods;
}

//# sourceMappingURL=auto-implement-methods.js.map