Skip to content

Commit

Permalink
Merge branch 'release/3.0.0-beta.2'
Browse files Browse the repository at this point in the history
  • Loading branch information
hirsch88 committed Dec 8, 2017
2 parents c129485 + f4b6a59 commit 8ad2e00
Show file tree
Hide file tree
Showing 29 changed files with 743 additions and 279 deletions.
34 changes: 30 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,8 @@ All script are defined in the package.json file, but the most important ones are

### Database Migration

- Run `./node_modules/.bin/typeorm create -n <migration-file-name>` to create a new migration file.
- Run `typeorm migrations:create -n <migration-file-name>` to create a new migration file.
- Try `typeorm -h` to see more useful cli commands like generating migration out of your models.
- To migrate your database run `npm start db.migrate`.
- To revert your latest migration run `npm start db.revert`.
- Drops the complete database schema `npm start db.drop`.
Expand Down Expand Up @@ -267,19 +268,44 @@ factory.define(User, (faker: typeof Faker) => {
});
```
This is a nested example for a factory to get the foreign key of the other entity.
This can be used to pass some dynamic value into the factory.
```typescript
factory.define(Pet, (faker: typeof Faker, args: any[]) => {
const type = args[0];
return {
name: faker.name.firstName(),
type: type || 'dog',
userId: factory.get(User).returning('id')
type: type || 'dog'
};
});
```
To deal with relations you can use the entity manager like this.
```typescript
import { SeedsInterface, FactoryInterface, times } from '../../lib/seeds';
import { Pet } from '../../../src/api/models/Pet';
import { User } from '../../../src/api/models/User';

export class CreatePets implements SeedsInterface {

public async seed(factory: FactoryInterface): Promise<any> {
const connection = await factory.getConnection();
const em = connection.createEntityManager();

await times(10, async (n) => {
// This creates a pet in the database
const pet = await factory.get(Pet).create();
// This only returns a entity with fake data
const user = await factory.get(User).make();
user.pets = [pet];
await em.save(user);
});
}

}
```
### 2. Create a seed file
The seeds files define how much and how the data are connected with each other. The files will be executed alphabetically.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "express-typescript-boilerplate",
"version": "3.0.0-beta",
"version": "3.0.0-beta.2",
"description": "A delightful way to building a RESTful API with NodeJs & TypeScript",
"main": "src/app.ts",
"scripts": {
Expand Down
41 changes: 41 additions & 0 deletions src/api/controllers/PetController.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { JsonController, Get, Post, Put, Param, Delete, Body, OnUndefined, Authorized } from 'routing-controllers';
import { PetService } from '../services/PetService';
import { Pet } from '../models/Pet';
import { PetNotFoundError } from '../errors/PetNotFoundError';


@Authorized()
@JsonController('/pets')
export class PetController {

constructor(
private petService: PetService
) { }

@Get()
public find(): Promise<Pet[]> {
return this.petService.find();
}

@Get('/:id')
@OnUndefined(PetNotFoundError)
public one( @Param('id') id: string): Promise<Pet | undefined> {
return this.petService.findOne(id);
}

@Post()
public create( @Body() pet: Pet): Promise<Pet> {
return this.petService.create(pet);
}

@Put('/:id')
public update( @Param('id') id: string, @Body() pet: Pet): Promise<Pet> {
return this.petService.update(id, pet);
}

@Delete('/:id')
public delete( @Param('id') id: string): Promise<void> {
return this.petService.delete(id);
}

}
7 changes: 7 additions & 0 deletions src/api/errors/PetNotFoundError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { HttpError } from 'routing-controllers';

export class PetNotFoundError extends HttpError {
constructor() {
super(404, 'Pet not found!');
}
}
27 changes: 27 additions & 0 deletions src/api/models/Pet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from 'typeorm';
import { IsNotEmpty } from 'class-validator';
import { User } from './User';


@Entity()
export class Pet {

@PrimaryGeneratedColumn('uuid')
public id: string;

@IsNotEmpty()
@Column()
public name: string;

@IsNotEmpty()
@Column()
public age: number;

@ManyToOne(type => User, user => user.pets)
public user: User;

public toString(): string {
return `${this.name}`;
}

}
6 changes: 5 additions & 1 deletion src/api/models/User.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { Entity, PrimaryGeneratedColumn, Column } from 'typeorm';
import { Entity, PrimaryGeneratedColumn, Column, OneToMany } from 'typeorm';
import { IsNotEmpty } from 'class-validator';
import { Pet } from './Pet';


@Entity()
Expand All @@ -20,6 +21,9 @@ export class User {
@Column()
public email: string;

@OneToMany(type => Pet, pet => pet.user)
public pets: Pet[];

public toString(): string {
return `${this.firstName} ${this.lastName} (${this.email})`;
}
Expand Down
7 changes: 7 additions & 0 deletions src/api/repositories/PetRepository.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Repository, EntityRepository } from 'typeorm';
import { Pet } from '../models/Pet';

@EntityRepository(Pet)
export class PetRepository extends Repository<Pet> {

}
47 changes: 47 additions & 0 deletions src/api/services/PetService.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Service } from 'typedi';
import { OrmRepository } from 'typeorm-typedi-extensions';
import { PetRepository } from '../repositories/PetRepository';
import { Pet } from '../models/Pet';
import { events } from '../subscribers/events';
import { EventDispatcher, EventDispatcherInterface } from '../../decorators/EventDispatcher';
import { Logger, LoggerInterface } from '../../decorators/Logger';


@Service()
export class PetService {

constructor(
@OrmRepository() private petRepository: PetRepository,
@EventDispatcher() private eventDispatcher: EventDispatcherInterface,
@Logger(__filename) private log: LoggerInterface
) { }

public find(): Promise<Pet[]> {
this.log.info('Find all pets');
return this.petRepository.find();
}

public findOne(id: string): Promise<Pet | undefined> {
this.log.info('Find all pets');
return this.petRepository.findOne({ id });
}

public async create(pet: Pet): Promise<Pet> {
this.log.info('Create a new pet => ', pet.toString());
const newPet = await this.petRepository.save(pet);
this.eventDispatcher.dispatch(events.pet.created, newPet);
return newPet;
}

public update(id: string, pet: Pet): Promise<Pet> {
this.log.info('Update a pet');
pet.id = id;
return this.petRepository.save(pet);
}

public delete(id: string): Promise<void> {
this.log.info('Delete a pet');
return this.petRepository.removeById(id);
}

}
2 changes: 1 addition & 1 deletion src/api/services/UserService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ export class UserService {

public find(): Promise<User[]> {
this.log.info('Find all users');
return this.userRepository.find();
return this.userRepository.find({ relations: ['pets'] });
}

public findOne(id: string): Promise<User | undefined> {
Expand Down
3 changes: 3 additions & 0 deletions src/api/subscribers/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ export const events = {
user: {
created: 'onUserCreate',
},
pet: {
created: 'onPetCreate',
},
};

0 comments on commit 8ad2e00

Please sign in to comment.