Skip to content

Commit

Permalink
Merge pull request #36 from lengfangbing/feat-update
Browse files Browse the repository at this point in the history
Feat update
  • Loading branch information
冷方冰 authored Sep 21, 2020
2 parents ec4dd4e + b03d145 commit d2f5666
Show file tree
Hide file tree
Showing 10 changed files with 70 additions and 65 deletions.
32 changes: 24 additions & 8 deletions decorator/decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,42 @@ import {
setRoutes,
clearRoutes,
setServer,
getMiddlewareInitial
getMiddlewareInitial,
getMiddlewares,
setMiddlewares,
clearMiddlewares,
} from "./entity.ts";
import {App} from "./app.ts";
import {DecorationApplication} from "./application.ts";
import {ListenOptions, MethodFuncArgument} from "../model.ts";

const consumeRoutes: ClassDecorator = (target: Function) => {
const consumeApplication: ClassDecorator = (target: Function) => {
const middleware = getMiddlewareInitial();
const router = getRouterInitial();
const path = target.prototype.decorator_prefix_min || '';
getMiddlewares().forEach(val => {
middleware.push(val);
});
getRoutes().forEach(val => {
router[val.method](path + val.path, val.handler, val.middleware);
});
clearMiddlewares();
clearRoutes();
}

const consumeRoutes: ClassDecorator = (target: Function) => {
const router = getRouterInitial();
const path = target.prototype.decorator_prefix_min || '';
getRoutes().forEach(val => {
router[val.method](path + val.path, val.handler, val.middleware.concat(getMiddlewares()));
});
clearMiddlewares();
clearRoutes();
}

const StartApplication: ClassDecorator = target => {
setApp(new DecorationApplication());
consumeRoutes(target);
consumeApplication(target);
return target;
}

Expand All @@ -39,16 +57,14 @@ const Prefix = (path: string): ClassDecorator => {
}

const Middleware: MethodDecorator = (target, propertyKey, descriptor: TypedPropertyDescriptor<any>) => {
const middleware = getMiddlewareInitial();
middleware.push(descriptor.value);
setMiddlewares(descriptor.value);
return descriptor;
}

const ApplyMiddleware = (args: MethodFuncArgument): MethodDecorator => {
const middleware = getMiddlewareInitial();
args.forEach(val => {
middleware.push(val);
})
setMiddlewares(val);
});
return (target, propertyKey, descriptor) => {
return descriptor;
}
Expand Down
5 changes: 2 additions & 3 deletions decorator/decorator.type.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import {Middleware} from "./middleware.ts";
import {DecorationApplication} from "./application.ts";
import {Router} from "./router.ts";
import {ListenOptions, Req, ReqMethod, Res} from "../model.ts";

export declare type MiddlewareFunc = (req: Req, res: Res, next?: Function) => Promise<unknown> | unknown;
import {ListenOptions, ReqMethod, MethodFuncArgument} from "../model.ts";

export declare type Entity = {
app: DecorationApplication | null,
Expand All @@ -16,4 +14,5 @@ export declare type Entity = {
middleware: Function[],
handler: Function,
}>;
middlewares: MethodFuncArgument;
};
15 changes: 14 additions & 1 deletion decorator/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import {Entity} from "./decorator.type.ts";
import {Middleware} from "./middleware.ts";
import {Router} from "./router.ts";
import {DecorationApplication} from "./application.ts";
import {ListenOptions} from "../model.ts";
import {ListenOptions, MiddlewareFunc} from "../model.ts";

