Skip to content

Commit b839c0e

Browse files
author
Gery Hirschfeld
authored
Merge pull request #72 from w3tecch/feature/seed
Feature/seed
2 parents c2d2912 + 7cd813f commit b839c0e

28 files changed

+662
-583
lines changed

README.md

Lines changed: 59 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -255,15 +255,18 @@ export class UserService {
255255
256256
## Seeding
257257
258-
Isn't exhausting to create some sample data into your fresh migrated database, well this time is over!
259-
How does it work? Just, create a factory for your entities and a seeds script.
258+
Isn't it exhausting to create some sample data for your database, well this time is over!
259+
260+
How does it work? Just create a factory for your entities (models) and a seed script.
260261
261262
### 1. Create a factory for your entity
262263
263-
For all the entities we want to seed, we need to define a factory. To do so we give you the awesome [faker](https://github.com/marak/Faker.js/) library as a parameter into your factory. Then create your "fake" entity as you would normally do and return it. Those factory files should be in the `src/database/factories` folder and suffixed with `Factory`. Example `src/database/factories/UserFactory.ts`.
264+
For all entities we want to seed, we need to define a factory. To do so we give you the awesome [faker](https://github.com/marak/Faker.js/) library as a parameter into your factory. Then create your "fake" entity and return it. Those factory files should be in the `src/database/factories` folder and suffixed with `Factory` like `src/database/factories/UserFactory.ts`.
265+
266+
Settings can be used to pass some static value into the factory.
264267
265268
```typescript
266-
factory.define(User, (faker: typeof Faker) => {
269+
define(User, (faker: typeof Faker, settings: { roles: string[] }) => {
267270
const gender = faker.random.number(1);
268271
const firstName = faker.name.firstName(gender);
269272
const lastName = faker.name.lastName(gender);
@@ -273,94 +276,76 @@ factory.define(User, (faker: typeof Faker) => {
273276
user.firstName = firstName;
274277
user.lastName = lastName;
275278
user.email = email;
279+
user.roles = settings.roles;
276280
return user;
277281
});
278282
```
279283
280-
This can be used to pass some dynamic value into the factory.
284+
Handle relation in the entity factory like this.
281285
282286
```typescript
283-
factory.define(Pet, (faker: typeof Faker, args: any[]) => {
284-
const type = args[0];
285-
return {
286-
name: faker.name.firstName(),
287-
type: type || 'dog'
288-
};
289-
});
290-
```
291-
292-
To deal with relations you can use the entity manager like this.
293-
294-
```typescript
295-
import { SeedsInterface, FactoryInterface, times } from '../../lib/seeds';
296-
import { Pet } from '../../../src/api/models/Pet';
297-
import { User } from '../../../src/api/models/User';
298-
299-
export class CreatePets implements SeedsInterface {
300-
301-
public async seed(factory: FactoryInterface): Promise<any> {
302-
const connection = await factory.getConnection();
303-
const em = connection.createEntityManager();
304-
305-
await times(10, async (n) => {
306-
// This creates a pet in the database
307-
const pet = await factory.get(Pet).create();
308-
// This only returns a entity with fake data
309-
const user = await factory.get(User).make();
310-
user.pets = [pet];
311-
await em.save(user);
312-
});
313-
}
287+
define(Pet, (faker: typeof Faker, settings: undefined) => {
288+
const gender = faker.random.number(1);
289+
const name = faker.name.firstName(gender);
314290

315-
}
291+
const pet = new Pet();
292+
pet.name = name;
293+
pet.age = faker.random.number();
294+
pet.user = factory(User)({ roles: ['admin'] })
295+
return pet;
296+
});
316297
```
317298
318299
### 2. Create a seed file
319300
320301
The seeds files define how much and how the data are connected with each other. The files will be executed alphabetically.
302+
With the second function, accepting your settings defined in the factories, you are able to create different variations of entities.
321303
322304
```typescript
323-
export class CreateUsers implements SeedsInterface {
305+
export class CreateUsers implements Seed {
324306

325-
public async seed(factory: FactoryInterface): Promise<any> {
326-
await factory
327-
.get(User)
328-
.createMany(10);
307+
public async seed(factory: Factory, connection: Connection): Promise<any> {
308+
await factory(User)({ roles: [] }).createMany(10);
329309
}
330310

331311
}
332312
```
333313
334-
With the second parameter in the `.get(<Entity>, <args>)` you are able to create different variations of entities.
314+
Here an example with nested factories. You can use the `.map()` function to alter
315+
the generated value before they get persisted.
335316
336317
```typescript
337-
export class CreateUsers implements SeedsInterface {
338-
339-
public async seed(factory: FactoryInterface): Promise<any> {
340-
await factory
341-
.get(User, 'admin')
342-
.create();
343-
}
344-
345-
}
318+
...
319+
await factory(User)()
320+
.map(async (user: User) => {
321+
const pets: Pet[] = await factory(Pet)().createMany(2);
322+
const petIds = pets.map((pet: Pet) => pet.Id);
323+
await user.pets().attach(petIds);
324+
})
325+
.createMany(5);
326+
...
346327
```
347328
348-
Here an example with nested factories.
329+
To deal with relations you can use the entity manager like this.
349330
350331
```typescript
351-
...
352-
await factory.get(User)
353-
.each(async (user: User) => {
332+
export class CreatePets implements SeedsInterface {
354333

355-
const pets: Pet[] = await factory.get(Pet)
356-
.createMany(2);
334+
public async seed(factory: FactoryInterface, connection: Connection): Promise<any> {
335+
const connection = await factory.getConnection();
336+
const em = connection.createEntityManager();
357337

358-
const petIds = pets.map((pet: Pet) => pet.Id);
359-
await user.pets().attach(petIds);
338+
await times(10, async (n) => {
339+
// This creates a pet in the database
340+
const pet = await factory(Pet)().create();
341+
// This only returns a entity with fake data
342+
const user = await factory(User)({ roles: ['admin'] }).make();
343+
user.pets = [pet];
344+
await em.save(user);
345+
});
346+
}
360347

361-
})
362-
.create(5);
363-
...
348+
}
364349
```
365350
366351
### 3. Run the seeder
@@ -371,6 +356,17 @@ The last step is the easiest, just hit the following command in your terminal, b
371356
npm start db.seed
372357
```
373358
359+
#### CLI Interface
360+
361+
| Command | Description |
362+
| --------------------------------------------------- | ----------- |
363+
| `npm start "db.seed"` | Run all seeds |
364+
| `npm start "db.seed --run CreateBruce,CreatePets"` | Run specific seeds (file names without extension) |
365+
| `npm start "db.seed -L"` | Log database queries to the terminal |
366+
| `npm start "db.seed --factories <path>"` | Add a different path to your factories (Default: `src/database/`) |
367+
| `npm start "db.seed --seeds <path>"` | Add a different path to your seeds (Default: `src/database/seeds/`) |
368+
| `npm start "db.seed --config <file>"` | Path to your ormconfig.json file |
369+
374370
## Run in Docker container
375371
376372
### Install Docker

package-scripts.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ module.exports = {
140140
script: series(
141141
'nps banner.seed',
142142
'nps config',
143-
runFast('./src/lib/seeds/cli.ts')
143+
runFast('./src/lib/seed/cli.ts')
144144
),
145145
description: 'Seeds generated records into the database'
146146
},

src/api/middlewares/ErrorHandlerMiddleware.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class ErrorHandlerMiddleware implements ExpressErrorMiddlewareInterface {
1818
res.json({
1919
name: error.name,
2020
message: error.message,
21-
errors: error['errors'] || [],
21+
errors: error[`errors`] || [],
2222
});
2323

2424
if (this.isProduction) {

src/database/factories/PetFactory.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import * as Faker from 'faker';
22

33
import { Pet } from '../../../src/api/models/Pet';
4-
import { Factory } from '../../lib/seeds';
4+
import { define } from '../../lib/seed';
55

6-
const factory = Factory.getInstance();
7-
8-
factory.define(Pet, (faker: typeof Faker) => {
6+
define(Pet, (faker: typeof Faker) => {
97
const gender = faker.random.number(1);
108
const name = faker.name.firstName(gender);
119

src/database/factories/UserFactory.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
import * as Faker from 'faker';
22

33
import { User } from '../../../src/api/models/User';
4-
import { Factory } from '../../lib/seeds';
4+
import { define } from '../../lib/seed';
55

6-
const factory = Factory.getInstance();
7-
8-
factory.define(User, (faker: typeof Faker) => {
6+
define(User, (faker: typeof Faker, settings: { role: string }) => {
97
const gender = faker.random.number(1);
108
const firstName = faker.name.firstName(gender);
119
const lastName = faker.name.lastName(gender);

src/database/seeds/CreateBruce.ts

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,31 @@
1+
import { Connection } from 'typeorm';
2+
13
import { User } from '../../../src/api/models/User';
2-
import { FactoryInterface, SeedsInterface } from '../../lib/seeds';
4+
import { Factory, Seed } from '../../lib/seed/types';
5+
6+
export class CreateBruce implements Seed {
7+
8+
public async seed(factory: Factory, connection: Connection): Promise<User> {
9+
// const userFactory = factory<User, { role: string }>(User as any);
10+
// const adminUserFactory = userFactory({ role: 'admin' });
11+
12+
// const bruce = await adminUserFactory.make();
13+
// console.log(bruce);
14+
15+
// const bruce2 = await adminUserFactory.seed();
16+
// console.log(bruce2);
17+
18+
// const bruce3 = await adminUserFactory
19+
// .map(async (e: User) => {
20+
// e.firstName = 'Bruce';
21+
// return e;
22+
// })
23+
// .seed();
24+
// console.log(bruce3);
325

4-
export class CreateBruce implements SeedsInterface {
26+
// return bruce;
527

6-
public async seed(factory: FactoryInterface): Promise<User> {
7-
const connection = await factory.getConnection();
28+
// const connection = await factory.getConnection();
829
const em = connection.createEntityManager();
930

1031
const user = new User();

src/database/seeds/CreatePets.ts

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
1+
import { Connection } from 'typeorm';
2+
13
import { Pet } from '../../../src/api/models/Pet';
24
import { User } from '../../../src/api/models/User';
3-
import { FactoryInterface, SeedsInterface, times } from '../../lib/seeds';
5+
import { Factory, Seed, times } from '../../lib/seed';
46

5-
export class CreatePets implements SeedsInterface {
7+
export class CreatePets implements Seed {
68

7-
public async seed(factory: FactoryInterface): Promise<any> {
8-
const connection = await factory.getConnection();
9+
public async seed(factory: Factory, connection: Connection): Promise<any> {
910
const em = connection.createEntityManager();
1011

1112
await times(10, async (n) => {
12-
const pet = await factory.get(Pet).create();
13-
const user = await factory.get(User).make();
13+
const pet = await factory(Pet)().seed();
14+
const user = await factory(User)().make();
1415
user.pets = [pet];
1516
await em.save(user);
1617
});

src/database/seeds/CreateUsers.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
1+
import { Connection } from 'typeorm/connection/Connection';
2+
13
import { User } from '../../../src/api/models/User';
2-
import { FactoryInterface, SeedsInterface } from '../../lib/seeds';
4+
import { Factory, Seed } from '../../lib/seed/types';
35

4-
export class CreateUsers implements SeedsInterface {
6+
export class CreateUsers implements Seed {
57

6-
public async seed(factory: FactoryInterface): Promise<any> {
7-
await factory
8-
.get(User)
9-
.createMany(10);
8+
public async seed(factory: Factory, connection: Connection): Promise<any> {
9+
await factory(User)().seedMany(10);
1010
}
1111

1212
}

0 commit comments

Comments
 (0)