Skip to content

Commit

Permalink
Merge branch 'release/2.0.0-beta.6'
Browse files Browse the repository at this point in the history
  • Loading branch information
hirsch88 committed Nov 18, 2017
2 parents 87e29b1 + e4faa9e commit 3da310e
Show file tree
Hide file tree
Showing 22 changed files with 566 additions and 298 deletions.
13 changes: 9 additions & 4 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
APP_NAME="express-typescript-boilerplate"
APP_ENV="local"
APP_HOST="http://localhost"
APP_HOST="http://localhost:3000"
APP_URL_PREFIX="/api"
APP_PORT=3000

Expand All @@ -13,6 +13,12 @@ APP_PORT=3000
LOG_LEVEL="debug"
LOG_ADAPTER="winston"

#
# APPLICATION
#
APP_BASIC_USER="admin"
APP_BASIC_PASSWORD="1234"

#
# API Info
#
Expand All @@ -23,14 +29,14 @@ API_INFO_ROUTE="/info"
# Swagger Documentation
#
SWAGGER_ENABLED=true
SWAGGER_ROUTE="/docs"
SWAGGER_ROUTE="/swagger"
SWAGGER_FILE="/src/api/swagger.json"

#
# Monitor
#
MONITOR_ENABLED=true
MONITOR_ROUTE="/status"
MONITOR_ROUTE="/monitor"

