"use strict";
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License.
Object.defineProperty(exports, "__esModule", { value: true });
exports.extractRoutes = extractRoutes;
exports.expressPathToAzureRoute = expressPathToAzureRoute;
exports.generateFunctionName = generateFunctionName;
/** Walk the Express router stack and return all registered routes. */
function extractRoutes(expressApp, basePath = '') {
    const routes = [];
    const seen = new Set();
    const stack = expressApp?._router?.stack;
    if (!Array.isArray(stack))
        return routes;
    processStack(stack, basePath, routes, seen);
    return routes;
}
function processStack(stack, prefix, routes, seen) {
    let idx = 0;
    while (idx < stack.length) {
        const layer = stack[idx];
        idx++;
        const route = layer.route;
        const handle = layer.handle;
        if (route) {
            const methods = getMethods(route.methods);
            const fullPath = cleanPath(prefix + route.path);
            const key = methods.sort().join(',') + ':' + fullPath;
            if (!seen.has(key)) {
                seen.add(key);
                routes.push({
                    expressPath: fullPath,
                    azureFunctionsRoute: expressPathToAzureRoute(fullPath),
                    methods,
                    functionName: generateFunctionName(fullPath, methods),
                });
            }
        }
        else if (handle && Array.isArray(handle.stack)) {
            const nestedPrefix = getPrefix(layer, layer.regexp);
            processStack(handle.stack, prefix + nestedPrefix, routes, seen);
        }
    }
}
function getPrefix(layer, regexp) {
    if (typeof layer.path === 'string' && layer.path !== '/')
        return layer.path;
    if (regexp) {
        const m = regexp.source.match(/^\^\\?\/?([\w\-\/]*)/);
        if (m && m[1])
            return '/' + m[1];
    }
    return '';
}
function getMethods(methods) {
    if (!methods)
        return ['GET'];
    const result = [];
    const keys = Object.keys(methods);
    let i = 0;
    while (i < keys.length) {
        if (methods[keys[i]] && keys[i] !== '_all')
            result.push(keys[i].toUpperCase());
        i++;
    }
    return result;
}
/** Convert Express path params to Azure Functions route format. */
function expressPathToAzureRoute(expressPath) {
    let route = expressPath.startsWith('/') ? expressPath.substring(1) : expressPath;
    route = route.replace(/:(\w+)/g, '{$1}');
    route = route.replace(/\(\.\*\)/g, '{*path}');
    route = route.replace(/\*(\w*)/g, (_m, name) => '{*' + (name || 'path') + '}');
    return route;
}
/** Generate a unique Azure Function name from route + methods. */
function generateFunctionName(expressPath, methods) {
    let p = expressPath.replace(/^\/|\/$/g, '');
    p = p.replace(/:(\w+)/g, '$1');
    p = p.replace(/\//g, '-');
    p = p.replace(/\*/g, 'wildcard').replace(/\(\.\*\)/g, 'wildcard');
    p = p.replace(/[^a-zA-Z0-9-]/g, '');
    return methods.join('-') + '-' + p;
}
function cleanPath(p) {
    let n = p.replace(/\/+/g, '/');
    if (!n.startsWith('/'))
        n = '/' + n;
    if (n.length > 1 && n.endsWith('/'))
        n = n.slice(0, -1);
    return n;
}
//# sourceMappingURL=routeExtractor.js.map