1
- import { ConnectionManager } from "typeorm" ;
2
- import { Container } from "typedi" ;
1
+ import { ConnectionManager , Repository , TreeRepository , MongoRepository } from "typeorm" ;
2
+ import { Container } from "typedi" ;
3
3
4
4
/**
5
- * Allows to inject a Repository using typedi's Container.
6
- * If you want to inject custom Repository class decorated with @EntityRepository decorator, use OrmCustomRepository instead.
5
+ * Helper to avoid V8 compilation of anonymous function on each call of decorator.
7
6
*/
8
- export function OrmRepository ( cls : Function , connectionName : string = "default" ) : Function {
9
- return function ( object : Object | Function , propertyName : string , index ?: number ) {
10
- Container . registerHandler ( { object, index, propertyName, value : ( ) => {
11
- const connectionManager = Container . get ( ConnectionManager ) ;
12
- if ( ! connectionManager . has ( connectionName ) )
13
- throw new Error ( `Cannot get connection "${ connectionName } " from the connection manager. ` +
14
- `Make sure you have created such connection. Also make sure you have called useContainer(Container) ` +
15
- `in your application before you established a connection and importing any entity.` ) ;
7
+ function getRepository ( connectionName : string , repositoryType : Function , entityType : Function ) {
8
+ const connectionManager = Container . get ( ConnectionManager ) ;
9
+ if ( ! connectionManager . has ( connectionName ) ) {
10
+ throw new Error (
11
+ `Cannot get connection "${ connectionName } " from the connection manager. ` +
12
+ `Make sure you have created such connection. Also make sure you have called useContainer(Container) ` +
13
+ `in your application before you established a connection and importing any entity.`
14
+ ) ;
15
+ }
16
+ const connection = connectionManager . get ( connectionName ) ;
16
17
17
- const connection = connectionManager . get ( connectionName ) ;
18
- return connection . getRepository ( cls as any ) ;
19
- } } ) ;
18
+ switch ( repositoryType ) {
19
+ case Repository :
20
+ return connection . getRepository ( entityType ) ;
21
+ case MongoRepository :
22
+ return connection . getMongoRepository ( entityType ) ;
23
+ case TreeRepository :
24
+ return connection . getTreeRepository ( entityType ) ;
25
+ // if not the TypeORM's ones, there must be custom repository classes
26
+ default :
27
+ return connection . getCustomRepository ( repositoryType ) ;
28
+ }
29
+ }
30
+
31
+ /**
32
+ * Allows to inject a Repository, MongoRepository, TreeRepository
33
+ * or custom repository using TypeDI's Container.
34
+ * Be aware that you have to annotate the property with correct type!
35
+ * ```ts
36
+ * class Sample {
37
+ * // constructor injection
38
+ * constructor(
39
+ * \@OrmRepository (User)
40
+ * private userRepository: Repository<User>,
41
+ * ) {}
42
+ *
43
+ * // property injection
44
+ * \@OrmRepository(User)
45
+ * userRepository: Repository<User>;
46
+ * }
47
+ * ```
48
+ */
49
+ export function OrmRepository ( entityType : Function , connectionName = "default" ) {
50
+ return ( object : object , propertyName : string , index ?: number ) => {
51
+ let repositoryType : Function ;
52
+
53
+ // if the decorator has been aplied to parameter (constructor injection)
54
+ if ( index ) {
55
+ const paramTypes : Function [ ] | undefined = Reflect . getOwnMetadata ( "design:paramtypes" , object , propertyName ) ;
56
+ if ( ! paramTypes || ! paramTypes [ index ] ) {
57
+ throw new Error (
58
+ `Cannot get reflected type for a "${ propertyName } " method's parameter of ${ object . constructor . name } class. ` +
59
+ `Make sure you have turned on an "emitDecoratorMetadata": true, option in tsconfig.json. ` +
60
+ `and that you have imported "reflect-metadata" on top of the main entry file in your application.` +
61
+ `And make sure that you have annotated the property type correctly with: ` +
62
+ `Repository, MongoRepository, TreeRepository or custom repository class type.`
63
+ ) ;
64
+ }
65
+ repositoryType = paramTypes [ index ] ;
66
+ }
67
+ // if the parameter has been aplied to class property
68
+ else {
69
+ const propertyType : Function | undefined = Reflect . getOwnMetadata ( "design:type" , object , propertyName ) ;
70
+ if ( ! propertyType ) {
71
+ throw new Error (
72
+ `Cannot get reflected type for a property "${ propertyName } " of ${ object . constructor . name } class. ` +
73
+ `Make sure you have turned on an "emitDecoratorMetadata": true, option in tsconfig.json ` +
74
+ `and that you have imported "reflect-metadata" on top of the main entry file in your application.` +
75
+ `And make sure that you have annotated the property type correctly with: ` +
76
+ `Repository, MongoRepository, TreeRepository or custom repository class type.`
77
+ ) ;
78
+ }
79
+ repositoryType = propertyType ;
80
+ }
81
+
82
+ Container . registerHandler ( {
83
+ index,
84
+ object,
85
+ propertyName,
86
+ value : ( ) => getRepository ( connectionName , repositoryType , entityType ) ,
87
+ } ) ;
20
88
} ;
89
+ }
90
+
91
+ class Test {
92
+
93
+ constructor (
94
+ @OrmRepository ( Test )
95
+ private repo : MongoRepository < any > ,
96
+ ) { }
97
+
98
+ @OrmRepository ( Test )
99
+ property : Repository < any > ;
21
100
}
0 commit comments