{"id":16758218,"url":"https://github.com/foo123/dromeo","last_synced_at":"2025-06-16T12:33:25.067Z","repository":{"id":51535681,"uuid":"15117819","full_name":"foo123/Dromeo","owner":"foo123","description":"A Simple and Flexible Pattern Routing Framework for PHP, JavaScript, Python","archived":false,"fork":false,"pushed_at":"2022-08-13T15:06:27.000Z","size":209,"stargazers_count":4,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-10T17:33:58.315Z","etag":null,"topics":["javascript","pattern","php","python","router"],"latest_commit_sha":null,"homepage":"https://foo123.github.io/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/foo123.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-12-11T20:12:38.000Z","updated_at":"2022-12-17T20:51:54.000Z","dependencies_parsed_at":"2022-08-12T23:31:13.761Z","dependency_job_id":null,"html_url":"https://github.com/foo123/Dromeo","commit_stats":null,"previous_names":[],"tags_count":13,"template":false,"template_full_name":null,"purl":"pkg:github/foo123/Dromeo","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FDromeo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FDromeo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FDromeo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FDromeo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foo123","download_url":"https://codeload.github.com/foo123/Dromeo/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foo123%2FDromeo/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260162633,"owners_count":22968090,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["javascript","pattern","php","python","router"],"created_at":"2024-10-13T04:04:31.087Z","updated_at":"2025-06-16T12:33:25.029Z","avatar_url":"https://github.com/foo123.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"Dromeo\r\n======\r\n\r\nA Simple and Flexible Pattern Routing Framework for PHP, JavaScript, Python\r\n\r\n\r\n![Dromeo](/dromeo.jpg)\r\n\r\n\r\nVersion: **1.2.0**\r\n\r\n\r\n[Etymology of *\"dromos\"* (path)](https://en.wiktionary.org/wiki/%CE%B4%CF%81%CF%8C%CE%BC%CE%BF%CF%82#Ancient_Greek)\r\n[Etymology pf *\"path\"*](https://en.wiktionary.org/wiki/path)\r\n\r\n\r\n[Dromeo.js](https://raw.githubusercontent.com/foo123/Dromeo/master/src/js/Dromeo.js)\r\n\r\n\r\n**see also:**\r\n\r\n* [ModelView](https://github.com/foo123/modelview.js) a simple, fast, powerful and flexible MVVM framework for JavaScript\r\n* [tico](https://github.com/foo123/tico) a tiny, super-simple MVC framework for PHP\r\n* [LoginManager](https://github.com/foo123/LoginManager) a simple, barebones agnostic login manager for PHP, JavaScript, Python\r\n* [SimpleCaptcha](https://github.com/foo123/simple-captcha) a simple, image-based, mathematical captcha with increasing levels of difficulty for PHP, JavaScript, Python\r\n* [Dromeo](https://github.com/foo123/Dromeo) a flexible, and powerful agnostic router for PHP, JavaScript, Python\r\n* [PublishSubscribe](https://github.com/foo123/PublishSubscribe) a simple and flexible publish-subscribe pattern implementation for PHP, JavaScript, Python\r\n* [Importer](https://github.com/foo123/Importer) simple class \u0026amp; dependency manager and loader for PHP, JavaScript, Python\r\n* [Contemplate](https://github.com/foo123/Contemplate) a fast and versatile isomorphic template engine for PHP, JavaScript, Python\r\n* [HtmlWidget](https://github.com/foo123/HtmlWidget) html widgets, made as simple as possible, both client and server, both desktop and mobile, can be used as (template) plugins and/or standalone for PHP, JavaScript, Python (can be used as [plugins for Contemplate](https://github.com/foo123/Contemplate/blob/master/src/js/plugins/plugins.txt))\r\n* [Paginator](https://github.com/foo123/Paginator)  simple and flexible pagination controls generator for PHP, JavaScript, Python\r\n* [Formal](https://github.com/foo123/Formal) a simple and versatile (Form) Data validation framework based on Rules for PHP, JavaScript, Python\r\n* [Dialect](https://github.com/foo123/Dialect) a cross-vendor \u0026amp; cross-platform SQL Query Builder, based on [GrammarTemplate](https://github.com/foo123/GrammarTemplate), for PHP, JavaScript, Python\r\n* [DialectORM](https://github.com/foo123/DialectORM) an Object-Relational-Mapper (ORM) and Object-Document-Mapper (ODM), based on [Dialect](https://github.com/foo123/Dialect), for PHP, JavaScript, Python\r\n* [Unicache](https://github.com/foo123/Unicache) a simple and flexible agnostic caching framework, supporting various platforms, for PHP, JavaScript, Python\r\n* [Xpresion](https://github.com/foo123/Xpresion) a simple and flexible eXpression parser engine (with custom functions and variables support), based on [GrammarTemplate](https://github.com/foo123/GrammarTemplate), for PHP, JavaScript, Python\r\n* [Regex Analyzer/Composer](https://github.com/foo123/RegexAnalyzer) Regular Expression Analyzer and Composer for PHP, JavaScript, Python\r\n\r\n\r\n**Examples:**\r\n\r\nsee `/test` folder\r\n\r\n\r\n**Route Patterns:**\r\n\r\n```javascript\r\n\r\n// Examples:\r\n//\r\n\r\n// match literal route\r\n'http://abc.org/'\r\n\r\n// match route and capture the last numeric part into 'id' param\r\n'http://abc.org/{%NUMBR%:id}'\r\n\r\n// same as previous, numeric 'id' part is optional\r\n'http://abc.org/{%NUMBR%:?id}'\r\n\r\n// numeric part is optional but not captured (no param name given)\r\n'http://abc.org/{%NUMBR%:?}'\r\n\r\n// numeric part is required but not captured (no param name given)\r\n'http://abc.org/{%NUMBR%:}'\r\n\r\n// part is required and captured as 'name', pattern is assumed %PART%=[^/]+ (capture everything between slashes)\r\n'http://abc.org/{:name}'\r\n\r\n// optional captured 'id' part is now the numeric pattern plus the leading '/'\r\n'http://abc.org{/%NUMBR%:?id}'\r\n\r\n// optional captured 'id' part is only the numeric pattern without the leading '/', i.e group 1\r\n'http://abc.org{/%NUMBR%:?id(1)}'\r\n\r\n/* etc.. */\r\n\r\n```\r\n\r\n\r\n**Methods:**\r\n\r\n* `Dromeo` is also a `XPCOM JavaScript Component` (Firefox) (e.g to be used in firefox browser addons/plugins)\r\n\r\n```javascript\r\n\r\n// -- instance methods --\r\n// --------------------------------------------------------\r\n\r\n// optional route_prefix to be used in case all routes have a common prefix\r\n// so can define routes using only the part that differs (easier/shorter code)\r\nvar router = new Dromeo(prefix='');\r\n\r\n// set/define delimiters used in route-patterns, see examples\r\nrouter.defineDelimiters(['{', '}', '%', '%', ':']);\r\n\r\n// define a (new) sub-pattern identified with className\r\n// sub-patterns are used in route-patterns,\r\n// e.g \"http://abc.org/{%ALNUM%:user}\", \"ALNUM\" is an alpha-numeric sub-pattern, i.e \"[a-zA-Z0-9\\\\-_]+\"\r\n// default sub-patterns:\r\n// ALPHA =\u003e   \"[a-zA-Z\\\\-_]+\"            alphabetic only\r\n// NUMBR =\u003e   \"[0-9]+\"                   numeric only\r\n// INT   =\u003e   \"[0-9]+\"                   integer with associated optional typecaster\r\n// ALNUM =\u003e   \"[a-zA-Z0-9\\\\-_]+\"         alpha-numeric only\r\n// QUERY =\u003e   \"\\\\?[^?#]+\"                query part with leading '?'\r\n// FRAGMENT =\u003e\"#[^?#]+\"                  hash/fragment part with leading '#'\r\n// PART  =\u003e   \"[^\\\\/?#]+\"                arbitrary path part (between /../)\r\n// ALL   =\u003e   \".+\"                       arbitrary sequence\r\nrouter.definePattern(className, subPattern [, typecaster = null]);\r\n\r\n// unset/remove the sub-pattern \"clasName\"\r\nrouter.dropPattern(className);\r\n\r\n// define a custom type, to be used as (optional) typecaster for matching parts\r\nrouter.defineType(type, typecaster);\r\n\r\n// reset/remove routes and fallback handler\r\nrouter.reset();\r\n\r\n// create a URI from named_route pattern with given parameter values\r\n// named routes are created by adding a name property when defining a route\r\n// NOTE: will throw error if parameter is missing and is required (not optional) in the route pattern\r\n// if strict is set to true will also try to match the parameter value based on route pattern type, eg numeric/alphanumeric etc.. and will throw error if pattern test failed\r\nrouter.make(named_route [, params = Object()[, strict = false]]);\r\n\r\n// example\r\nrouter.on({\r\n    route: '/{:user}/{:id}',\r\n    name: 'my_route',\r\n    handler: function(){/* .. */}\r\n});\r\nconsole.log(router.make('my_route', {user:'foo',id:'123'}));\r\n// prints \"/foo/123\"\r\n\r\n// set/unset fallback handler\r\nrouter.fallback([handlerFunc | false | null]);\r\n\r\n// set a handler for routePattern, with optional defaults object (oneOff if \"one\" used)\r\nrouter.[on|one](routeObj | routeObjs | routePattern, handler);\r\n// route object configuration\r\n//\r\n//{\r\n//    route: '..', // the route pattern matched, needed\r\n//    name: '..', // create a named route to be referenced at will, for example in order to create URLs matching the route pattern with given parameters\r\n//    method: 'post', // the method (case-insensitive), default is '*', i.e any, can use array of methods as well, i.e ['get','post']\r\n//    handler: function(params){/*..*/}, // the route handler to be called, needed\r\n//    defaults: {/*..*/}, // any default and/or extra parameters to be used, if missing, and passed to handler, default is {}\r\n//    types: {/*..*/} // optional typecasters for specific matches, i.e INTEGER, STRING, ARRAY, PARAMS or custom, default null\r\n//}\r\n//\r\n\r\n// this also works:\r\nrouter.[on|one](routePattern, function(params){/*..*/});\r\n\r\n// set handler(s) for multiple routePattern(s) (oneOff if \"one\" used)\r\n\r\n// using array of objects\r\nrouter.[on|one]([\r\n    routeObj1,\r\n    routeObj2\r\n    /* etc .. */\r\n]);\r\n\r\n// using variable arguments\r\nrouter.[on|one](\r\n    routeObj1,\r\n    routeObj2\r\n    /* etc .. */\r\n);\r\n\r\n// set a group of routes sharing common prefix\r\nrouter.onGroup(prefix, function(subRouter){\r\n    subRouter.on(/*..*/);\r\n    subRouter.onGroup(prefix2, function(subRouter2){/*..*/}); // can be nested\r\n    // ..\r\n});\r\n\r\n// remove the routePattern (optionally if handlerFunc matches as well)\r\nrouter.off(routePattern | routeObj [, handlerFunc = null]);\r\n\r\n// redirect to given url (with optional statusCode and statusMsg)\r\n// in Node, the **response object** from node.http should be passed as well\r\nrouter.redirect(url, response [, statusCode=302, statusMsg=true]);\r\n\r\n// parse and extract uri components and optional query/fragment params as objects (using RFC3986)\r\nvar components = router.parse(url [, query_p='query_params', fragment_p='fragment_params']);\r\n\r\n// parse/unglue a uri component into a params object (using RFC3986)\r\nvar params = router.unglue(uriComponent);\r\n\r\n// build (url-encoded) url from baseUrl and query and/or hash objects (using RFC3986)\r\nvar url = router.build(baseUrl, query=null, hash=null);\r\n\r\n// build/glue together a uri component from a params object (using RFC3986)\r\nvar component = router.glue(params);\r\n\r\n// match and route a given url\r\n// (with optional method, only routes which match the method will be used),\r\n// returns true if matched any routePattern else false\r\nvar matched = router.route(url, method=\"*\", breakOnFirstMatch=true, originalUrl=null, originalKey=null);\r\n\r\n```\r\n\r\n**TODO**\r\n\r\n* add support for (http/request) method [DONE]\r\n* add support for extra passed defaults [DONE]\r\n* add support for (optional) type-casting of matched parameters [DONE]\r\n* add support for making string (URI) from route pattern with given parameters [DONE]\r\n* add support for extracting original matches if originalInput (if passed), eg with original case, is different than givenInput [DONE]\r\n* add support for subgroup of routes under common prefix (ie. `onGroup()`) [DONE]\r\n* add support for [RFC 6570 URI Template specification](http://tools.ietf.org/html/rfc6570) (TODO?)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoo123%2Fdromeo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoo123%2Fdromeo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoo123%2Fdromeo/lists"}