#
# DATABASE
Expand All @@ -53,5 +59,4 @@ DB_SEEDS_DIR="./src/database/seeds"
#
# Auth0
#
# AUTH0_HOST="https://w3tecch.auth0.com"
AUTH0_HOST="http://localhost:3333"
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ node_js:
install:
- yarn install
scripts:
- npm test
- npm run build
- nps test
- nps build
notifications:
email: false
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ Try it!! We are happy to hear your feedback or any kind of new features.
- **Easy Exception Handling** with our own simple and easy to adopt logic. You will love it.
- **Easy Data Seeding** with our own factories.
- **Custom Commands** are also available in our setup and really easy to use or even extend.
- **Custom Validators** to validate your request even better and stricter. [custom-validation-classes](https://github.com/pleerock/class-validator#custom-validation-classes)
- **Scaffolding Commands** will speed up your development tremendously as you should focus on business code and not scaffolding.
- **Smart Validation** thanks to [class-validator](https://github.com/pleerock/class-validator) with some nice annotations.
- **API Documentation** thanks to [swagger](http://swagger.io/).
Expand Down Expand Up @@ -152,7 +153,7 @@ All script are defined in the package.json file, but the most important ones are
* There is also a vscode task for this called `lint`.

### Tests
* Run the unit tests using `npm test` (There is also a vscode task for this called `test`).
* Run the unit tests using `nps test` (There is also a vscode task for this called `test`).
* Run the e2e tests using `nps test:e2e` and don't forget to start your application and your [Auth0 Mock Server](https://github.com/hirsch88/auth0-mock-server).

### Running in dev mode
Expand Down Expand Up @@ -185,6 +186,7 @@ All the templates for the commands are located in `src/console/templates`.
* `npm run console make:request <file>` - Generates a basic request.
* `npm run console make:listener <file>` - Generates a basic listener.
* `npm run console make:exception <file>` - Generates a basic exception.
* `npm run console make:validator <file>` - Generates a custom validator.
* `npm run console update:targets <file>` - Reads all the API files and generate a new `constants/Targets.ts` file out of it.

**Example**
Expand Down Expand Up @@ -230,6 +232,7 @@ The route prefix is `/api` by default, but you can change this in the .env file.
| **src/api/repositories/** | Repository / DB layer |
| **src/api/requests/** | Request bodys with validations |
| **src/api/services/** | Service layer |
| **src/api/validators/** | Custom validators, which can be used in the request classes |
| **src/api/** swagger.json | Swagger documentation |
| **src/console/** | Command line scripts |
| **src/config/** | Configurations like database or logger |
Expand Down
4 changes: 2 additions & 2 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ install:
- yarn install

build_script:
- npm run build
- nps build

test_script:
- npm test
- nps test
8 changes: 7 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
{
"name": "express-typescript-boilerplate",
"version": "2.0.0-beta.5",
"version": "2.0.0-beta.6",
"description": "A delightful way to building a RESTful API with NodeJs & TypeScript",
"main": "src/app.ts",
"engines": {
"node": "8.2.1"
},
"scripts": {
"start": "node dist/app.js",
"test": "nps test",
Expand Down Expand Up @@ -60,6 +63,7 @@
"@types/request": "^2.0.7",
"@types/request-promise": "^4.1.39",
"@types/serve-favicon": "^2.2.29",
"@types/uuid": "^3.4.3",
"@types/winston": "^2.3.7",
"body-parser": "^1.18.2",
"bookshelf": "^0.10.4",
Expand All @@ -72,6 +76,7 @@
"cors": "^2.8.4",
"dotenv": "^4.0.0",
"express": "^4.16.2",
"express-basic-auth": "^1.1.3",
"express-status-monitor": "^1.0.1",
"faker": "^4.1.0",
"figlet": "^1.2.0",
Expand Down Expand Up @@ -99,6 +104,7 @@
"ts-node": "^3.3.0",
"tslint": "^5.8.0",
"typescript": "^2.6.1",
"uuid": "^3.1.0",
"wait-on": "^2.0.2",
"winston": "^2.4.0"
},
Expand Down
4 changes: 3 additions & 1 deletion src/api/requests/user/UserCreateRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IsEmail, IsNotEmpty } from 'class-validator';
import { IsEmail, IsNotEmpty, Validate } from 'class-validator';
import { RequestBody } from '../../../core/api/RequestBody';
import { EndsWithValidator } from '../../Validators/EndsWithValidator';

/**
* This class is used for create request. Create a new instance
Expand All @@ -20,6 +21,7 @@ export class UserCreateRequest extends RequestBody {

@IsNotEmpty()
@IsEmail()
@Validate(EndsWithValidator, ['@gmail.com', '@w3tec.ch'])
public email: string;

public picture: string;
Expand Down
4 changes: 3 additions & 1 deletion src/api/requests/user/UserUpdateRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { IsEmail, IsNotEmpty } from 'class-validator';
import { IsEmail, IsNotEmpty, Validate } from 'class-validator';
import { RequestBody } from '../../../core/api/RequestBody';
import { EndsWithValidator } from '../../Validators/EndsWithValidator';

/**
* This class is used for update request. Create a new instance
Expand All @@ -19,6 +20,7 @@ export class UserUpdateRequest extends RequestBody {
public lastName: string;

@IsEmail()
@Validate(EndsWithValidator, ['@gmail.com', '@w3tec.ch'])
public email: string;

@IsNotEmpty()
Expand Down
21 changes: 21 additions & 0 deletions src/api/validators/EndsWithValidator.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import * as _ from 'lodash';
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';


@ValidatorConstraint({ name: 'endsWith', async: false })
export class EndsWithValidator implements ValidatorConstraintInterface {

public validate(text: string, args: ValidationArguments): boolean {
for (const ending of args.constraints) {
if (_.endsWith(text, ending)) {
return true;
}
}
return false;
}

public defaultMessage(args: ValidationArguments): string {
return 'Incorrect suffix';
}

}
4 changes: 2 additions & 2 deletions src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,13 @@

import 'reflect-metadata';
import { App } from './core/App';
import { CustomConfig } from './config/CustomConfig';
import { CustomHeaderConfig } from './config/CustomHeaderConfig';

export const app = new App();


// Here you can add more custom configurations
app.configure(new CustomConfig());
app.configure(new CustomHeaderConfig());

// Launch the server with all his awesome features.
app.bootstrap();
20 changes: 0 additions & 20 deletions src/config/CustomConfig.ts

This file was deleted.

31 changes: 31 additions & 0 deletions src/config/CustomHeaderConfig.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* config.Custom
* ------------------------------------
*
* Define all log adapters for this application and chose one.
*/

import * as express from 'express';
import * as uuid from 'uuid';

import { Logger } from '../core/Logger';
import { App, Configurable } from '../core/App';
import { Environment } from '../core/helpers/Environment';


export class CustomHeaderConfig implements Configurable {

private log = new Logger(__filename);

public configure(app: App): void {
this.log.debug('Add custom headers');

app.Express.use((req: express.Request, res: express.Response, next: express.NextFunction) => {
res.setHeader('X-API-VERSION', Environment.getPkg().version);
res.setHeader('X-Request-Id', uuid.v4());
next();
});

}
}

20 changes: 20 additions & 0 deletions src/console/MakeValidatorCommand.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
/**
* MakeValidatorCommand
* -------------------------------------
*
*/
import { AbstractMakeCommand } from './lib/AbstractMakeCommand';


export class MakeValidatorCommand extends AbstractMakeCommand {

public static command = 'make:validator';
public static description = 'Generate new validator';

public type = 'Validator';
public suffix = 'Validator';
public template = 'validator.hbs';
public target = 'api/validators';
public updateTargets = false;

}
17 changes: 17 additions & 0 deletions src/console/templates/validator.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ValidatorConstraint, ValidatorConstraintInterface, ValidationArguments } from 'class-validator';


@ValidatorConstraint({ name: '{{name.normal}}', async: false })
export class {{name.capitalize}}Validator implements ValidatorConstraintInterface {

public validate(text: string, args: ValidationArguments): boolean {
// Place your validation here
return true;
}

public defaultMessage(args: ValidationArguments): string {
// Error message if the validation fails
return 'Incorrect value';
}

}
8 changes: 4 additions & 4 deletions src/core/ApiInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export class ApiInfo {
return process.env.APP_URL_PREFIX + process.env.API_INFO_ROUTE;
}

public setup(app: express.Application): void {
public setup(application: express.Application): void {
if (Environment.isTruthy(process.env.API_INFO_ENABLED)) {
app.get(
application.get(
ApiInfo.getRoute(),
// @ts-ignore: False type definitions from express
(req: myExpress.Request, res: myExpress.Response) => {
Expand All @@ -22,11 +22,11 @@ export class ApiInfo {
};
if (Environment.isTruthy(process.env.SWAGGER_ENABLED)) {
links.links['swagger'] =
`${app.get('host')}:${app.get('port')}${SwaggerUI.getRoute()}`;
`${application.get('host')}${SwaggerUI.getRoute()}`;
}
if (Environment.isTruthy(process.env.MONITOR_ENABLED)) {
links.links['monitor'] =
`${app.get('host')}:${app.get('port')}${ApiMonitor.getRoute()}`;
`${application.get('host')}${ApiMonitor.getRoute()}`;
}
return res.json({
name: pkg.name,
Expand Down
3 changes: 2 additions & 1 deletion src/core/ApiMonitor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as express from 'express';
import * as monitor from 'express-status-monitor';
import { Environment } from './helpers/Environment';
import { BasicAuthentication } from './BasicAuthentication';


export class ApiMonitor {
Expand All @@ -12,7 +13,7 @@ export class ApiMonitor {
public setup(app: express.Application): void {
if (Environment.isTruthy(process.env.MONITOR_ENABLED)) {
app.use(monitor());
app.get(ApiMonitor.getRoute(), monitor().pageRoute);
app.get(ApiMonitor.getRoute(), BasicAuthentication(), monitor().pageRoute);
}
}
}
11 changes: 11 additions & 0 deletions src/core/BasicAuthentication.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import * as basicAuth from 'express-basic-auth';


export const BasicAuthentication = (): any => {
return basicAuth({
users: {
[process.env.APP_BASIC_USER]: process.env.APP_BASIC_PASSWORD
},
challenge: true
});
};
8 changes: 4 additions & 4 deletions src/core/Server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,21 +65,21 @@ export class Server {
*/
public onStartUp(app: express.Application): void {
this.log.debug(``);
this.log.debug(`Aloha, your app is ready on ${app.get('host')}:${app.get('port')}${process.env.APP_URL_PREFIX}`);
this.log.debug(`Aloha, your app is ready on ${app.get('host')}${process.env.APP_URL_PREFIX}`);
this.log.debug(`To shut it down, press <CTRL> + C at any time.`);
this.log.debug(``);
this.log.debug('-------------------------------------------------------');
this.log.debug(`Environment : ${Environment.getNodeEnv()}`);
this.log.debug(`Version : ${Environment.getPkg().version}`);
this.log.debug(``);
if (Environment.isTruthy(process.env.API_INFO_ENABLED)) {
this.log.debug(`API Info : ${app.get('host')}:${app.get('port')}${ApiInfo.getRoute()}`);
this.log.debug(`API Info : ${app.get('host')}${ApiInfo.getRoute()}`);
}
if (Environment.isTruthy(process.env.SWAGGER_ENABLED)) {
this.log.debug(`Swagger : ${app.get('host')}:${app.get('port')}${SwaggerUI.getRoute()}`);
this.log.debug(`Swagger : ${app.get('host')}${SwaggerUI.getRoute()}`);
}
if (Environment.isTruthy(process.env.MONITOR_ENABLED)) {
this.log.debug(`Monitor : ${app.get('host')}:${app.get('port')}${ApiMonitor.getRoute()}`);
this.log.debug(`Monitor : ${app.get('host')}${ApiMonitor.getRoute()}`);
}
this.log.debug('-------------------------------------------------------');
this.log.debug('');
Expand Down

0 comments on commit 3da310e

Please sign in to comment.