Comparing version 1.0.0-beta to 1.0.0
@@ -28,20 +28,27 @@ "use strict"; | ||
const keys = this.path.match(/:\w+/g); | ||
if (!keys) { | ||
this.paramKeys = []; | ||
return; | ||
const any = this.path.includes('*'); | ||
this.paramKeys = []; | ||
if (keys) { | ||
this.paramKeys = keys.map((m) => m.replace(':', '')); | ||
this._static = false; | ||
} | ||
this.paramKeys = keys.map((m) => m.replace(':', '')); | ||
this._static = false; | ||
if (any) { | ||
this._static = false; | ||
} | ||
} | ||
setRegex() { | ||
if (this.paramKeys.length) { | ||
if (!this._static) { | ||
// \\w+ | ||
this.regex = new RegExp(`^(${this.path.replace(/:\w+/g, '([A-Za-z0-9._-]+)')})$`); | ||
const expr = this.path.replace(/:\w+/g, '([A-Za-z0-9._-]+)').replace(/\*/g, '(.*)'); | ||
this.regex = new RegExp(`^(${expr})$`); | ||
} | ||
} | ||
match(method, path, params = {}) { | ||
matchMethod(method) { | ||
// route method should match with given method | ||
if (this.method != '*' && this.method !== method) { | ||
return false; | ||
if (this.method == '*' || this.method == method || (this.method == 'GET' && method == 'HEAD')) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
match(path, params = {}) { | ||
// in case path is without params | ||
@@ -48,0 +55,0 @@ if (this.path === path) { |
@@ -8,2 +8,3 @@ "use strict"; | ||
this.routes = []; | ||
this.middlewares = []; | ||
this.staticRoutes = {}; | ||
@@ -15,2 +16,7 @@ this.opts = { | ||
staticref: true, | ||
addMiddleware(route, middleware) { | ||
Array.isArray(route.handler) ? [middleware, ...route.handler] : [middleware, route.handler]; | ||
}, | ||
composeHandler(route) { | ||
}, | ||
...options, | ||
@@ -66,2 +72,3 @@ }; | ||
const route = new route_js_1.Route(method, this.makePath(path), handler); | ||
this.opts.composeHandler(route); | ||
this.routes.push(route); | ||
@@ -84,2 +91,3 @@ this.static(route); | ||
const route = new route_js_1.Route(method, path, handler); | ||
this.opts.composeHandler(route); | ||
this.routes.push(route); | ||
@@ -102,3 +110,3 @@ this.static(route); | ||
this.routes.push(...router.routes.map((route) => { | ||
route = route.clone(); | ||
// route = route.clone(); | ||
this.static(route); | ||
@@ -134,3 +142,9 @@ return route; | ||
} | ||
throw new Error('Expects an instance of Router.'); | ||
if (typeof what == 'function') { | ||
this.middlewares.push(what); | ||
if (this.routes.length) { | ||
this.routes.forEach(route => this.opts.addMiddleware(route, what)); | ||
} | ||
} | ||
throw new Error('Expects an instance of Router or a CallableFunction for middleware.'); | ||
} | ||
@@ -155,4 +169,4 @@ else if (args.length === 2) { | ||
const r = this.routes[i]; | ||
const matched = r.match(method, path, params); | ||
if (matched) { | ||
const matched = r.match(path, params); | ||
if (matched && r.matchMethod(method)) { | ||
return r; | ||
@@ -159,0 +173,0 @@ } |
@@ -25,20 +25,27 @@ export class Route { | ||
const keys = this.path.match(/:\w+/g); | ||
if (!keys) { | ||
this.paramKeys = []; | ||
return; | ||
const any = this.path.includes('*'); | ||
this.paramKeys = []; | ||
if (keys) { | ||
this.paramKeys = keys.map((m) => m.replace(':', '')); | ||
this._static = false; | ||
} | ||
this.paramKeys = keys.map((m) => m.replace(':', '')); | ||
this._static = false; | ||
if (any) { | ||
this._static = false; | ||
} | ||
} | ||
setRegex() { | ||
if (this.paramKeys.length) { | ||
if (!this._static) { | ||
// \\w+ | ||
this.regex = new RegExp(`^(${this.path.replace(/:\w+/g, '([A-Za-z0-9._-]+)')})$`); | ||
const expr = this.path.replace(/:\w+/g, '([A-Za-z0-9._-]+)').replace(/\*/g, '(.*)'); | ||
this.regex = new RegExp(`^(${expr})$`); | ||
} | ||
} | ||
match(method, path, params = {}) { | ||
matchMethod(method) { | ||
// route method should match with given method | ||
if (this.method != '*' && this.method !== method) { | ||
return false; | ||
if (this.method == '*' || this.method == method || (this.method == 'GET' && method == 'HEAD')) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
match(path, params = {}) { | ||
// in case path is without params | ||
@@ -45,0 +52,0 @@ if (this.path === path) { |
@@ -5,2 +5,3 @@ import { Route } from './route.js'; | ||
this.routes = []; | ||
this.middlewares = []; | ||
this.staticRoutes = {}; | ||
@@ -12,2 +13,7 @@ this.opts = { | ||
staticref: true, | ||
addMiddleware(route, middleware) { | ||
Array.isArray(route.handler) ? [middleware, ...route.handler] : [middleware, route.handler]; | ||
}, | ||
composeHandler(route) { | ||
}, | ||
...options, | ||
@@ -63,2 +69,3 @@ }; | ||
const route = new Route(method, this.makePath(path), handler); | ||
this.opts.composeHandler(route); | ||
this.routes.push(route); | ||
@@ -81,2 +88,3 @@ this.static(route); | ||
const route = new Route(method, path, handler); | ||
this.opts.composeHandler(route); | ||
this.routes.push(route); | ||
@@ -99,3 +107,3 @@ this.static(route); | ||
this.routes.push(...router.routes.map((route) => { | ||
route = route.clone(); | ||
// route = route.clone(); | ||
this.static(route); | ||
@@ -131,3 +139,9 @@ return route; | ||
} | ||
throw new Error('Expects an instance of Router.'); | ||
if (typeof what == 'function') { | ||
this.middlewares.push(what); | ||
if (this.routes.length) { | ||
this.routes.forEach(route => this.opts.addMiddleware(route, what)); | ||
} | ||
} | ||
throw new Error('Expects an instance of Router or a CallableFunction for middleware.'); | ||
} | ||
@@ -152,4 +166,4 @@ else if (args.length === 2) { | ||
const r = this.routes[i]; | ||
const matched = r.match(method, path, params); | ||
if (matched) { | ||
const matched = r.match(path, params); | ||
if (matched && r.matchMethod(method)) { | ||
return r; | ||
@@ -156,0 +170,0 @@ } |
{ | ||
"name": "repulser", | ||
"version": "1.0.0-beta", | ||
"description": "Routing library for node.js and browser", | ||
"version": "1.0.0", | ||
"description": "Routing library for javascript", | ||
"type": "module", | ||
@@ -6,0 +6,0 @@ "main": "./cjs/index.js", |
107
readme.md
@@ -21,3 +21,3 @@ # Repulser | ||
const stream = require('stream'); | ||
const { Router } = require('.'); | ||
const { Router } = require('../cjs'); | ||
@@ -84,4 +84,39 @@ function isReadableStream(obj) { | ||
router.any('/users/any/profile', async (ctx) => { | ||
switch (ctx.method) { | ||
case 'GET': | ||
ctx.reply({ message: 'Get user profile route!' }) | ||
break | ||
case 'POST': | ||
ctx.reply({ message: 'Create user profile route!' }) | ||
break | ||
case 'PUT': | ||
ctx.reply({ message: 'Update user profile route!' }) | ||
break | ||
case 'DELETE': | ||
ctx.reply({ message: 'Delete user profile route!' }) | ||
break | ||
default: | ||
ctx.reply({ message: 'Method not supported!' }) | ||
break | ||
} | ||
}); | ||
router.all(['GET', 'PUT', 'DELETE'], '/users/all/address', async (ctx) => { | ||
switch (ctx.method) { | ||
case 'GET': | ||
ctx.reply({ message: 'Get user address route!' }) | ||
break | ||
case 'PUT': | ||
ctx.reply({ message: 'Add/Update user address route!' }) | ||
break | ||
case 'DELETE': | ||
ctx.reply({ message: 'Delete user address route!' }) | ||
break | ||
} | ||
}); | ||
createServer(async (req, res) => { | ||
const ctx = { | ||
method: req.method, | ||
req, | ||
@@ -98,4 +133,6 @@ res, | ||
const route = router.find(req.method, ctx.url); | ||
ctx.params = {}; | ||
const route = router.find(req.method, ctx.url, ctx.params); | ||
if (!route) { | ||
@@ -109,4 +146,2 @@ res.statusCode = 404; | ||
ctx.params = route.params(); | ||
await route.handler(ctx); | ||
@@ -123,2 +158,9 @@ | ||
if (ctx.method == 'HEAD') { | ||
res.statusCode = 204; | ||
res.end(); | ||
return; | ||
} | ||
// handle json response | ||
@@ -297,13 +339,12 @@ if (ctx.response.type === 'application/json') { | ||
app.use(async (ctx, next) => { | ||
const route = router.find(ctx.method.toUpperCase(), ctx.url); | ||
ctx.params = {} | ||
const route = router.find(ctx.method.toUpperCase(), ctx.url, ctx.params); | ||
if (!route) { | ||
throw new Error('Page not found.'); | ||
} | ||
if (!route) { | ||
throw new Error('Page not found.'); | ||
} | ||
ctx.params = route.params(); | ||
await route.handler(ctx); | ||
await route.handler(ctx); | ||
await next(); | ||
await next(); | ||
}); | ||
@@ -316,12 +357,42 @@ ``` | ||
app.use((req, res, next) => { | ||
const route = router.find(req.method.toUpperCase(), req.url); | ||
req.params = {} | ||
const route = router.find(req.method.toUpperCase(), req.url, req.params); | ||
if (!route) { | ||
return next(new Error('Page not found.')); | ||
} | ||
if (!route) { | ||
return next(new Error('Page not found.')); | ||
} | ||
req.params = route.params(); | ||
await route.handler(req, res, next); | ||
}); | ||
``` | ||
await route.handler(req, res, next); | ||
**Extra Features** | ||
- router level middlewares | ||
```js | ||
const router = new Router({ | ||
/* | ||
note: route.handler will be converted to array | ||
you can modify the behaviour using | ||
addMiddleware(route: Route, middleware: CallableFunction) | ||
*/ | ||
}); | ||
router.use((ctx, next) => { | ||
// will add this middlewares to every route | ||
// note: route.handler will be converted to an Array (no change, if already an Array) | ||
}) | ||
``` | ||
- route handler modifier | ||
```js | ||
import compose from 'koa-compose'; | ||
const router = new Router({ | ||
composeHandler(route: Route) { | ||
route.handler = compose(route.handler) | ||
}, | ||
}); | ||
``` |
@@ -0,1 +1,2 @@ | ||
import { Route } from "./route.js"; | ||
export interface IRouterOptions { | ||
@@ -6,3 +7,5 @@ prefix: string; | ||
staticref: boolean; | ||
addMiddleware: (route: Route, middleware: CallableFunction) => any; | ||
composeHandler: (route: Route) => any; | ||
} | ||
export declare type HTTP_METHOD = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'HEAD' | 'OPTIONS'; |
@@ -17,3 +17,4 @@ /// <reference types="node" /> | ||
protected setRegex(): void; | ||
match(method: HTTP_METHOD, path: string, params?: NodeJS.Dict<string>): boolean; | ||
matchMethod(method: HTTP_METHOD): boolean; | ||
match(path: string, params?: NodeJS.Dict<string>): boolean; | ||
clone(): Route<T>; | ||
@@ -20,0 +21,0 @@ meta(meta?: NodeJS.Dict<any>): NodeJS.Dict<any>; |
@@ -7,2 +7,3 @@ /// <reference types="node" /> | ||
readonly opts: IRouterOptions; | ||
readonly middlewares: CallableFunction[]; | ||
readonly staticRoutes: NodeJS.Dict<Route>; | ||
@@ -9,0 +10,0 @@ constructor(options?: Partial<IRouterOptions>); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
45677
580
1
391