const defaultServer = {
port: 8000,
Expand All @@ -15,6 +15,7 @@ const entity: Entity = {
server: defaultServer,
middleware: null,
routes: [],
middlewares: [],
};

export function getAppInitial(): DecorationApplication {
Expand Down Expand Up @@ -69,3 +70,15 @@ export function setRoutes(routes: Entity['routes'][number]) {
export function clearRoutes() {
entity.routes = [];
}

export function getMiddlewares() {
return entity.middlewares;
}

export function setMiddlewares(func: MiddlewareFunc) {
entity.middlewares.push(func);
}

export function clearMiddlewares() {
entity.middlewares = [];
}
3 changes: 3 additions & 0 deletions examples/decorator/demo2/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ export class TestClass extends App {
console.log('middle2 end');
}

// in @StartApplication class middleware will work for global
// but in @Route class , it will only work for that Route

@Get('/id/:id/info', [async (req: Req, res: Res, next: Function) => {
console.log(`I am a middleware func in ${req.url}`);
await next();
Expand Down
1 change: 1 addition & 0 deletions examples/decorator/demo2/routes/route1.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {Get, Route, Middleware, Req, Res} from "../deps.ts";
@Route
class Route1 {
@Middleware
// this middleware will only work for this Route
async middle3(req: Req, res: Res, next: Function) {
console.log('route1 middle');
await next();
Expand Down
1 change: 1 addition & 0 deletions examples/decorator/demo2/routes/route2.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {Get, Route, Prefix, Middleware, Req, Res} from "../deps.ts";
@Prefix('/route2')
class Route2 {
@Middleware
// this middleware will only work for this Route
async middle (req: Req, res: Res, next: Function) {
console.log('route2 middle');
await next();
Expand Down
22 changes: 11 additions & 11 deletions router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ export class Router {
if (!us.length) throw new Error('router.add first argument path is invalid, use /path instead');
let p: NewRoute | null = null;
let pm: NewRoute['paramsNames'] = {};
us.forEach((value: string | { paramsName: string }, index: number) => {
us.forEach((value: string | { key: string, paramsName: string }, index: number) => {
if (typeof value === 'string') {
if (p) {
if (p.next) {
Expand All @@ -85,27 +85,27 @@ export class Router {
}
} else {
if (p === null) {
if (fM['']) {
p = fM[''];
if (fM[value.key]) {
p = fM[value.key];
} else {
fM[''] = this.#initRoute();
p = fM[''];
fM[value.key] = this.#initRoute();
p = fM[value.key];
}
pm[index] = value.paramsName;
} else {
if (p.next) {
if (p.next['']) {
p = p.next[''];
if (p.next[value.key]) {
p = p.next[value.key];
} else {
p.next[''] = this.#initRoute();
p = p.next[''];
p.next[value.key] = this.#initRoute();
p = p.next[value.key];
}
pm[index] = value.paramsName;
} else {
p.next = {
'': this.#initRoute()
[value.key]: this.#initRoute()
}
p = p.next[''];
p = p.next[value.key];
pm[index] = value.paramsName;
}
}
Expand Down
23 changes: 11 additions & 12 deletions router_test.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import {
parseUrlQuery,
splitPath,
splitNewPath,
splitUrl
} from './utils/test/url_test.ts';

Expand Down Expand Up @@ -141,7 +140,7 @@ export class Router {
// p理解为一个查找路由这个数据结构的指针
let p: NewRoute | null = null;
let params: NewRoute['paramsNames'] = {};
urls.forEach((value: string | { paramsName: string }, index: number) => {
urls.forEach((value: string | { key: string, paramsName: string }, index: number) => {
// 静态路由
if (typeof value === 'string') {
// 如果p代表了有值了, 就代表funcMap有匹配项了
Expand Down Expand Up @@ -174,27 +173,27 @@ export class Router {
// 把所有动态路由都改成''(空字符串)索引的形式构造树
// 第一个就是动态路由
if (p === null) {
if (funcMap['']) {
p = funcMap[''];
if (funcMap[value.key]) {
p = funcMap[value.key];
} else {
funcMap[''] = this.#initRoute();
p = funcMap[''];
funcMap[value.key] = this.#initRoute();
p = funcMap[value.key];
}
params[index] = value.paramsName;
} else {
if (p.next) {
if (p.next['']) {
p = p.next[''];
if (p.next[value.key]) {
p = p.next[value.key];
} else {
p.next[''] = this.#initRoute();
p = p.next[''];
p.next[value.key] = this.#initRoute();
p = p.next[value.key];
}
params[index] = value.paramsName;
} else {
p.next = {
'': this.#initRoute()
[value.key]: this.#initRoute()
}
p = p.next[''];
p = p.next[value.key];
params[index] = value.paramsName;
}
}
Expand Down
4 changes: 2 additions & 2 deletions utils/parse/url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,15 +83,15 @@ export function splitPath(path: string){
const v = url.substring(0, i);
let j = 0;
if((j = v.indexOf(':')) >= 0){
res.push({paramsName: v.substring(j+1)});
res.push({key: '', paramsName: v.substring(j+1)});
}else{
res.push(`/${v}`);
}
url = url.substring(i+1);
}
if(url.length){
if((i = url.indexOf(':')) >= 0){
res.push({paramsName: url.substring(i+1)});
res.push({key: '', paramsName: url.substring(i+1)});
}else{
res.push(`/${url}`);
}
Expand Down
29 changes: 1 addition & 28 deletions utils/test/url_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,29 +69,6 @@ export function splitUrl(url: string){
}

export function splitPath(path: string){
const res = [];
let url = path.substring(1) || '/';
let i = 0;
while((i = url.indexOf('/')) >= 0){
const v = url.substring(0, i);
let j = 0;
if((j = v.indexOf(':')) >= 0){
res.push({paramsName: v.substring(j+1)});
}else{
res.push(`/${v}`);
}
url = url.substring(i+1);
}
if(url.length){
if((i = url.indexOf(':')) >= 0){
res.push({paramsName: url.substring(i+1)});
}else{
res.push(`/${url}`);
}
}
return res;
}
export function splitNewPath(path: string){
const res = [];
let url = path.substring(1) || '/';
let i = 0;
Expand All @@ -100,8 +77,6 @@ export function splitNewPath(path: string){
let j = 0;
if((j = v.indexOf(':')) >= 0){
res.push({key: '', paramsName: v.substring(j+1)});
}else if((j = v.indexOf('*')) >= 0){
res.push({key: '#', paramsName: v.substring(j+1)});
}else{
res.push(`/${v}`);
}
Expand All @@ -110,8 +85,6 @@ export function splitNewPath(path: string){
if(url.length){
if((i = url.indexOf(':')) >= 0){
res.push({key: '', paramsName: url.substring(i+1)});
}else if((i = url.indexOf('*')) >= 0){
res.push({key: '#', paramsName: url.substring(i+1)});
}else{
res.push(`/${url}`);
}
Expand Down Expand Up @@ -154,5 +127,5 @@ export function parseResponseCookie(options?: Record<string, unknown>){
return res.join(';');
}
assertEquals('domain=.foo.com;Path=/;secure;httpOnly', parseResponseCookie({domain: '.foo.com', Path: '/', secure: true, httpOnly: true}));
assertEquals(['/name', {paramsName: 'id'}, '/v1'], splitPath('/name/:id/v1'));
assertEquals(['/name', {key: '', paramsName: 'id'}, '/v1'], splitPath('/name/:id/v1'));
assertEquals(['/name', '/fangbing', '/v1'], splitUrl('/name/fangbing/v1'));

0 comments on commit d2f5666

Please sign in to comment.