Skip to content

Commit

Permalink
Update to RC.8
Browse files Browse the repository at this point in the history
  • Loading branch information
kamil.mysliwiec committed Apr 11, 2017
1 parent e161627 commit ad10000
Show file tree
Hide file tree
Showing 11 changed files with 175 additions and 52 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## 1.0.0-RC7 (08.04.2017)

- MiddlewareBuilder: `use()` deprecated, use `apply()` instead
- MiddlewareBuilder: new `apply()` method

## 1.0.0-RC4 (08.04.2017)

- Support for @Post, @Get, @Delete, @Put, @All decorators
Expand Down
19 changes: 9 additions & 10 deletions example/modules/users/users.module.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,8 @@
import { Module } from './../../../src/';
import { UsersController } from './users.controller';
import { UsersService } from './users.service';
import { AuthMiddleware } from './auth.middleware';
import { MiddlewareBuilder } from '../../../src/core/middlewares/builder';
import { ProvideValues } from '../../../src/common/utils/provide-values.util';

const ProvideRoles = ProvideValues({
role: ['admin', 'user']
});
import { AuthMiddleware } from './auth.middleware';

@Module({
controllers: [ UsersController ],
Expand All @@ -21,12 +16,16 @@ export class UsersModule {
}

configure(builder: MiddlewareBuilder) {
builder.use({
builder.apply(AuthMiddleware)
.with('admin', 'creator', 'editor')
.forRoutes(UsersController);

/* builder.use({
middlewares: [
ProvideRoles(AuthMiddleware)
AuthMiddleware
],
forRoutes: [ UsersController]
});
forRoutes: [ UsersController ]
});*/
}
}

Expand Down
29 changes: 29 additions & 0 deletions src/common/test/utils/bind-resolve-values.util.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'mocha';
import 'reflect-metadata';
import { expect } from 'chai';
import { BindResolveMiddlewareValues } from '../../utils/bind-resolve-values.util';
import { NestMiddleware } from '../../../core/middlewares/interfaces/nest-middleware.interface';

describe('BindResolveMiddlewareValues', () => {
let type,
arg1 = 3,
arg2 = 4;

class Test implements NestMiddleware {
resolve(a, b) {
return () => [a, b];
}
}

beforeEach(() => {
type = BindResolveMiddlewareValues([ arg1, arg2 ])(Test);
});
it('should pass values to resolve() method', () => {
const obj = new type();
const hof = obj.resolve();
expect(hof()).to.deep.equal([arg1, arg2]);
});
it('should set name of metatype', () => {
expect(type.name).to.eq((<any>Test).name + JSON.stringify([ arg1, arg2 ]));
});
});
1 change: 0 additions & 1 deletion src/common/test/utils/component.decorator.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import 'reflect-metadata';
import 'mocha';
import { expect } from 'chai';
import { Component } from '../../utils/component.decorator';

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import 'reflect-metadata';
import { expect } from 'chai';
import { ProvideValues } from '../../utils/provide-values.util';
import { MergeWithValues } from '../../utils/merge-with-values.util';

describe('ProvideValues', () => {
describe('MergeWithValues', () => {
let type, data = { test: [ 1, 2, 3 ] };
class Test {}

beforeEach(() => {
type = ProvideValues(data)(Test);
type = MergeWithValues(data)(Test);
});
it('should enrich prototype with given values', () => {
expect(type.prototype).to.contain(data);
Expand Down
15 changes: 15 additions & 0 deletions src/common/utils/bind-resolve-values.util.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { Constructor } from './merge-with-values.util';
import { NestMiddleware } from '../../core/middlewares/interfaces/nest-middleware.interface';

export const BindResolveMiddlewareValues = <T extends Constructor<NestMiddleware>>(data: Array<any>) => {
return (metatype: T): any => {
const type = class extends metatype {
resolve() {
return super.resolve(...data);
}
};
const token = metatype.name + JSON.stringify(data);
Object.defineProperty(type, 'name', { value: token });
return type;
}
};
2 changes: 1 addition & 1 deletion src/common/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ export * from './module.decorator';
export * from './dependencies.decorator';
export * from './inject.decorator';
export { Component as Middleware } from './component.decorator';
export * from './provide-values.util';
export * from './merge-with-values.util';
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
import 'reflect-metadata';

interface Constructor<T> {
export interface Constructor<T> {
new(...args: any[]): T
}

export const ProvideValues = <T extends Constructor<{}>>(data) => {
return (metatype: T) => {
export const MergeWithValues = <T extends Constructor<{}>>(data: { [param: string]: any }) => {
return (metatype: T): any => {
const type = class extends metatype {
constructor(...args) {
super(args);
super(...args);
}
};
const token = metatype.name + JSON.stringify(data);
Object.defineProperty(type, 'name', { value: token });
Object.assign(type.prototype, data);
return type;
}
};
};
52 changes: 48 additions & 4 deletions src/core/middlewares/builder.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,66 @@
import { MiddlewareConfiguration } from './interfaces/middleware-configuration.interface';
import { InvalidMiddlewareConfigurationException } from '../../errors/exceptions/invalid-middleware-configuration.exception';
import { isUndefined } from '../../common/utils/shared.utils';
import { isUndefined, isNil } from '../../common/utils/shared.utils';
import { BindResolveMiddlewareValues } from '../../common/utils/bind-resolve-values.util';
import { Logger } from '../../common/services/logger.service';
import { Metatype } from '../../common/interfaces/metatype.interface';

export class MiddlewareBuilder {
private storedConfiguration = new Set<MiddlewareConfiguration>();
private middlewaresCollection = new Set<MiddlewareConfiguration>();
private logger = new Logger(MiddlewareBuilder.name);

apply(metatypes: Metatype<any> | Array<Metatype<any>>): MiddlewareConfigProxy {
let resolveParams = null;
const configProxy = {
with: (...data) => {
resolveParams = data;
return configProxy as MiddlewareConfigProxy;
},
forRoutes: (routes) => {
if (isUndefined(routes)) {
throw new InvalidMiddlewareConfigurationException();
}
const configuration = {
middlewares: this.bindValuesToResolve(metatypes, resolveParams),
forRoutes: [].concat(routes)
};
this.middlewaresCollection.add(<MiddlewareConfiguration>configuration);
return this;
}
};
return configProxy;
}

/**
* @deprecated
* Since version RC.6 this method is deprecated. Use apply() instead.
*/
use(configuration: MiddlewareConfiguration) {
this.logger.warn('DEPRECATED! Since version RC.6 `use()` method is deprecated. Use `apply()` instead.');

const { middlewares, forRoutes } = configuration;
if (isUndefined(middlewares) || isUndefined(forRoutes)) {
throw new InvalidMiddlewareConfigurationException();
}

this.storedConfiguration.add(configuration);
this.middlewaresCollection.add(configuration);
return this;
}

build() {
return [ ...this.storedConfiguration ];
return [ ...this.middlewaresCollection ];
}

private bindValuesToResolve(middlewares: Metatype<any> | Array<Metatype<any>>, resolveParams: Array<any>) {
if (isNil(resolveParams)) {
return middlewares;
}
const bindArgs = BindResolveMiddlewareValues(resolveParams);
return [].concat(middlewares).map(bindArgs);
}
}

export interface MiddlewareConfigProxy {
with: (...data) => MiddlewareConfigProxy;
forRoutes: (routes) => MiddlewareBuilder;
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Request, Response, NextFunction } from 'express';

export interface NestMiddleware {
resolve: () => (req?: Request, res?: Response, next?: NextFunction) => void;
resolve(...args): (req?: Request, res?: Response, next?: NextFunction) => void;
}
86 changes: 59 additions & 27 deletions src/core/test/middlewares/builder.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,38 +8,70 @@ describe('MiddlewareBuilder', () => {
beforeEach(() => {
builder = new MiddlewareBuilder();
});

it('should store configuration passed as argument', () => {
builder.use(<any>{
middlewares: 'Test',
forRoutes: 'Test'
describe('apply', () => {
let configProxy;
beforeEach(() => {
configProxy = builder.apply([]);
});
it('should return configuration proxy', () => {
expect(configProxy).to.have.keys('with', 'forRoutes');
});
describe('configuration proxy', () => {
it('should returns itself on "with()" call', () => {
expect(configProxy.with()).to.be.eq(configProxy);
});
describe('when "forRoutes()" called', () => {
class Test {}
it('should throws "InvalidMiddlewareConfigurationException" when passed argument is undefined', () => {
expect(() => configProxy.forRoutes()).to.throws(
InvalidMiddlewareConfigurationException
);
});
it('should store configuration passed as argument', () => {
configProxy.forRoutes(Test);

expect(builder.build()).to.deep.equal([{
middlewares: 'Test',
forRoutes: 'Test'
}]);
expect(builder.build()).to.deep.equal([{
middlewares: [],
forRoutes: [ Test ]
}]);
});
});
});
});

it('should be possible to chain "use" calls', () => {
builder.use(<any>{
middlewares: 'Test',
forRoutes: 'Test'
}).use(<any>{
middlewares: 'Test',
forRoutes: 'Test'
describe('use', () => {
it('should store configuration passed as argument', () => {
builder.use(<any>{
middlewares: 'Test',
forRoutes: 'Test'
});

expect(builder.build()).to.deep.equal([{
middlewares: 'Test',
forRoutes: 'Test'
}]);
});
expect(builder.build()).to.deep.equal([<any>{
middlewares: 'Test',
forRoutes: 'Test'
}, <any>{
middlewares: 'Test',
forRoutes: 'Test'
}]);
});

it('should throw exception when middleware configuration object is invalid', () => {
expect(builder.use.bind(builder, 'test')).throws(InvalidMiddlewareConfigurationException);
});
it('should be possible to chain "use" calls', () => {
builder.use(<any>{
middlewares: 'Test',
forRoutes: 'Test'
}).use(<any>{
middlewares: 'Test',
forRoutes: 'Test'
});
expect(builder.build()).to.deep.equal([<any>{
middlewares: 'Test',
forRoutes: 'Test'
}, <any>{
middlewares: 'Test',
forRoutes: 'Test'
}]);
});

it('should throw exception when middleware configuration object is invalid', () => {
expect(builder.use.bind(builder, 'test')).throws(InvalidMiddlewareConfigurationException);
});

});
});

0 comments on commit ad10000

Please sign in to comment.