function joinPaths(prefix, path) {
    if (!prefix)
        return path;
    if (!path)
        return prefix;
    return `${prefix.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`;
}
function extractPathParamNames(apiPath) {
    const names = [];
    const matcher = /\{([A-Za-z][A-Za-z0-9_]*)\}/g;
    let match;
    while ((match = matcher.exec(apiPath)) !== null)
        names.push(match[1]);
    return names;
}
function substitutePath(apiPath, params) {
    return apiPath.replace(/\{([A-Za-z][A-Za-z0-9_]*)\}/g, (_, name) => {
        const value = params[name];
        if (value === undefined)
            throw new Error(`Missing path param: ${name}`);
        return encodeURIComponent(value);
    });
}
async function readStream(stream) {
    const chunks = [];
    for await (const chunk of stream) {
        chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(String(chunk)));
    }
    return Buffer.concat(chunks).toString('utf8');
}
export function buildRoutes(manifest) {
    const routes = [];
    for (const mod of manifest.modules) {
        for (const action of mod.actions) {
            const apiPath = joinPaths(action.pathPrefix || mod.pathPrefix, action.path);
            const paramNames = extractPathParamNames(apiPath);
            const paramSuffix = paramNames.map((name) => `/:${name}`).join('');
            const routeUrl = `/api/${mod.domain}/${action.name}${paramSuffix}`;
            routes.push({
                method: action.method,
                routeUrl,
                domain: mod.domain,
                action: action.name,
                description: action.description,
                apiPath,
                responseMode: action.responseMode ?? 'json',
                call: async (client, { params, query, body }) => {
                    const concretePath = substitutePath(apiPath, params);
                    if (action.responseMode === 'ndjson') {
                        if (action.method === 'GET') {
                            return client.get(concretePath, { params: query });
                        }
                        return readStream(await client.postStream(concretePath, body));
                    }
                    if (action.method === 'GET') {
                        return client.get(concretePath, { params: query });
                    }
                    return client.post(concretePath, body);
                },
            });
        }
    }
    return routes;
}
//# sourceMappingURL=router.js.map