Skip to content

Commit cebfb14

Browse files
author
hirsch88
committed
Merge branch 'release/2.0.0-beta.2'
2 parents 5e9dcb7 + 83c401e commit cebfb14

40 files changed

+643
-466
lines changed

README.md

Lines changed: 98 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,27 +40,104 @@ Try it!! We are happy to hear your feedback or any kind of new features.
4040
- **Integrated Testing Tool** thanks to [Wallaby.js](https://wallabyjs.com/)
4141

4242
## Getting Started
43-
### Prerequisites
44-
* Install [Node.js](http://nodejs.org)
45-
* on OSX use [homebrew](http://brew.sh) `brew install node`
46-
* on Windows use [chocolatey](https://chocolatey.org/) `choco install nodejs`
47-
* Install yarn globally `npm install yarn -g`
48-
49-
### Installing
50-
* `fork` this repo
51-
* `clone` your fork
52-
* `cp .env.example .env` to copy the example .env file and enter your database connection
53-
* Create a new database. You will find the name in the .env file.
54-
* Run `npm run setup` or enter the following commands manually:
55-
* `yarn install` to install all dependencies and typings.
56-
* `npm run db:migrate` to create the schema.
57-
* `npm run db:seed` to insert some test data.
58-
* `npm run serve` to start the application.
59-
60-
### Running the app
61-
After you have installed all dependencies you can run the app.
62-
Enter `npm run serve` to start a local server using `nodemon`, which will watch for any file changes and will restart the sever according to these changes.
63-
The server address will be displayed to you as `http://0.0.0.0:3000`.
43+
### Step 1: Set up the Development Environment
44+
You need to set up your development environment before you can do anything.
45+
46+
Install [Node.js and NPM](https://nodejs.org/en/download/)
47+
* on OSX use [homebrew](http://brew.sh) `brew install node`
48+
* on Windows use [chocolatey](https://chocolatey.org/) `choco install nodejs`
49+
50+
Install yarn globally
51+
```
52+
npm install yarn -g
53+
```
54+
55+
Install a MySQL database.
56+
57+
> If you work with a mac, we recommend to use homebrew for the installation.
58+
59+
### Step 2: Create new Project
60+
Fork or download this project. Configure your package.json for your new project.
61+
62+
Then copy the `example.env` file and rename it to `.env`. In this file you have to add your database connection information.
63+
64+
Create a new database with the name you have in your `.env`-file.
65+
66+
Then setup your application environment.
67+
```
68+
npm run setup
69+
```
70+
71+
> This installs all dependencies with yarn. After that it migrates the database and seeds some test data into it. So after that your development environment is ready to use.
72+
73+
### Step 3: Serve your App
74+
Go to the project dir and start your app with this npm script.
75+
```
76+
npm run serve
77+
```
78+
79+
> This starts a local server using `nodemon`, which will watch for any file changes and will restart the sever according to these changes.
80+
> The server address will be displayed to you as `http://0.0.0.0:3000`.
81+
82+
### Step 4: Create a new Resource
83+
Go to the project dir and hit this command in your terminal.
84+
```
85+
npm run console make:resource
86+
```
87+
88+
Apply the same information like you see in the screenshot below.
89+
90+
![console](console.png)
91+
92+
> With that you just have created a complete new endpoint in your api for the resource pets.
93+
94+
Normally a pet belogns to a user, so we have to add the relationship between users an pets. Open the created migration file and replace the user property with these lines.
95+
```
96+
table.integer('user_id').unsigned();
97+
table.foreign('user_id').references('id').inTable('users').onDelete('cascade');
98+
```
99+
100+
Next we have to add this relationship also in the pets model.
101+
```
102+
public user(): User {
103+
return this.belongsTo(User);
104+
}
105+
```
106+
107+
> The relationship between the users and pets are set and ready. So you can migrate your database with `npm run db:migrate`
108+
109+
### Step 5: Create a Seeder
110+
To seed some cute pets we need a smart factory. So open the ./src/database/factories/index.ts and add this code.
111+
```
112+
/**
113+
* PET - Factory
114+
*/
115+
factory.define(Pet, (faker: Faker.FakerStatic, args: any[]) => {
116+
const type = args[0];
117+
return {
118+
name: faker.name.firstName(),
119+
type: type || 'dog',
120+
userId: factory.get(User).returning('id')
121+
};
122+
});
123+
```
124+
125+
> This factory helps us to create a fake pet to seed to the database.
126+
127+
Run this command in your terminal and call the new seeder `create pets`.
128+
```
129+
npm run console make:seed
130+
```
131+
132+
Open the file and place this code into it.
133+
```
134+
await factory.get(Pet)
135+
.create(10);
136+
```
137+
138+
> Now we can seed some nice cats into the database with `npm run db:seed`.
139+
140+
> That was easy! Now its your turn to make something great out of it.
64141
65142
## Scripts / Tasks
66143
All script are defined in the package.json file, but the most important ones are listed here.

console.png

99.4 KB
Loading

knexfile.js

Lines changed: 0 additions & 17 deletions
This file was deleted.

knexfile.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
require('dotenv').config();
2+
3+
/**
4+
* This is the database configuration for the migrations and
5+
* the seeders.
6+
*/
7+
module.exports = require('./src/config/Database').DatabaseConfig;

nodemon.json

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
{
22
"delay": "0",
33
"execMap": {
4-
"ts": "./node_modules/.bin/ts-node"
4+
"ts": "ts-node"
55
},
66
"events": {
7-
"start": "./node_modules/.bin/tslint -c ./tslint.json -t stylish 'src/**/*.ts'",
8-
"restart": "osascript -e 'display notification \"restarting server\" with title \"node.js application\"'"
7+
"start": "tslint -c ./tslint.json -t stylish 'src/**/*.ts'"
98
}
109
}

package.json

Lines changed: 37 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,37 +1,37 @@
11
{
22
"name": "express-typescript-boilerplate",
3-
"version": "2.0.0-beta.1",
3+
"version": "2.0.0-beta.2",
44
"description": "A delightful way to building a RESTful API with NodeJs & TypeScript",
55
"main": "src/app.ts",
66
"scripts": {
7-
"banner": "npm run ts-node:fast -- ./src/console/lib/banner.ts",
8-
"ts-node": "./node_modules/.bin/ts-node",
9-
"ts-node:fast": "./node_modules/.bin/ts-node -F",
7+
"setup": "yarn install && npm run banner setup && npm run db:migrate && npm run db:seed",
8+
"serve": "npm run banner serve && \"./node_modules/.bin/nodemon\" --watch src --watch .env",
9+
"build": "npm run banner build && npm run lint && npm run clean:dist && npm run transpile && npm run copy:assets",
10+
"start": "node dist/app.js",
1011
"pretest": "./node_modules/.bin/tslint -c ./tslint.json -t stylish './test/unit/**/*.ts'",
12+
"test": "npm run banner test && cross-env NODE_ENV=test \"./node_modules/.bin/jest\" --testPathPattern=unit",
1113
"test:pretty": "npm run test -- --verbose",
1214
"test:coverage": "npm run test -- --coverage",
1315
"pretest:black-box": "./node_modules/.bin/tslint -c ./tslint.json -t stylish './test/black-box/**/*.ts'",
14-
"test:black-box": "npm run banner test && NODE_ENV=test ./node_modules/.bin/jest ./test/black-box -i",
16+
"test:black-box": "npm run banner test && cross-env NODE_ENV=test \"./node_modules/.bin/jest\" --testPathPattern=black-box -i",
1517
"test:black-box:pretty": "npm run test:black-box -- --verbose",
18+
"db:migrate": "npm run banner migrate && \"./node_modules/.bin/knex\" migrate:latest",
19+
"db:migrate:rollback": "npm run banner rollback && \"./node_modules/.bin/knex\" migrate:rollback",
20+
"db:seed": "npm run banner seed && \"./node_modules/.bin/knex\" seed:run",
21+
"db:reset": "npm run console db:reset",
22+
"console": "npm run ts-node:fast -- ./src/console/lib/console.ts",
23+
"console:dev": "npm run ts-node -- ./src/console/lib/console.ts",
24+
"console:help": "npm run ts-node:fast -- ./src/console/lib/console.ts --help",
1625
"lint": "./node_modules/.bin/tslint -c ./tslint.json -p tsconfig.json 'src/**/*.ts' --format stylish",
1726
"transpile": "./node_modules/.bin/tsc",
27+
"clean": "npm run banner clean && npm run clean:dist",
1828
"clean:dist": "./node_modules/.bin/trash './dist'",
1929
"copy:assets": "npm run copy:swagger && npm run copy:public",
2030
"copy:swagger": "./node_modules/.bin/copyup ./src/api/swagger.json ./dist",
2131
"copy:public": "./node_modules/.bin/copyup ./src/public/* ./dist",
22-
"db:migrate": "npm run banner migrate && npm run ts-node:fast -- ./node_modules/.bin/knex migrate:latest",
23-
"db:migrate:rollback": "npm run banner rollback && npm run ts-node:fast -- ./node_modules/.bin/knex migrate:rollback",
24-
"db:seed": "npm run banner seed && npm run ts-node:fast -- ./node_modules/.bin/knex seed:run",
25-
"db:reset": "npm run console db:reset",
26-
"console": "npm run ts-node:fast -- ./src/console/commander.ts",
27-
"console:dev": "npm run ts-node -- ./src/console/commander.ts",
28-
"console:help": "npm run ts-node:fast -- ./src/console/commander.ts --help",
29-
"setup": "npm run banner setup && yarn install && npm run db:migrate && npm run db:seed",
30-
"serve": "npm run banner serve && ./node_modules/.bin/nodemon --watch 'src/**/*.ts' --watch 'src/**/*.json' --watch '.env'",
31-
"clean": "npm run banner clean && npm run clean:dist",
32-
"test": "npm run banner test && NODE_ENV=test ./node_modules/.bin/jest ./test/unit",
33-
"build": "npm run banner build && npm run lint && npm run clean:dist && npm run transpile && npm run copy:assets",
34-
"start": "node dist/app.js"
32+
"banner": "npm run ts-node:fast -- ./src/console/lib/banner.ts",
33+
"ts-node": "./node_modules/.bin/ts-node",
34+
"ts-node:fast": "./node_modules/.bin/ts-node -F"
3535
},
3636
"repository": "git+ssh://git@github.com/w3tec/express-typescript-boilerplate.git",
3737
"engines": {
@@ -75,24 +75,23 @@
7575
"@types/helmet": "0.0.35",
7676
"@types/inquirer": "^0.0.35",
7777
"@types/jest": "^20.0.2",
78-
"@types/jsonwebtoken": "^7.2.1",
78+
"@types/jsonwebtoken": "^7.2.2",
7979
"@types/knex": "0.0.52",
80-
"@types/lodash": "^4.14.67",
81-
"@types/mkdirp": "^0.3.29",
80+
"@types/lodash": "^4.14.68",
8281
"@types/morgan": "^1.7.32",
8382
"@types/pluralize": "^0.0.27",
8483
"@types/reflect-metadata": "0.0.5",
8584
"@types/request": "^0.0.45",
86-
"@types/request-promise": "^4.1.35",
85+
"@types/request-promise": "^4.1.36",
8786
"@types/serve-favicon": "^2.2.28",
8887
"@types/winston": "^2.3.3",
8988
"body-parser": "^1.17.2",
9089
"bookshelf": "^0.10.3",
9190
"bookshelf-camelcase": "^1.1.4",
92-
"chalk": "^1.1.3",
91+
"chalk": "^2.0.1",
9392
"class-validator": "^0.7.2",
94-
"commander": "^2.10.0",
95-
"compression": "^1.6.2",
93+
"commander": "^2.11.0",
94+
"compression": "^1.7.0",
9695
"copyfiles": "^1.2.0",
9796
"cors": "^2.8.1",
9897
"dotenv": "^4.0.0",
@@ -103,14 +102,12 @@
103102
"glob": "^7.1.2",
104103
"handlebars": "^4.0.10",
105104
"helmet": "^3.6.1",
106-
"inquirer": "^3.1.1",
107-
"inversify": "^4.1.1",
108-
"inversify-express-utils": "^3.5.1",
109-
"jest": "^20.0.3",
105+
"inquirer": "^3.2.0",
106+
"inversify": "^4.2.0",
107+
"inversify-express-utils": "^4.0.0",
110108
"jsonwebtoken": "^7.4.1",
111109
"knex": "^0.12.0",
112110
"lodash": "^4.17.4",
113-
"mkdirp": "^0.5.1",
114111
"morgan": "^1.7.0",
115112
"mysql": "^2.13.0",
116113
"nodemon": "^1.11.0",
@@ -119,16 +116,12 @@
119116
"reflect-metadata": "^0.1.10",
120117
"request": "^2.81.0",
121118
"request-promise": "^4.2.1",
122-
"require-dir": "^0.3.2",
123-
"rimraf": "^2.6.1",
124-
"run-sequence": "^1.2.2",
125119
"serve-favicon": "^2.4.3",
126-
"swagger-jsdoc": "^1.9.5",
127-
"swagger-ui-express": "^2.0.0",
120+
"swagger-jsdoc": "^1.9.6",
121+
"swagger-ui-express": "^2.0.1",
128122
"trash-cli": "^1.4.0",
129-
"ts-jest": "^20.0.6",
130-
"ts-node": "^3.1.0",
131-
"tslint": "^5.4.3",
123+
"ts-node": "^3.2.0",
124+
"tslint": "^5.5.0",
132125
"typescript": "^2.4.1",
133126
"winston": "^2.3.1"
134127
},
@@ -146,5 +139,10 @@
146139
"testEnvironment": "node",
147140
"setupTestFrameworkScriptFile": "./test/unit/lib/setup.ts"
148141
},
149-
"license": "MIT"
142+
"license": "MIT",
143+
"devDependencies": {
144+
"cross-env": "^5.0.1",
145+
"jest": "^20.0.3",
146+
"ts-jest": "^20.0.7"
147+
}
150148
}

src/api/controllers/UserController.ts

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*/
88

99
import { inject, named } from 'inversify';
10-
import { Controller, Get, Post, Put, Delete, RequestParam, RequestBody, Response, Request } from 'inversify-express-utils';
10+
import { controller, httpGet, httpPost, httpPut, httpDelete, response, request, requestBody, requestParam } from 'inversify-express-utils';
1111
import { app } from '../../app';
1212
import { Types, Targets } from '../../constants';
1313
import { UserService } from '../services/UserService';
@@ -17,42 +17,42 @@ const populateUser = app.IoC.getNamed<interfaces.Middleware>(Types.Middleware, T
1717
const authenticate = app.IoC.getNamed<interfaces.Middleware>(Types.Middleware, Targets.Middleware.AuthenticateMiddleware);
1818

1919

20-
@Controller('/users', authenticate.use)
20+
@controller('/users', authenticate.use)
2121
export class UserController {
2222

2323
constructor( @inject(Types.Service) @named(Targets.Service.UserService) private userService: UserService) { }
2424

25-
@Get('/')
26-
public async findAll( @Response() res: myExpress.Response): Promise<any> {
25+
@httpGet('/')
26+
public async findAll( @response() res: myExpress.Response): Promise<any> {
2727
const users = await this.userService.findAll();
2828
return res.found(users.toJSON());
2929
}
3030

31-
@Post('/')
32-
public async create( @Response() res: myExpress.Response, @RequestBody() body: any): Promise<any> {
31+
@httpPost('/')
32+
public async create( @response() res: myExpress.Response, @requestBody() body: any): Promise<any> {
3333
const user = await this.userService.create(body);
3434
return res.created(user.toJSON());
3535
}
3636

37-
@Get('/me', populateUser.use)
38-
public async findMe( @Request() req: myExpress.Request, @Response() res: myExpress.Response): Promise<any> {
37+
@httpGet('/me', populateUser.use)
38+
public async findMe( @request() req: myExpress.Request, @response() res: myExpress.Response): Promise<any> {
3939
return res.found(req.user);
4040
}
4141

42-
@Get('/:id')
43-
public async findOne( @Response() res: myExpress.Response, @RequestParam('id') id: string): Promise<any> {
42+
@httpGet('/:id')
43+
public async findOne( @response() res: myExpress.Response, @requestParam('id') id: string): Promise<any> {
4444
const user = await this.userService.findOne(parseInt(id, 10));
4545
return res.found(user.toJSON());
4646
}
4747

48-
@Put('/:id')
49-
public async update( @Response() res: myExpress.Response, @RequestParam('id') id: string, @RequestBody() body: any): Promise<any> {
48+
@httpPut('/:id')
49+
public async update( @response() res: myExpress.Response, @requestParam('id') id: string, @requestBody() body: any): Promise<any> {
5050
const user = await this.userService.update(parseInt(id, 10), body);
5151
return res.updated(user.toJSON());
5252
}
5353

54-
@Delete('/:id')
55-
public async destroy( @Response() res: myExpress.Response, @RequestParam('id') id: string): Promise<any> {
54+
@httpDelete('/:id')
55+
public async destroy( @response() res: myExpress.Response, @requestParam('id') id: string): Promise<any> {
5656
await this.userService.destroy(parseInt(id, 10));
5757
return res.destroyed();
5858
}

src/api/services/UserService.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { inject, named } from 'inversify';
1212
import { Types, Core, Targets } from '../../constants';
1313
import { Logger as LoggerType } from '../../core/Logger';
1414
import { EventEmitter } from '../../core/api/events';
15-
import { Validate, Request } from '../../core/api/Validate';
15+
import { validate, request } from '../../core/api/Validate';
1616
import { NotFoundException } from '../exceptions/NotFoundException';
1717
import { UserCreateRequest } from '../requests/user/UserCreateRequest';
1818
import { UserUpdateRequest } from '../requests/user/UserUpdateRequest';
@@ -77,8 +77,8 @@ export class UserService {
7777
* @param {*} data is the json body of the request
7878
* @returns {Promise<User>}
7979
*/
80-
@Validate()
81-
public async create( @Request(UserCreateRequest) data: any): Promise<User> {
80+
@validate()
81+
public async create( @request(UserCreateRequest) data: any): Promise<User> {
8282
// If the request body was valid we will create the user
8383
const user = await this.userRepo.create(data);
8484
this.events.emit(UserCreatedListener.Event, user.toJSON());
@@ -93,8 +93,8 @@ export class UserService {
9393
* @param {*} newUser is the json body of the request
9494
* @returns {Promise<User>}
9595
*/
96-
@Validate()
97-
public async update(id: number, @Request(UserUpdateRequest) newUser: any): Promise<User> {
96+
@validate()
97+
public async update(id: number, @request(UserUpdateRequest) newUser: any): Promise<User> {
9898
// Find or fail
9999
const user = await this.findOne(id);
100100
// Set new values

0 commit comments

Comments
 (0)