-
Notifications
You must be signed in to change notification settings - Fork 132
/
Copy pathentity-factory.ts
143 lines (127 loc) · 4.65 KB
/
entity-factory.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
import * as Faker from 'faker'
import { ObjectType, SaveOptions } from 'typeorm'
import { FactoryFunction, EntityProperty } from './types'
import { isPromiseLike } from './utils/factory.util'
import { printError, printWarning } from './utils/log.util'
import { getConnectionOptions, createConnection } from './connection'
export class EntityFactory<Entity, Context> {
private mapFunction: (entity: Entity) => Promise<Entity>
constructor(
public name: string,
public entity: ObjectType<Entity>,
private factory: FactoryFunction<Entity, Context>,
private context?: Context,
) {}
// -------------------------------------------------------------------------
// Public API
// -------------------------------------------------------------------------
/**
* This function is used to alter the generated values of entity, before it
* is persist into the database
*/
public map(mapFunction: (entity: Entity) => Promise<Entity>): EntityFactory<Entity, Context> {
this.mapFunction = mapFunction
return this
}
/**
* Make a new entity, but does not persist it
*/
public async make(overrideParams: EntityProperty<Entity> = {}): Promise<Entity> {
return this.makeEnity(overrideParams, false)
}
/**
* Create makes a new entity and does persist it
*/
public async create(overrideParams: EntityProperty<Entity> = {}, saveOptions?: SaveOptions): Promise<Entity> {
const option = await getConnectionOptions()
const connection = await createConnection(option)
if (connection && connection.isConnected) {
const em = connection.createEntityManager()
try {
const entity = await this.makeEnity(overrideParams, true)
return await em.save<Entity>(entity, saveOptions)
} catch (error) {
const message = 'Could not save entity'
printError(message, error)
throw new Error(message)
}
} else {
const message = 'No db connection is given'
printError(message)
throw new Error(message)
}
}
public async makeMany(amount: number, overrideParams: EntityProperty<Entity> = {}): Promise<Entity[]> {
const list = []
for (let index = 0; index < amount; index++) {
list[index] = await this.make(overrideParams)
}
return list
}
public async createMany(
amount: number,
overrideParams: EntityProperty<Entity> = {},
saveOptions?: SaveOptions,
): Promise<Entity[]> {
const list = []
for (let index = 0; index < amount; index++) {
list[index] = await this.create(overrideParams, saveOptions)
}
return list
}
public async seed(overrideParams: EntityProperty<Entity> = {}): Promise<Entity> {
printWarning('The seed() method is deprecated please use the create() method instead')
return this.create(overrideParams)
}
public async seedMany(amount: number, overrideParams: EntityProperty<Entity> = {}): Promise<Entity[]> {
printWarning('The seedMany() method is deprecated please use the createMany() method instead')
return this.createMany(amount, overrideParams)
}
// -------------------------------------------------------------------------
// Private Helpers
// -------------------------------------------------------------------------
private async makeEnity(overrideParams: EntityProperty<Entity> = {}, isSeeding = false): Promise<Entity> {
if (!this.factory) {
throw new Error('Could not found entity')
}
let entity = await this.resolveEntity(this.factory(Faker, this.context), isSeeding)
if (this.mapFunction) {
entity = await this.mapFunction(entity)
}
for (const key in overrideParams) {
if (overrideParams.hasOwnProperty(key)) {
entity[key] = overrideParams[key]
}
}
return entity
}
private async resolveEntity(entity: Entity, isSeeding = false): Promise<Entity> {
for (const attribute in entity) {
if (!entity.hasOwnProperty(attribute)) {
continue
}
if (isPromiseLike(entity[attribute])) {
entity[attribute] = await entity[attribute]
}
if (
entity[attribute] &&
typeof entity[attribute] === 'object' &&
entity[attribute].constructor.name === EntityFactory.name
) {
const subEntityFactory = entity[attribute]
try {
if (isSeeding) {
entity[attribute] = await (subEntityFactory as any).create()
} else {
entity[attribute] = await (subEntityFactory as any).make()
}
} catch (error) {
const message = `Could not make ${(subEntityFactory as any).name}`
printError(message, error)
throw new Error(message)
}
}
}
return entity
}
}