Skip to content

Commit

Permalink
Add custom http methods
Browse files Browse the repository at this point in the history
  • Loading branch information
rajkumardusad committed Mar 3, 2023
1 parent a01232d commit f061b6f
Show file tree
Hide file tree
Showing 15 changed files with 322 additions and 286 deletions.
1 change: 1 addition & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ export declare class Router {
unsubscribe(path: string, ...callbacks: any[]): this;
view(path: string, ...callbacks: any[]): this;
any(methods: string | string[], path: string, ...callbacks: any[]): this;
add(method: string, path: string, ...callbacks: any[]): this;
all(path: string, ...callbacks: any[]): this;
use(...callbacks: any): this;
group(path: string, callback: any): this;
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@routejs/router",
"version": "2.1.1",
"version": "2.1.2",
"description": "Fast and lightweight http routing engine for nodejs",
"main": "index.mjs",
"type": "module",
Expand Down
3 changes: 1 addition & 2 deletions src/methods.cjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
const nodePath = require("node:path");
const Route = require("./route.cjs");
const Router = require("./router.cjs");
const supportedMethod = require("./supported-method.cjs");

module.exports.use = function use(...callbacks) {
if (typeof callbacks[0] === "string" || callbacks[0] instanceof String) {
Expand All @@ -24,7 +23,7 @@ module.exports.path = function path(method, path, ...callbacks) {
};

module.exports.all = function all(path, ...callbacks) {
return setRoute({ method: supportedMethod, path, callbacks });
return setRoute({ path, callbacks });
};

module.exports.domain = function domain(host, routes) {
Expand Down
3 changes: 1 addition & 2 deletions src/methods.mjs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import nodePath from "node:path";
import Route from "./route.mjs";
import Router from "./router.mjs";
import supportedMethod from "./supported-method.mjs";

export function use(...callbacks) {
if (typeof callbacks[0] === "string" || callbacks[0] instanceof String) {
Expand All @@ -24,7 +23,7 @@ export function path(method, path, ...callbacks) {
}

export function all(path, ...callbacks) {
return setRoute({ method: supportedMethod, path, callbacks });
return setRoute({ path, callbacks });
}

export function domain(host, routes) {
Expand Down
125 changes: 60 additions & 65 deletions src/route.cjs
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
const supportedMethod = require("./supported-method.cjs");

module.exports = class Route {
host = null;
hostRegexp = null;
Expand Down Expand Up @@ -28,19 +26,9 @@ module.exports = class Route {
"Error: route method accepts only string or array of string as an argument"
);
}
if (!supportedMethod.includes(e.toUpperCase())) {
throw new TypeError(
`Error: ${e.toUpperCase()} method is not supported`
);
}
return e.toUpperCase();
});
} else if (typeof method === "string" || method instanceof String) {
if (!supportedMethod.includes(method.toUpperCase())) {
throw new TypeError(
`Error: ${method.toUpperCase()} method is not supported`
);
}
method = method.toUpperCase();
} else {
throw new TypeError(
Expand Down Expand Up @@ -73,15 +61,17 @@ module.exports = class Route {
: this.#compileMiddlewareRegExp("/");
this.group = group;
this.name = name;
this.params = path ? this.#getParams(path) : this.#getParams(group);
this.subdomains = this.#getParams(host);
this.params = path
? this.#getRouteParams(path)
: this.#getRouteParams(group);
this.subdomains = this.#getHostParams(host);
this.callbacks = Array.isArray(callbacks)
? callbacks.map((callback) => {
if (typeof callback !== "function") {
throw new TypeError(
`Error: ${
path ? "route" : "middleware"
} callback accepts only function as an argument`
"Error: " +
(path ? "route" : "middleware") +
" callback accepts only function as an argument"
);
}
return callback;
Expand Down Expand Up @@ -140,12 +130,10 @@ module.exports = class Route {
return false;
}
if (match.length > 1) {
let index = 0;
for (let i = 1; i < match.length ?? 0; i++) {
if (this.subdomains && this.subdomains.hasOwnProperty(index)) {
route.subdomains[this.subdomains[index]] = match[i];
if (this.subdomains && this.subdomains.hasOwnProperty(i - 1)) {
route.subdomains[this.subdomains[i - 1]] = match[i];
}
index++;
}
}
}
Expand All @@ -166,12 +154,10 @@ module.exports = class Route {
}

if (match.length > 1) {
let index = 0;
for (let i = 1; i < match.length ?? 0; i++) {
if (this.params && this.params.hasOwnProperty(index)) {
route.params[this.params[index]] = match[i];
if (this.params && this.params.hasOwnProperty(i - 1)) {
route.params[this.params[i - 1]] = match[i];
}
index++;
}
}
return route;
Expand All @@ -181,87 +167,96 @@ module.exports = class Route {
try {
let regexp = host
? host
// Esacep regex special char except inside {}
.replace(/[.*+?^${}()|[\]\\](?![^{]*})/g, "\\$&")
// Esacep regex special char except inside {} and ()
.replace(/(?<!\\)[.^$|[\]](?![^{(]*(\}|\)))/g, "\\$&")
.replace(/(?<!\\)[\*](?![^{(]*(\}|\)))/g, "(?:.*)")
// Ignore trailing slashes
.replace(/^\/?|\/?$/g, "")
// Add user defined regex
.replace(/\{([^\\}]+)\:/g, "")
.replace(/\)\\}/g, ")")
.replace(/(?<=((?<!(\\))\{[^\/\(\{]+?)\:([^\)\}]+))\)\}/g, ")")
.replace(/(?<!\\)\{([^\/\{\}\(\)]+)\:(?=(.*)\))/g, "")
// Named regex
.replace(/\{(.*?)\\}/g, "([^.]+?)")
.replace(/(?<!\\)\{([^/]+?)(?<!\\)\}/g, "([^.]+?)")
: "";
if (this.caseSensitive === true) {
return regexp ? new RegExp(`^${regexp}$`) : null;
return regexp ? new RegExp("^" + regexp + "$") : null;
}
return regexp ? new RegExp(`^${regexp}$`, "i") : null;
return regexp ? new RegExp("^" + regexp + "$", "i") : null;
} catch (err) {
throw new TypeError(`Error: ${host} invalid regular expression`);
throw new TypeError("Error: " + host + " invalid regular expression");
}
}

#compileRouteRegExp(path) {
try {
let regexp = path
? path
// Esacep regex special char except inside {}
.replace(/[.*+?^${}()|[\]\\](?![^{]*})/g, "\\$&")
// Ignore trailing slashes
.replace(/^\/?|\/?$/g, "")
// Add user defined regex
.replace(/\{([^\\}]+)\:/g, "")
.replace(/\)\\}/g, ")")
// Named regex
.replace(/\{(.*?)\\}/g, "([^/]+?)")
: "";
let regexp = this.#compileRegExp(path);
if (this.caseSensitive === true) {
return regexp
? new RegExp(`^/?${regexp}/?$`)
? new RegExp("^/?" + regexp + "/?$")
: regexp === ""
? new RegExp("^/?$")
: null;
}
return regexp
? new RegExp(`^/?${regexp}/?$`, "i")
? new RegExp("^/?" + regexp + "/?$", "i")
: regexp === ""
? new RegExp("^/?$", "i")
: null;
} catch (err) {
throw new TypeError(`Error: ${path} invalid regular expression`);
throw new TypeError("Error: " + path + " invalid regular expression");
}
}

#compileMiddlewareRegExp(path) {
try {
let regexp = path
? path
// Esacep regex special char except inside {}
.replace(/[.*+?^${}()|[\]\\](?![^{]*})/g, "\\$&")
// Ignore trailing slashes
.replace(/^\/?|\/?$/g, "")
// Add user defined regex
.replace(/\{([^\\}]+)\:/g, "")
.replace(/\)\\}/g, ")")
// Named regex
.replace(/\{(.*?)\\}/g, "([^/]+?)")
: "";
let regexp = this.#compileRegExp(path);
if (this.caseSensitive === true) {
return regexp
? new RegExp(`^/?${regexp}/?(?=\/|$)`)
? new RegExp("^/?" + regexp + "/?(?=/|$)")
: regexp === ""
? new RegExp("^/?(?=/|$)")
: null;
}
return regexp
? new RegExp(`^/?${regexp}/?(?=\/|$)`, "i")
? new RegExp("^/?" + regexp + "/?(?=/|$)", "i")
: regexp === ""
? new RegExp("^/?(?=/|$)", "i")
: null;
} catch (err) {
throw new TypeError(`Error: ${path} invalid regular expression`);
throw new TypeError("Error: " + path + " invalid regular expression");
}
}

#compileRegExp(path) {
try {
return path
? path
// Esacep regex special char except inside {} and ()
.replace(/(?<!\\)[.^$|[\]](?![^{(]*(\}|\)))/g, "\\$&")
.replace(/(?<!\\)[\*](?![^{(]*(\}|\)))/g, "(?:.*)")
// Ignore trailing slashes
.replace(/^\/?|\/?$/g, "")
// Add user defined regex
.replace(/(?<=((?<!(\\))\{[^\/\(\{]+?)\:([^\)\}]+))\)\}/g, ")")
.replace(/(?<!\\)\{([^\/\{\}\(\)]+)\:(?=(.*)\))/g, "")
// Named regex
.replace(/(?<!\\)\{([^/]+?)(?<!\\)\}/g, "([^/]+?)")
: "";
} catch (err) {
throw new TypeError("Error: " + path + " invalid regular expression");
}
}

#getParams(path) {
let params = path ? path.match(/(?<=\{).+?(?=\})/g) : null;
#getRouteParams(path) {
let params = path ? path.match(/(?<=\{)([^/]+?)(?=\})/g) : null;
if (!params) {
return undefined;
}
return params.map((e) => e.replace(/\:\((.*)?/, ""));
}

#getHostParams(path) {
let params = path ? path.match(/(?<=\{)([^.]+?)(?=\})/g) : null;
if (!params) {
return undefined;
}
Expand Down
Loading

0 comments on commit f061b6f

Please sign in to comment.