<commit_before>import { Express, Router, Request, Response } from 'express';
import * as fs from 'fs';
import * as path from 'path';

export interface RouteMetadata {
    method: string;
    route: string;
    handler: Function;
}

/**
 * Base class for MVC-like controllers
 */
export class Controller {

    protected router: Router;
    protected request: Request;
    protected response: Response;

    protected name: string;

    public constructor() {
        let proto: any = (<Object>this).constructor;
        this.name = (<string>proto.name).replace('Controller', '').toLowerCase();
        this.router = Router();
        let routes: RouteMetadata[] = Reflect.getMetadata("controller:routes", this);
        if (routes) {
            routes.forEach(route => {
                let method: Function = (<any>this.router)[route.method];
                method.call(this.router, '/' + route.route, (req: Request, res: Response) => {
                    this.request = req;
                    this.response = res;
                    route.handler.call(this);
                    this.request = null;
                    this.response = null;
                });
            });
        }
    }
    protected view(): void;
    protected view(viewName: string): void;
    protected view(modelData: Object): void;
    protected view(viewName?: string | Object, modelData?: Object): void {
        if (typeof viewName === 'object') {
            modelData = viewName;
            viewName = undefined;
        }
        if (viewName === undefined) {
            viewName = this.request.route.path.substr(1);
        }
        this.response.render(this.name + '/' + (<string>viewName), modelData);
    }

    protected json(data: any) {
        this.response.json(data);
    }

    public get Router() {
        return this.router;
    }

    public get Name() {
        return this.name;
    }
}

function addRouteMetadata(target: Object, method: string, route: string, handler: Function) {
    let existingData: RouteMetadata[] = Reflect.getMetadata("controller:routes", target);
    if (existingData === undefined) {
        existingData = [];
    }
    existingData.push({ method, route: route.replace(new RegExp(method, 'i'), ''), handler });

    Reflect.defineMetadata("controller:routes", existingData, target);
}

export function HttpGet(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "get", route ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpPost(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "post", route ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpPut(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "put", route ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpPatch(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "patch", route ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpDelete(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "delete", route ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpOptions(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "options", route ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpHead(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "head", route ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function Route(route?: string) {
    let routeMethod = function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "all", route ? route : propertyKey, descriptor.value);
        return descriptor;
    }
    let routeClass = function(target: Object) {
        Reflect.defineMetadata("controller:routePrefix", route !== undefined ? route : (<any>target).name, target);
        return target;
    }
    return function() {
        if (arguments.length === 1) {
            return routeClass.apply(this, arguments);
        }
        return routeMethod.apply(this, arguments);
    }
}

export interface SetupOptions {
    controllerDir?: string;
}

export function setup(app: Express, options: SetupOptions = {}) {
    if (!options.controllerDir) {
        options.controllerDir = path.join(process.cwd(), 'controllers');
    }
    fs.readdir(options.controllerDir, (err, files) => {
        if (err) {
            return;
        }
        var re = /[A-Za-z0-9]+Controller\.js$/;
        files.filter(file => re.test(file)).forEach(file => {
            let module = require(path.join(options.controllerDir, file));
            let controllerClass = module[file.replace('.js', '')];
            let controller: Controller = new controllerClass;
            let route: string = Reflect.getMetadata("controller:routePrefix", controllerClass);
            app.use('/' + (route ? route : controller.Name), controller.Router);
        });
    });

}<commit_msg>Fixed issue with empty route parameters<commit_after>import { Express, Router, Request, Response } from 'express';
import * as fs from 'fs';
import * as path from 'path';
require('reflect-metadata');

export interface RouteMetadata {
    method: string;
    route: string;
    handler: Function;
}

/**
 * Base class for MVC-like controllers
 */
export class Controller {

    protected router: Router;
    protected request: Request;
    protected response: Response;

    protected name: string;

    public constructor() {
        let proto: any = (<Object>this).constructor;
        this.name = (<string>proto.name).replace('Controller', '').toLowerCase();
        this.router = Router();
        let routes: RouteMetadata[] = Reflect.getMetadata("controller:routes", this);
        if (routes) {
            routes.forEach(route => {
                let method: Function = (<any>this.router)[route.method];
                method.call(this.router, '/' + route.route, (req: Request, res: Response) => {
                    this.request = req;
                    this.response = res;
                    route.handler.call(this);
                    this.request = null;
                    this.response = null;
                });
            });
        }
    }
    protected view(): void;
    protected view(viewName: string): void;
    protected view(modelData: Object): void;
    protected view(viewName?: string | Object, modelData?: Object): void {
        if (typeof viewName === 'object') {
            modelData = viewName;
            viewName = undefined;
        }
        if (viewName === undefined) {
            viewName = this.request.route.path.substr(1);
        }
        this.response.render(this.name + '/' + (<string>viewName), modelData);
    }

    protected json(data: any) {
        this.response.json(data);
    }

    public get Router() {
        return this.router;
    }

    public get Name() {
        return this.name;
    }
}

function addRouteMetadata(target: Object, method: string, route: string, handler: Function) {
    let existingData: RouteMetadata[] = Reflect.getMetadata("controller:routes", target);
    if (existingData === undefined) {
        existingData = [];
    }
    existingData.push({ method, route: route.replace(new RegExp(method, 'i'), ''), handler });

    Reflect.defineMetadata("controller:routes", existingData, target);
}

export function HttpGet(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "get", route !== undefined ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpPost(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "post", route !== undefined ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpPut(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "put", route !== undefined ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpPatch(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "patch", route !== undefined ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpDelete(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "delete", route !== undefined ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpOptions(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "options", route !== undefined ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function HttpHead(route?: string) {
    return function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "head", route !== undefined ? route : propertyKey, descriptor.value);
        return descriptor;
    }
}

export function Route(route?: string) {
    let routeMethod = function(target: Object, propertyKey: string, descriptor: TypedPropertyDescriptor<any>) {
        addRouteMetadata(target, "all", route !== undefined ? route : propertyKey, descriptor.value);
        return descriptor;
    }
    let routeClass = function(target: Object) {
        Reflect.defineMetadata("controller:routePrefix", route !== undefined ? route : (<any>target).name, target);
        return target;
    }
    return function() {
        if (arguments.length === 1) {
            return routeClass.apply(this, arguments);
        }
        return routeMethod.apply(this, arguments);
    }
}

export interface SetupOptions {
    controllerDir?: string;
}

export function setup(app: Express, options: SetupOptions = {}) {
    if (!options.controllerDir) {
        options.controllerDir = path.join(process.cwd(), 'controllers');
    }
    fs.readdir(options.controllerDir, (err, files) => {
        if (err) {
            return;
        }
        var re = /[A-Za-z0-9]+Controller\.js$/;
        files.filter(file => re.test(file)).forEach(file => {
            let module = require(path.join(options.controllerDir, file));
            let controllerClass = module[file.replace('.js', '')];
            let controller: Controller = new controllerClass;
            let route: string = Reflect.getMetadata("controller:routePrefix", controllerClass);
            app.use('/' + (route !== undefined ? route : controller.Name), controller.Router);
        });
    });

}
{'fraction_non_alphanumeric': 0.12597547380156077, 'fraction_numerical': 0.0006860475087899837, 'mean_word_length': 2.953220338983051, 'pattern_counts': {'":': 0, '<': 29, '<?xml version=': 0, '>': 39, 'https://': 0, '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': '5148453', 'n_tokens_mistral': 3061, 'n_tokens_neox': 3023, 'n_words': 785}