npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

deep-routes

v0.4.1

Published

route parser utilities for deepjs

Downloads

15

Readme

deep-routes

Dynamic url to route mapping.

deep-routes library comes with :

  • a small DSL to describe routes parsing.
  • flat map management tools
  • deeply stuctured map management tools

Maps (deeply structured or flat) could contains OCM entries that will be resolved when traversing.

install

npm install deep-routes

or

bower install deep-routes

Route DSL

It has been developped to clarify route parsing description, and to allow relative route matching in structured maps (see below).

Example : /campaign/?s:id/update/?q:query/?(i:start/i:end) could matchs :

  • /campaign/
  • /campaign/anID
  • /campaign/anID/update
  • /campaign/anID/update/?some=query
  • /campaign/anID/update/?some=query/12/24
  • /campaign/anID/update/12/24

Usage

var deep = require("deepjs");
require("deep-routes/lib/route");
var route = new deep.Route("/campaign/?s:id/update/?q:query/?(i:start/i:end)");
var r = route.match("/campaign/12/update/?foo");
console.log(r);
/* result : 
{
	catched: ["campaign", "12", "update", "?foo"],
	output: {
		id: "12",
		query:"?foo"
	},
	parts: ["campaign", "12", "update", "?foo"],
	index: 4,
	start: 0
}
 */

Rules

  • starting with ? : parts is optional
  • starting with ! : anything but following
  • parts group : surrounded with parenthesis
  • disjonction : surrounded with square brackets, separated with comas. e.g. [campaign,!product]
  • variable catch : parts name start with x: where 'x' is a variable type (see below). e.g. "s:id" or "q:query"
  • parts name equal $ : says that tested route need to ends here

Additionnaly, if whole route start with '?' or '!', it is seen as a optional or negated block.

variables types

  • i: integer
  • f: float
  • q: queryString. anything starting with '?'
  • r: rql query. anything starting with '?'
  • s: string. anything.
  • p: path. used at end of route. says : take the rest of tested route. e.g. /campaign/p:path will match /campaign/my/long/path

add custom type

adding date :

deep.Route.addType("d:", function(input) { // date
	var r = parseInt(input, 10);
	if (!isNaN(r) && r !== Infinity)
		return new Date(r);
	return null;
});

Flat map

A "flat" map is just an object containing, at first level, "routes" as properties keys and "controllers" as properties values (absolutly free shaped object).

example :

var deep = require("deepjs");
require("deep-routes/lib/flat");

var map = {
	"/product/?s:id":{
		// product controller
		title:"product controller"
	},
	"/register/?s:email":{
		title:"register controller"
	},
	//...
};

deep.route.flatMapper(map) // flatten and compile map. returns a mapper object which contains a single method : match(uri)
.done(function(mapper){
	var r = mapper.match("/product/12"); // return first match
	console.log(r);
	/* result : 
	{
		params:{ id:12 }, 
		catched:["product", "12"], 
		entry:{ title:"product controller" }
	}
	*/
})
.elog(); // print any error

Standard restful expansion

When using deep.route.flatMapper for restful services mapping, you could ask to expand simple routes (routes without variable catch) with default restful routing pattern (catching optional id, queries or subpath).

It means :

var deep = require("deepjs");
require("deep-routes/lib/flat");

var map = {
	"/campaign":{  // declare simple path without variable catch => will be expanded
		// campaign controller
		title:"campaign controller"
	},
	"/register/?s:email":{  // contains variable catch => will not be expanded
		title:"register controller"
	},
	//...
};

deep.route.flatMapper(map, true) // pass true as second argument to expand "simple" route
.done(function(mapper){
	var r = mapper.match("/campaign/12"); // return first match
	console.log(r);
	/* result :
	{
		params:{ id:12 }, 
		catched:["campaign", "12"], 
		entry:{ title:"campaign controller" }
	}
	*/
})
.elog(); // print any error

/campaign/ has been expanded in /campaign/?[(s:id/?p:path),q:query]

Deeply structured map

A structured map is defined by a structure of objects containing "route" and/or "subs" properties, the two only keywords of structured map.

The "route" entry gives the route matcher of your controller, and "subs" property contains optional subcontrollers.

The routing algorithm is like an automate that try to match any "route" property founded in current level's entries. If "route" matchs (or if there is no route property, which means always match), it selects current entry, and if current entry contains a "subs" property then algorithm appying route matching recursively on it.

So the algorithm finally selects a tree of controllers that match a uri.

Additionnaly, any "route" entry could be absolute (starting with "/"), or relative to last matched index :

  • ./foo : says try to match "foo" after last matched index
  • ../foo : says try to match "foo" after last matched index - 1
  • ../../foo : says try to match "foo" after last matched index - 2
  • ...

It means :

var map = {
	topbar:{
		// top bar controller
		// no "route" property => will always be selected
	},
	home:{
		// home controller : selected if this.route start with /home or equal /
		route:"/[home,$]"
		// ...
	},
	product:{
		// products ctrler : selected if this.route start with /products
		route:"/product",
		// ...
		subs:{
			list:{
				// list ctrler : selected if this.route match, from last matched index (here after /product) :
				route:"./q:query/?(i:start/i:end)"
			},
			detail:{
				// list ctrler : selected if this.route match, from last matched index :
				route:"./detail/s:id"
			},
			comment:{
				// comment ctrler : selected if this.route match, from last matched index :
				route:"./comment/s:id"
			}
		}
	},
	//...
};

Possibles routes matched by this map :

  • / (selected : topbar, home)
  • /home (selected : topbar, home)
  • /product/?some=query (selected : topbar, products, list)
  • /product/?some=query/0/9 (selected : topbar, products, list)
  • /product/?some=query/detail/53 (selected : topbar, products, list, detail)
  • /product/?some=query/detail/53/comment/12 (selected : topbar, products, list, detail, comment)
  • /product/?some=query/comment/12 (selected : topbar, products, list, comment)
  • /product/?some=query/0/9/detail/53 (selected : topbar, products, list, detail)
  • /product/?some=query/0/9/detail/53/comment/12 (selected : topbar, products, list, detail, comment)
  • /product/?some=query/0/9/comment/12 (selected : topbar, products, list, comment)
  • /product/detail/53 (selected : topbar, products, detail)
  • /product/detail/53/comment/12 (selected : topbar, products, detail, comment)
  • /product/comment/12 (selected : topbar, products, detail)

The idea, with relative route management, is to break coupling between parent and children, to obtain clean MVC pattern where neither parent nor children know anything about each other.

As a controller could define its own route management (as "list", "detail" and "comment" in example above), independently of previously "consummmed" route's parts, it allows us to reattach or reuse a controller elsewhere without anychange.

Structured maps and views

As structured maps have been developped principaly for views and subviews management, it works hand in hand with deep-views.

var deep = require("deepjs");
require("deep-views/lib/view");
require("deep-routes/lib/structured");
var map = {
	topbar:deep.View({
		how:"<div>topbar content</div>",
		where:"dom.appendTo::#topbar"
	}),
	home:deep.View({
		route:"/[home,$]",
		how:"<div>home content</div>",
		where:"dom.appendTo::#content"
	}),
	profile:deep.View({
		route:"/profile/?s:name",
		how:"<div>hello { name | 'dude' } !</div>",
		where:"dom.appendTo::#content"
	})
};
deep.route.structuredMapper(map) // flatten and compile map. return root node (a deep.route.MapNode).
.done(function(node){
	var r = node.match("/campaign/john");
	console.log(r);
})
.elog();

load and refresh sequence

relink

inner view route and getRoute

Licence

LGPL 3.0