1
- import { ConnectionManager , Repository , TreeRepository , MongoRepository } from 'typeorm' ;
1
+ import { ConnectionManager , Repository , TreeRepository , MongoRepository , EntityTarget , ObjectType } from 'typeorm' ;
2
2
import { Constructable , Container , ContainerInstance } from 'typedi' ;
3
3
4
4
import { EntityTypeMissingError } from '../errors/entity-type-missing.error' ;
5
5
import { PropertyTypeMissingError } from '../errors/property-type-missing.error' ;
6
6
import { ParamTypeMissingError } from '../errors/param-type-missing.error' ;
7
+ import { ConnectionNotFoundError } from '../errors/manager-not-found.error' ;
7
8
8
9
/**
9
10
* Helper to avoid V8 compilation of anonymous function on each call of decorator.
10
11
*/
11
- function getRepository (
12
+ function getRepositoryHelper (
12
13
connectionName : string ,
13
- repositoryType : Function ,
14
- entityType : Function ,
14
+ repositoryType : ObjectType < unknown > ,
15
+ entityType : EntityTarget < unknown > ,
15
16
containerInstance : ContainerInstance
16
17
) {
17
18
const connectionManager = containerInstance . get ( ConnectionManager ) ;
18
19
if ( ! connectionManager . has ( connectionName ) ) {
19
- throw new Error (
20
- `Cannot get connection "${ connectionName } " from the connection manager. ` +
21
- `Make sure you have created such connection. Also make sure you have called useContainer(Container) ` +
22
- `in your application before you established a connection and importing any entity.`
23
- ) ;
20
+ throw new ConnectionNotFoundError ( connectionName ) ;
24
21
}
22
+
25
23
const connection = connectionManager . get ( connectionName ) ;
26
24
27
25
switch ( repositoryType ) {
@@ -31,97 +29,63 @@ function getRepository(
31
29
return connection . getMongoRepository ( entityType ) ;
32
30
case TreeRepository :
33
31
return connection . getTreeRepository ( entityType ) ;
34
- // if not the TypeORM's ones, there must be custom repository classes
35
32
default :
33
+ /** If the requested type is not well-known, then it must be a custom repository. */
36
34
return connection . getCustomRepository ( repositoryType ) ;
37
35
}
38
36
}
39
37
40
38
/**
41
- * Satisfy typescript compiler about universal decorators.
42
- */
43
- export type ParamOrPropDecorator = ( object : object , propertyName : string , index ?: number ) => void ;
44
-
45
- /**
46
- * Allows to inject a custom repository using TypeDI's Container.
47
- * Be aware that you have to annotate the param/property with correct type!
48
- * ```ts
49
- * class Sample {
50
- * // constructor injection
51
- * constructor(
52
- * \@InjectRepository ()
53
- * private userRepository: UserRepository,
54
- * ) {}
39
+ * Injects the requested custom repository object using TypeDI's container. To make injection work without explicity
40
+ * specifying the type in the decorator, you must annotate your properties and/or parameters with the correct type!
55
41
*
56
- * // property injection
42
+ * ```ts
43
+ * class SampleClass {
57
44
* \@InjectRepository ()
58
45
* userRepository: UserRepository;
46
+ *
47
+ * constructor(@InjectRepository() private userRepository: UserRepository) {}
59
48
* }
60
49
* ```
61
50
*/
62
- export function InjectRepository ( ) : ParamOrPropDecorator ;
51
+ export function InjectRepository ( ) : CallableFunction ;
52
+ export function InjectRepository ( connectionName : string ) : CallableFunction ;
53
+
63
54
/**
64
- * Allows to inject a Repository, MongoRepository, TreeRepository using TypeDI's Container.
65
- * Be aware that you have to annotate the param/property with correct type!
66
- * ```ts
67
- * class Sample {
68
- * // constructor injection
69
- * constructor(
70
- * \@InjectRepository (User)
71
- * private userRepository: Repository<User>,
72
- * ) {}
55
+ * Injects the requested `Repository`, `MongoRepository`, `TreeRepository` object using TypeDI's container.
56
+ * To make injection work without explicity specifying the type in the decorator, you must annotate your properties
57
+ * and/or parameters with the correct type!
73
58
*
74
- * // property injection
59
+ * ```ts
60
+ * class SampleClass {
75
61
* \@InjectRepository (User)
76
62
* userRepository: Repository<User>;
77
- * }
78
- * ```
79
- */
80
- export function InjectRepository ( entityType : Function ) : ParamOrPropDecorator ;
81
- /**
82
- * Allows to inject a custom repository using TypeDI's Container
83
- * and specify the connection name in a parameter.
84
- * Be aware that you have to annotate the param/property with correct type!
85
- * ```ts
86
- * class Sample {
87
- * // constructor injection
88
- * constructor(
89
- * \@InjectRepository ("test-conn")
90
- * private userRepository: UserRepository,
91
- * ) {}
92
63
*
93
- * // property injection
94
- * \@InjectRepository("test-conn")
95
- * userRepository: UserRepository;
64
+ * constructor(@InjectRepository(User) private userRepository: Repository<User>) {}
96
65
* }
97
66
* ```
98
67
*/
99
- export function InjectRepository ( connectionName : string ) : ParamOrPropDecorator ;
68
+ export function InjectRepository ( entityType : Function ) : CallableFunction ;
100
69
/**
101
- * Allows to inject a Repository, MongoRepository, TreeRepository using TypeDI's Container
102
- * and specify the connection name in a parameter.
103
- * Be aware that you have to annotate the param/property with correct type!
104
- * ```ts
105
- * class Sample {
106
- * // constructor injection
107
- * constructor(
108
- * \@InjectRepository (User, "test-conn")
109
- * private userRepository: Repository<User>,
110
- * ) {}
70
+ * Injects the requested `Repository`, `MongoRepository`, `TreeRepository` object using TypeDI's container.
71
+ * To make injection work without explicity specifying the type in the decorator, you must annotate your properties
72
+ * and/or parameters with the correct type!
111
73
*
112
- * // property injection
74
+ * ```ts
75
+ * class SampleClass {
113
76
* \@InjectRepository (User, "test-conn")
114
77
* userRepository: Repository<User>;
78
+ *
79
+ * constructor(@InjectRepository(User, "test-conn") private userRepository: Repository<User>) {}
115
80
* }
116
81
* ```
117
82
*/
118
- export function InjectRepository ( entityType : Function , connectionName : string ) : ParamOrPropDecorator ;
119
-
83
+ export function InjectRepository ( entityType : Function , connectionName : string ) : CallableFunction ;
120
84
export function InjectRepository (
121
85
entityTypeOrConnectionName ?: Function | string ,
122
86
paramConnectionName = 'default'
123
- ) : ParamOrPropDecorator {
124
- return ( object : object , propertyName : string , index ?: number ) => {
87
+ ) : CallableFunction {
88
+ return ( object : object , propertyName : string | symbol , index ?: number ) : void => {
125
89
let entityType : Function | undefined ;
126
90
let connectionName : string ;
127
91
let repositoryType : Function ;
@@ -134,20 +98,27 @@ export function InjectRepository(
134
98
entityType = entityTypeOrConnectionName ;
135
99
}
136
100
137
- // if the decorator has been aplied to parameter (constructor injection)
101
+ if ( Reflect ?. getOwnMetadata == undefined ) {
102
+ throw new Error ( 'Reflect.getOwnMetadata is not defined. Make sure to import the `reflect-metadata` package!' ) ;
103
+ }
104
+
138
105
if ( index !== undefined ) {
106
+ /** The decorator has been applied to a constructor parameter. */
139
107
const paramTypes : Function [ ] | undefined = Reflect . getOwnMetadata ( 'design:paramtypes' , object , propertyName ) ;
108
+
140
109
if ( ! paramTypes || ! paramTypes [ index ] ) {
141
- throw new ParamTypeMissingError ( object , propertyName , index ) ;
110
+ throw new ParamTypeMissingError ( object , propertyName as string , index ) ;
142
111
}
112
+
143
113
repositoryType = paramTypes [ index ] ;
144
- }
145
- // if the parameter has been aplied to class property
146
- else {
114
+ } else {
115
+ /** The decorator has been applied to a class property. */
147
116
const propertyType : Function | undefined = Reflect . getOwnMetadata ( 'design:type' , object , propertyName ) ;
117
+
148
118
if ( ! propertyType ) {
149
- throw new PropertyTypeMissingError ( object , propertyName ) ;
119
+ throw new PropertyTypeMissingError ( object , propertyName as string ) ;
150
120
}
121
+
151
122
repositoryType = propertyType ;
152
123
}
153
124
@@ -156,15 +127,15 @@ export function InjectRepository(
156
127
case MongoRepository :
157
128
case TreeRepository :
158
129
if ( ! entityType ) {
159
- throw new EntityTypeMissingError ( object , propertyName , index ) ;
130
+ throw new EntityTypeMissingError ( object , propertyName as string , index ) ;
160
131
}
161
132
}
162
133
163
134
Container . registerHandler ( {
164
- index,
165
135
object : object as Constructable < unknown > ,
166
- propertyName,
167
- value : containerInstance => getRepository ( connectionName , repositoryType , entityType ! , containerInstance ) ,
136
+ index : index ,
137
+ propertyName : propertyName as string ,
138
+ value : containerInstance => getRepositoryHelper ( connectionName , repositoryType , entityType ! , containerInstance ) ,
168
139
} ) ;
169
140
} ;
170
141
}
0 commit comments