Skip to content

Commit 8ad2e00

Browse files
author
hirsch88
committed
Merge branch 'release/3.0.0-beta.2'
2 parents c129485 + f4b6a59 commit 8ad2e00

29 files changed

+743
-279
lines changed

README.md

+30-4
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,8 @@ All script are defined in the package.json file, but the most important ones are
142142

143143
### Database Migration
144144

145-
- Run `./node_modules/.bin/typeorm create -n <migration-file-name>` to create a new migration file.
145+
- Run `typeorm migrations:create -n <migration-file-name>` to create a new migration file.
146+
- Try `typeorm -h` to see more useful cli commands like generating migration out of your models.
146147
- To migrate your database run `npm start db.migrate`.
147148
- To revert your latest migration run `npm start db.revert`.
148149
- Drops the complete database schema `npm start db.drop`.
@@ -267,19 +268,44 @@ factory.define(User, (faker: typeof Faker) => {
267268
});
268269
```
269270
270-
This is a nested example for a factory to get the foreign key of the other entity.
271+
This can be used to pass some dynamic value into the factory.
271272
272273
```typescript
273274
factory.define(Pet, (faker: typeof Faker, args: any[]) => {
274275
const type = args[0];
275276
return {
276277
name: faker.name.firstName(),
277-
type: type || 'dog',
278-
userId: factory.get(User).returning('id')
278+
type: type || 'dog'
279279
};
280280
});
281281
```
282282
283+
To deal with relations you can use the entity manager like this.
284+
285+
```typescript
286+
import { SeedsInterface, FactoryInterface, times } from '../../lib/seeds';
287+
import { Pet } from '../../../src/api/models/Pet';
288+
import { User } from '../../../src/api/models/User';
289+
290+
export class CreatePets implements SeedsInterface {
291+
292+
public async seed(factory: FactoryInterface): Promise<any> {
293+
const connection = await factory.getConnection();
294+
const em = connection.createEntityManager();
295+
296+
await times(10, async (n) => {
297+
// This creates a pet in the database
298+
const pet = await factory.get(Pet).create();
299+
// This only returns a entity with fake data
300+
const user = await factory.get(User).make();
301+
user.pets = [pet];
302+
await em.save(user);
303+
});
304+
}
305+
306+
}
307+
```
308+
283309
### 2. Create a seed file
284310
285311
The seeds files define how much and how the data are connected with each other. The files will be executed alphabetically.

package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "express-typescript-boilerplate",
3-
"version": "3.0.0-beta",
3+
"version": "3.0.0-beta.2",
44
"description": "A delightful way to building a RESTful API with NodeJs & TypeScript",
55
"main": "src/app.ts",
66
"scripts": {

src/api/controllers/PetController.ts

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import { JsonController, Get, Post, Put, Param, Delete, Body, OnUndefined, Authorized } from 'routing-controllers';
2+
import { PetService } from '../services/PetService';
3+
import { Pet } from '../models/Pet';
4+
import { PetNotFoundError } from '../errors/PetNotFoundError';
5+
6+
7+
@Authorized()
8+
@JsonController('/pets')
9+
export class PetController {
10+
11+
constructor(
12+
private petService: PetService
13+
) { }
14+
15+
@Get()
16+
public find(): Promise<Pet[]> {
17+
return this.petService.find();
18+
}
19+
20+
@Get('/:id')
21+
@OnUndefined(PetNotFoundError)
22+
public one( @Param('id') id: string): Promise<Pet | undefined> {
23+
return this.petService.findOne(id);
24+
}
25+
26+
@Post()
27+
public create( @Body() pet: Pet): Promise<Pet> {
28+
return this.petService.create(pet);
29+
}
30+
31+
@Put('/:id')
32+
public update( @Param('id') id: string, @Body() pet: Pet): Promise<Pet> {
33+
return this.petService.update(id, pet);
34+
}
35+
36+
@Delete('/:id')
37+
public delete( @Param('id') id: string): Promise<void> {
38+
return this.petService.delete(id);
39+
}
40+
41+
}

src/api/errors/PetNotFoundError.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { HttpError } from 'routing-controllers';
2+
3+
export class PetNotFoundError extends HttpError {
4+
constructor() {
5+
super(404, 'Pet not found!');
6+
}
7+
}

src/api/models/Pet.ts

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
2+
import { IsNotEmpty } from 'class-validator';
3+
import { User } from './User';
4+
5+
6+
@Entity()
7+
export class Pet {
8+
9+
@PrimaryGeneratedColumn('uuid')
10+
public id: string;
11+
12+
@IsNotEmpty()
13+
@Column()
14+
public name: string;
15+
16+
@IsNotEmpty()
17+
@Column()
18+
public age: number;
19+
20+
@ManyToOne(type => User, user => user.pets)
21+
public user: User;
22+
23+
public toString(): string {
24+
return `${this.name}`;
25+
}
26+
27+
}

src/api/models/User.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
1+
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
22
import { IsNotEmpty } from 'class-validator';
3+
import { Pet } from './Pet';
34

45

56
@Entity()
@@ -20,6 +21,9 @@ export class User {
2021
@Column()
2122
public email: string;
2223

24+
@OneToMany(type => Pet, pet => pet.user)
25+
public pets: Pet[];
26+
2327
public toString(): string {
2428
return `${this.firstName} ${this.lastName} (${this.email})`;
2529
}

src/api/repositories/PetRepository.ts

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { Repository, EntityRepository } from 'typeorm';
2+
import { Pet } from '../models/Pet';
3+
4+
@EntityRepository(Pet)
5+
export class PetRepository extends Repository<Pet> {
6+
7+
}

src/api/services/PetService.ts

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import { Service } from 'typedi';
2+
import { OrmRepository } from 'typeorm-typedi-extensions';
3+
import { PetRepository } from '../repositories/PetRepository';
4+
import { Pet } from '../models/Pet';
5+
import { events } from '../subscribers/events';
6+
import { EventDispatcher, EventDispatcherInterface } from '../../decorators/EventDispatcher';
7+
import { Logger, LoggerInterface } from '../../decorators/Logger';
8+
9+
10+
@Service()
11+
export class PetService {
12+
13+
constructor(
14+
@OrmRepository() private petRepository: PetRepository,
15+
@EventDispatcher() private eventDispatcher: EventDispatcherInterface,
16+
@Logger(__filename) private log: LoggerInterface
17+
) { }
18+
19+
public find(): Promise<Pet[]> {
20+
this.log.info('Find all pets');
21+
return this.petRepository.find();
22+
}
23+
24+
public findOne(id: string): Promise<Pet | undefined> {
25+
this.log.info('Find all pets');
26+
return this.petRepository.findOne({ id });
27+
}
28+
29+
public async create(pet: Pet): Promise<Pet> {
30+
this.log.info('Create a new pet => ', pet.toString());
31+
const newPet = await this.petRepository.save(pet);
32+
this.eventDispatcher.dispatch(events.pet.created, newPet);
33+
return newPet;
34+
}
35+
36+
public update(id: string, pet: Pet): Promise<Pet> {
37+
this.log.info('Update a pet');
38+
pet.id = id;
39+
return this.petRepository.save(pet);
40+
}
41+
42+
public delete(id: string): Promise<void> {
43+
this.log.info('Delete a pet');
44+
return this.petRepository.removeById(id);
45+
}
46+
47+
}

src/api/services/UserService.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class UserService {
1818

1919
public find(): Promise<User[]> {
2020
this.log.info('Find all users');
21-
return this.userRepository.find();
21+
return this.userRepository.find({ relations: ['pets'] });
2222
}
2323

2424
public findOne(id: string): Promise<User | undefined> {

src/api/subscribers/events.ts

+3
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,7 @@ export const events = {
77
user: {
88
created: 'onUserCreate',
99
},
10+
pet: {
11+
created: 'onPetCreate',
12+
},
1013
};

0 commit comments

Comments
 (0)