New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

anumargak

Package Overview
Dependencies
Maintainers
1
Versions
22
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

anumargak - npm Package Compare versions

Comparing version 1.7.0 to 1.8.0

src/semver-store.js

12

package.json
{
"name": "anumargak",
"version": "1.7.0",
"version": "1.8.0",
"description": "Amazing fast multipurpose simple to use web/ HTTP router",

@@ -36,4 +36,4 @@ "main": "./src/letsRoute.js",

"find-my-way": "^1.15.1",
"jasmine": "^3.1.0",
"jasmine-core": "^3.1.0",
"jasmine": "^3.2.0",
"jasmine-core": "^3.2.0",
"mock-req": "^0.2.0",

@@ -45,3 +45,9 @@ "nyc": "^11.9.0"

"semver-store": "^0.3.0"
},
"nyc": {
"exclude": [
"tests",
"build"
]
}
}

@@ -19,19 +19,16 @@ # अनुमार्गक (anumargak)

* Fastest node js router (as far as Google & I know)
* Framework independent
* Supports static and dynamic both type of URLs
* Framework independent.
* Supports static and dynamic both type of URLs.
* Supports path parameter with defined type `\this\is\:num([0-9]+)`
* Support multiple path parameters
* Support multiple path parameters.
* Handles enumerated URLs `\login\as\:role(admin|staff|user)`
* Supports wildchar `\this\is\*`, `\this\is\wild*`
* You nee not to register 2 separate routes for trailing slash. `\like\me\` and `\like\me`.
* You need not to register 2 separate routes for trailing slash. `\like\me\` and `\like\me`.
* You may skip leading slash while registering the route, though not recommended. `\like\me` and `like\me`.
* Capture parameters' value for dynamic URLs.
* Warn (by default) or silently overwrites (when `overwriteAllow : true`) same or similar URLs
* `\this\is\static` and `\this\is\static`
* `\this\:param\is\dynamic` and `\this\param\:is\dynamic`
* `\this\is\:uid([a-zA-Z0-9]+)` and `\this\is\:num([0-9]+)`
* Add similar but not same URLs
* `\this\is\:age([0-9]+)` and `\this\is\:name([a-zA-Z]+)`
* Support of shorthand methods
* Add similar but not same URLs : `\this\is\:age([0-9]+)` and `\this\is\:name([a-zA-Z]+)`
* Support shorthand methods
* You can always have a count on registered routes.
* Supports versioned routes
* Supports versioned routes.
* You can name regular expressions to increase code redability.

@@ -41,50 +38,53 @@ ## Usage

```js
const http = require('http')
const router = require('anumargak')({
defaultRoute : defaultHandler,
defaultRoute : defaultHandler,//it'll be called when no route matches. If it is not set the we'll set statusCode to 404
ignoreTrailingSlash: true,
ignoreLeadingSlash: true,
});
})
anumargak.on("GET", "/this/is/static", handler);
anumargak.on(["POST","PUT"], "/this/is/static", handler);//supports array
anumargak.on("GET", "/this/is/:dynamic", handler);
anumargak.on("GET", "/this/is/:dynamic", handler);//it will overwrite old mapping
anumargak.on("GET", "/this/is/:dynamic/with/:pattern(\\d+)", handler);
//Eg: params = { dynamic : val, pattern: 123}
anumargak.on("GET", "/this/is/:dynamic/with/:two-:params", handler);//use - to separate multiple parameters
anumargak.on("GET", "/this/is/:dynamic/with/:two(\\d+):params", handler);
anumargak.on("GET", "/this/is/:dynamic/with/:two(\\d+)rest", handler);
anumargak.on("GET", "/similar/:string([a-z]{10})", handler);
anumargak.on("GET", "/similar/:number([0-9]{10})", handler);//above route is different from this
router.on('GET', '/', (req, res, params) => {
//process the request response here
})
const server = http.createServer((req, res) => {
router.lookup(req, res)
})
anumargak.find("GET","/this/is/static");//will return handler
anumargak.find("GET","/this/is/dynamic/with/123?ignore=me");//ignore query parameters and hashtag part automatically
server.listen(3000);
```
anumargak.lookup(req,res) ;//will execute handler with req,res and params(for dynamic URLs) as method parameters
## on(method, url [, options] , handler [, store] )
console.log(anumargak.count); //Print number of unique routes added
To register a route.
```JavaScript
router.on("GET", "/this/is/static", handler);
router.on(["POST","PUT"], "/this/is/static", handler);
```
Example with server
```js
const http = require('http')
const router = require('anumargak')()
### Dynamic URL
router.on('GET', '/', (req, res, params) => {
//process the request response here
})
You can register dynamic url with multiple path paramters
const server = http.createServer((req, res) => {
router.lookup(req, res)
})
```JavaScript
router.on("GET", "/this/is/:dynamic", handler);
router.on("GET", "/this/is/:dynamic", handler);//it will error
router.on("GET", "/this/is/:dynamic/with/:pattern(\\d+)", handler);
//Eg: params = { dynamic : val, pattern: 123}
router.on("GET", "/this/is/:dynamic/with/:two-:params", handler);//use - to separate multiple parameters
router.on("GET", "/this/is/:dynamic/with/:two(\\d+):params", handler);//multiple parameters
router.on("GET", "/this/is/:dynamic/with/:two(\\d+)rest", handler);//single parameter
```
server.listen(3000, err => {
if (err) throw err
console.log('Server listening on: http://localost:3000')
})
### Enumerated URL
Anumargak handls enumerated URLs in static way. Because static URLs can be looked up faster than dynamic URLs.
```js
router.on("GET", "/login/as/:role(admin|user|staff)", handler);
```
**wildcard**: wild cards are helpful when a route handler wants to control all the underlying paths. Eg. a handler registered with `/help*` may take care of all the help pages and static resources under the same path.
### wildcard
wild cards are helpful when a route handler wants to control all the underlying paths. Eg. a handler registered with `/help*` may take care of all the help pages and static resources under the same path. You can check [आलेख (Aalekh)](https://github.com/muneem4node/aalekh) for live example.

@@ -95,3 +95,3 @@ ```js

//this/is/juglee/and/wild/and/unknown
anumargak.on("GET", "/this/is/:dynamic/and/*", handler);
router.on("GET", "/this/is/:dynamic/and/*", handler);

@@ -101,6 +101,6 @@ //this/is/juglee/and/wild

//this/is/juglee/and/wild/and/unknown
anumargak.on("GET", "/this/is/:dynamic/and/wild*", handler);
router.on("GET", "/this/is/:dynamic/and/wild*", handler);
```
**shorthand methods**
### shorthand methods

@@ -117,4 +117,83 @@ ```js

## Similar but not same URLs
## off(method, url [, version] )
To remove a registered route. If no route is found no error will be thrown.
```JavaScript
anumargak.off("GET", "/this/is/static");
anumargak.off("GET", "/this/is/:dynamic");
anumargak.off("GET", "/this/is/*/really/wild");
anumargak.off("GET", "/login/as/:role(admin|user|staff)"); //it'll delete all the versions
```
### Enumerated URLs
an enumerated URL can be deleted multi steps
```JavaScript
anumargak.off("GET", "/login/as/:role(admin|user|staff)");
//or
anumargak.off("GET", "/login/as/admin");
anumargak.off("GET", "/login/as/user");
anumargak.off("GET", "/login/as/staff");
//or
anumargak.off("GET", "/login/as/:role(user|staff)");
anumargak.off("GET", "/login/as/admin");
```
### Versioned URLs
version can be provided as an additional parmeter. Valid values are:
* 1.2.3 : It'll delete only one URL
* 1.2.x : It'll delete all the URLs with different patche versions : 1.2.0, 1.2.1 ...
* 1.x : It'll delete all the URLs with different minor versions : 1.2.0, 1.2.1, 1.3.5 ...
```JavaScript
anumargak.off("GET", "/this/is/static", version);
```
Please **note** that, if you delete a route without specifying versions then all the versioned routes will also be deleted.
## find(method, url [, version])
To find a registered route. It returns;
```JavaScript
{
handler : function(){}, //registered function
params : {}, //path parameters
store : any // extra data provided at the time of registering the route
}
```
## quickFind(method, url [, version])
To find a registered route. It returns;
```JavaScript
{
handler : function(){}, //registered function
store : any // extra data provided at the time of registering the route
}
```
`quickFind()` is faster than `find()`.
## lookup(request, response)
This method reads *request* object to fetch url, method, and `accept-version` header to find matching route and then run the handler.
The handler should accept: request, response, and params. params is an object of path parameters.
## count
You can always check how many routes are registered. If you delete some routes count will be decreased.
## Other detail
### Similar but not same URLs
You can register the URLs which look similar but not exactly same.
```js

@@ -127,6 +206,10 @@ const anumargak = require('anumargak')()

anumargak.on("GET", "/this/is/my/:name([a-zA-z]+)", handler);
anumargak.on("GET", "/login/as/:role(admin|user|staff)", handler);
anumargak.on("GET", "/login/as/:role(developer|tester|hacker)", handler);
```
## Named Expressions
### Named Expressions
Anumargak lets you add named expressions. You can use them at the time of registering the route.

@@ -153,3 +236,3 @@

## accept-version
### accept-version

@@ -215,1 +298,5 @@ Same routes can be registerd with different versions. Lookup method reads `accept-version` header to read the version or you can pass the version in find method directly.

- <img src="https://avatars3.githubusercontent.com/u/4491530?v=4" width="20" height="20"/> [shuklajay117](https://github.com/shuklajay117)
## Disclaimer
I initially used *find-my-way* npm package for [मुनीम (Muneem)](https://github.com/muneem4node/muneem) framework. But then I realized that lookup for static URLs is comparitively slower. Hence I develop this library. If you notice, I tried to keep the naming convention and syntaxes common wherever possible to reduce the time to switch from one library to another and to keep learning curve smaller.
var { getFirstMatche, getAllMatches, doesMatch, urlSlice } = require("./util");
var namedExpressionsStore = require("./namedExpressionsStore");
var semverStore = require("semver-store");
var semverStore = require("./semver-store");

@@ -18,5 +18,6 @@ var httpMethods = ["GET", "HEAD", "PUT", "POST", "DELETE", "OPTIONS", "PATCH", "TRACE", "CONNECT", "COPY", "LINK", "UNLINK", "PURGE", "LOCK", "UNLOCK", "PROPFIND", "VIEW"];

*/
Anumargak.prototype.on = function (method, url, options, fn) {
Anumargak.prototype.on = function (method, url, options, fn, extraData) {
if (typeof options === 'function') {
extraData = fn;
fn = options;

@@ -27,6 +28,6 @@ options = {};

if (typeof method === "string") {
this.normalizeUrl(method, url, options, fn);
this._on(method, url, options, fn, extraData);
} else if (Array.isArray(method)) {
for (var i = 0; i < method.length; i++) {
this.normalizeUrl(method[i], url, options, fn);
this._on(method[i], url, options, fn, extraData);
}

@@ -36,2 +37,4 @@ } else {

}
return this;
}

@@ -44,3 +47,4 @@

Anumargak.prototype.normalizeUrl = function (method, url, options, fn) {
Anumargak.prototype._on = function (method, url, options, fn, extraData) {

@@ -51,2 +55,8 @@ //validate for correct input

url = this.normalizeUrl(url);
this._addRoute(method, url, options, fn, extraData);
}
Anumargak.prototype.normalizeUrl = function (url) {
//Normalize URL

@@ -66,3 +76,3 @@ if (this.ignoreLeadingSlash) {

this._addRoute(method, url, options, fn);
return url;
}

@@ -73,12 +83,14 @@

*/
Anumargak.prototype._addRoute = function (method, url, options, fn, params) {
Anumargak.prototype._addRoute = function (method, url, options, fn, extraData, params) {
var found = this._checkForEnum(method, url, options, fn, params);
if(found) return;
var matches = getAllMatches(url, paramRegexStr);
if (matches.length > 0) {//DYNAMIC
this._addDynamic(method, url, options, fn, params, matches);
} else {//STATIC
this._addStatic(method, url, options, fn, params, this.ignoreTrailingSlash);
var done = this._checkForEnum(method, url, options, fn, extraData, params);
if( done ) { //All the enumerated URLs are registered
return;
}else{
var matches = getAllMatches(url, paramRegexStr);
if (matches.length > 0) {//DYNAMIC
this._addDynamic(method, url, options, fn, extraData, params, matches);
} else {//STATIC
this._addStatic(method, url, options, fn, extraData, params, this.ignoreTrailingSlash);
}
}

@@ -95,3 +107,3 @@ }

*/
Anumargak.prototype._checkForEnum = function(method, url, options, fn, params){
Anumargak.prototype._checkForEnum = function(method, url, options, fn, extraData, params){
var matches = getFirstMatche(url, enumRegexStr);

@@ -112,3 +124,3 @@ if (matches) {

}
this._addRoute(method, newurl, options, fn, params);
this._addRoute(method, newurl, options, fn, extraData, params);
}

@@ -119,10 +131,11 @@ return true;

Anumargak.prototype._addStatic = function(method, url, options, fn, params, ignoreTrailingSlash){
Anumargak.prototype._addStatic = function(method, url, options, fn, extraData, params, ignoreTrailingSlash){
this.checkIfRegistered(this.staticRoutes, method, url, options, fn);
var routeData = this.getRouteData(this.staticRoutes[method][url], method, url, options, fn);
var routeHandlers = this.getRouteHandlers(this.staticRoutes[method][url], method, url, options, fn);
this.staticRoutes[method][url] = {
fn : routeData.handler,
verMap: routeData.verMap,
params: params
fn : routeHandlers.handler,
verMap: routeHandlers.verMap,
params: params,
store: extraData
};

@@ -138,7 +151,8 @@

var routeData = this.getRouteData(this.staticRoutes[method][url], method, url, options, fn);
var routeHandlers = this.getRouteHandlers(this.staticRoutes[method][url], method, url, options, fn);
this.staticRoutes[method][url] = {
fn : routeData.handler,
verMap: routeData.verMap,
params: params
fn : routeHandlers.handler,
verMap: routeHandlers.verMap,
params: params,
store: extraData
};

@@ -150,3 +164,21 @@

Anumargak.prototype._addDynamic = function(method, url, options, fn, params, matches){
Anumargak.prototype._addDynamic = function(method, url, options, fn, extraData, params, matches){
var normalizedUrl = normalizeDynamicUrl(url, matches, this.ignoreTrailingSlash);
url = normalizedUrl.url;
this.checkIfRegistered(this.dynamicRoutes, method, url, options, fn);
var routeHandlers = this.getRouteHandlers(this.dynamicRoutes[method][url], method, url, options, fn);
var regex = new RegExp("^" + url + "$");
this.dynamicRoutes[method][url] = {
fn: routeHandlers.handler,
regex: regex,
verMap: routeHandlers.verMap,
params: params || {},
paramsArr: normalizedUrl.paramsArr ,
store: extraData
};
}
var normalizeDynamicUrl = function (url, matches, ignoreTrailingSlash ) {
var paramsArr = [];

@@ -171,3 +203,3 @@ for (var i = 0; i < matches.length; i++) {

if (this.ignoreTrailingSlash) {
if ( ignoreTrailingSlash) {
if (url.endsWith("/")) {

@@ -179,19 +211,10 @@ url = url + "?";

}
var regex = new RegExp("^" + url + "$");
this.checkIfRegistered(this.dynamicRoutes, method, url, options, fn);
var routeData = this.getRouteData(this.dynamicRoutes[method][url], method, url, options, fn);
this.dynamicRoutes[method][url] = {
fn: routeData.handler,
regex: regex,
verMap: routeData.verMap,
params: params || {},
paramsArr: paramsArr
};
return {
paramsArr : paramsArr,
url : url
};
}
Anumargak.prototype.getRouteData = function (route, method, url, options, fn) {
Anumargak.prototype.getRouteHandlers = function (route, method, url, options, fn) {
if(options.version){

@@ -280,38 +303,49 @@ var verMap, handler;

Anumargak.prototype.find = function (method, url, version) {
Anumargak.prototype.quickFind = function (method, url, version) {
url = urlSlice(url);
var result = this.staticRoutes[method][url];
if (result) return this.getHandler(result, version);
else {
if (result) {
return {
handler: this.getHandler(result, version),
store : result.store
}
}else {
var urlRegex = Object.keys(this.dynamicRoutes[method]);
for (var i = 0; i < urlRegex.length; i++) {
if (this.dynamicRoutes[method][urlRegex[i]].regex.exec(url))
return this.getHandler( this.dynamicRoutes[method][ urlRegex[i] ], version);
if (this.dynamicRoutes[method][urlRegex[i]].regex.exec(url)){
var result = this.dynamicRoutes[method][ urlRegex[i] ];
return {
handler: this.getHandler( result, version),
//params: result.params,
store: result.store
}
}
}
}
return this.defaultFn;
return null;
}
Anumargak.prototype.getHandler = function (route, version) {
if(version){
return route.verMap.get(version);
}else{
return route.fn;
}
}
Anumargak.prototype.lookup = function (req, res) {
var method = req.method;
var url = urlSlice(req.url);
var version = req.headers['accept-version'];
var result = this._lookup(url, method, version);
result.fn(req, res, result.params);
var result = this.find(method, req.url, version);
if(result === null){
this.defaultFn(req, res);
}else{
result.handler(req, res, result.params);
}
}
Anumargak.prototype._lookup = function (url, method, version) {
Anumargak.prototype.find = function (method, url, version) {
url = urlSlice(url);
var result = this.staticRoutes[method][url];
if (result) return { fn: this.getHandler(result, version), params: result.params };
else {
if (result) {
return {
handler: this.getHandler(result, version),
params: result.params,
store: result.store
};
}else {
var urlRegex = Object.keys(this.dynamicRoutes[method]);

@@ -326,9 +360,87 @@ for (var i = 0; i < urlRegex.length; i++) {

}
return { fn: this.getHandler(this.dynamicRoutes[method][urlRegex[i]], version), params: params };
var result = this.dynamicRoutes[method][urlRegex[i]];
return {
handler: this.getHandler(result, version),
params: params,
store: result.store
};
}
}
}
return { fn: this.defaultFn };
return null;
}
Anumargak.prototype.getHandler = function (route, version) {
if(version){
return route.verMap.get(version);
}else{
return route.fn;
}
}
Anumargak.prototype.off = function (method, url, version) {
url = this.normalizeUrl(url);
var done = this.removeEnum(method, url);
if(done) return;
var matches = getAllMatches(url, paramRegexStr);
var result;
if (matches.length > 0) {//DYNAMIC
url = normalizeDynamicUrl(url, matches, this.ignoreTrailingSlash).url;
result = this.isRegistered(this.dynamicRoutes, method, url);
} else {//STATIC
result = this.isRegistered(this.staticRoutes, method, url);
}
if (result) {
if(version ){
var route;
if( this.dynamicRoutes[method][result] ){
route = this.dynamicRoutes[method][result];
}else {
route = this.staticRoutes[method][result];
}
if(route.verMap && route.verMap.get( version )){
var delCount = route.verMap.delete( version );
this.count -= delCount;
}
}else{
if( this.dynamicRoutes[method][result] ){
if( this.dynamicRoutes[method][result].verMap ){
this.count -= this.dynamicRoutes[method][result].verMap.count();
}
delete this.dynamicRoutes[method][result];
this.count--;
}else {
if( this.staticRoutes[method][result].verMap ){
this.count -= this.staticRoutes[method][result].verMap.count();
}
delete this.staticRoutes[method][result];
this.count--;
}
}
}
}
Anumargak.prototype.removeEnum = function(method, url){
var matches = getFirstMatche(url, enumRegexStr);
if (matches) {
var name = matches[1];
var pattern = matches[3];
var arr = pattern.split("\|");
for (var i = 0; i < arr.length; i++) {
var newurl = url.replace(matches[0], arr[i]);
this.off(method, newurl);
this.count++;
}
this.count--;
return true ;
}
}
/**

@@ -422,2 +534,4 @@ * Adds routes for GET method and URL

this.defaultFn = options.defaultRoute;
}else{
this.defaultFn = defaultRoute;
}

@@ -430,2 +544,6 @@ this.ignoreTrailingSlash = options.ignoreTrailingSlash || false;

function defaultRoute(req, res) {
res.statusCode = 404
res.end()
}
module.exports = Anumargak;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc