@loopback/metadata 4.0.0-alpha.9 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +1 -1
- package/README.md +273 -150
- package/dist/decorator-factory.d.ts +297 -0
- package/{dist6/src → dist}/decorator-factory.js +197 -90
- package/dist/decorator-factory.js.map +1 -0
- package/dist/index.d.ts +22 -1
- package/dist/index.js +24 -7
- package/dist/index.js.map +1 -0
- package/dist/inspector.d.ts +120 -0
- package/dist/inspector.js +186 -0
- package/dist/inspector.js.map +1 -0
- package/dist/{src/reflect.d.ts → reflect.d.ts} +16 -15
- package/dist/{src/reflect.js → reflect.js} +7 -8
- package/dist/reflect.js.map +1 -0
- package/dist/types.d.ts +70 -0
- package/dist/types.js +32 -0
- package/dist/types.js.map +1 -0
- package/package.json +43 -44
- package/src/decorator-factory.ts +289 -140
- package/src/index.ts +22 -2
- package/src/inspector.ts +118 -126
- package/src/reflect.ts +32 -21
- package/src/types.ts +94 -0
- package/CHANGELOG.md +0 -99
- package/api-docs/apple-touch-icon-114x114-precomposed.png +0 -0
- package/api-docs/apple-touch-icon-144x144-precomposed.png +0 -0
- package/api-docs/apple-touch-icon-57x57-precomposed.png +0 -0
- package/api-docs/apple-touch-icon-72x72-precomposed.png +0 -0
- package/api-docs/apple-touch-icon-precomposed.png +0 -0
- package/api-docs/apple-touch-icon.png +0 -0
- package/api-docs/css/bootstrap.min.css +0 -9
- package/api-docs/css/code-themes/arta.css +0 -158
- package/api-docs/css/code-themes/ascetic.css +0 -50
- package/api-docs/css/code-themes/brown_paper.css +0 -104
- package/api-docs/css/code-themes/brown_papersq.png +0 -0
- package/api-docs/css/code-themes/dark.css +0 -103
- package/api-docs/css/code-themes/default.css +0 -135
- package/api-docs/css/code-themes/far.css +0 -111
- package/api-docs/css/code-themes/github.css +0 -127
- package/api-docs/css/code-themes/googlecode.css +0 -144
- package/api-docs/css/code-themes/idea.css +0 -121
- package/api-docs/css/code-themes/ir_black.css +0 -104
- package/api-docs/css/code-themes/magula.css +0 -121
- package/api-docs/css/code-themes/monokai.css +0 -114
- package/api-docs/css/code-themes/pojoaque.css +0 -104
- package/api-docs/css/code-themes/pojoaque.jpg +0 -0
- package/api-docs/css/code-themes/rainbow.css +0 -114
- package/api-docs/css/code-themes/school_book.css +0 -111
- package/api-docs/css/code-themes/school_book.png +0 -0
- package/api-docs/css/code-themes/sl-theme.css +0 -45
- package/api-docs/css/code-themes/solarized_dark.css +0 -88
- package/api-docs/css/code-themes/solarized_light.css +0 -88
- package/api-docs/css/code-themes/sunburst.css +0 -158
- package/api-docs/css/code-themes/tomorrow-night-blue.css +0 -52
- package/api-docs/css/code-themes/tomorrow-night-bright.css +0 -51
- package/api-docs/css/code-themes/tomorrow-night-eighties.css +0 -51
- package/api-docs/css/code-themes/tomorrow-night.css +0 -52
- package/api-docs/css/code-themes/tomorrow.css +0 -49
- package/api-docs/css/code-themes/vs.css +0 -86
- package/api-docs/css/code-themes/xcode.css +0 -154
- package/api-docs/css/code-themes/zenburn.css +0 -115
- package/api-docs/css/main.css +0 -139
- package/api-docs/favicon.ico +0 -0
- package/api-docs/fonts/0ihfXUL2emPh0ROJezvraLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
- package/api-docs/fonts/OsJ2DjdpjqFRVUSto6IffLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
- package/api-docs/fonts/_aijTyevf54tkVDLy-dlnLO3LdcAZYWl9Si6vvxL-qU.woff +0 -0
- package/api-docs/index.html +0 -53
- package/api-docs/js/main.js +0 -19
- package/api-docs/js/vendor/bootstrap.min.js +0 -6
- package/api-docs/js/vendor/jquery-1.10.1.min.js +0 -6
- package/api-docs/js/vendor/jquery.scrollTo-1.4.3.1.js +0 -218
- package/api-docs/js/vendor/modernizr-2.6.2-respond-1.1.0.min.js +0 -11
- package/dist/src/decorator-factory.d.ts +0 -252
- package/dist/src/decorator-factory.js +0 -468
- package/dist/src/decorator-factory.js.map +0 -1
- package/dist/src/index.d.ts +0 -3
- package/dist/src/index.js +0 -13
- package/dist/src/index.js.map +0 -1
- package/dist/src/inspector.d.ts +0 -150
- package/dist/src/inspector.js +0 -163
- package/dist/src/inspector.js.map +0 -1
- package/dist/src/reflect.js.map +0 -1
- package/dist6/index.d.ts +0 -1
- package/dist6/index.js +0 -13
- package/dist6/src/decorator-factory.d.ts +0 -252
- package/dist6/src/decorator-factory.js.map +0 -1
- package/dist6/src/index.d.ts +0 -3
- package/dist6/src/index.js +0 -13
- package/dist6/src/index.js.map +0 -1
- package/dist6/src/inspector.d.ts +0 -150
- package/dist6/src/inspector.js +0 -163
- package/dist6/src/inspector.js.map +0 -1
- package/dist6/src/reflect.d.ts +0 -38
- package/dist6/src/reflect.js +0 -143
- package/dist6/src/reflect.js.map +0 -1
- package/index.d.ts +0 -6
- package/index.js +0 -7
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
# @loopback/metadata
|
|
2
2
|
|
|
3
|
-
This module contains utilities to help developers implement
|
|
4
|
-
|
|
3
|
+
This module contains utilities to help developers implement
|
|
4
|
+
[TypeScript decorators](https://www.typescriptlang.org/docs/handbook/decorators.html),
|
|
5
|
+
define/merge metadata, and inspect metadata.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
- Reflector: Wrapper of
|
|
7
8
|
[reflect-metadata](https://github.com/rbuckton/reflect-metadata)
|
|
8
|
-
|
|
9
|
+
- Decorator factories: A set of factories for class/method/property/parameter
|
|
9
10
|
decorators to apply metadata to a given class and its static or instance
|
|
10
11
|
members.
|
|
11
|
-
|
|
12
|
+
- MetadataInspector: High level APIs to inspect a class and/or its members to
|
|
12
13
|
get metadata applied by decorators.
|
|
13
14
|
|
|
14
|
-
|
|
15
|
+
## Basic Use
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
### To create a class decorator
|
|
17
18
|
|
|
18
19
|
```ts
|
|
19
20
|
import {ClassDecoratorFactory} from '@loopback/metadata';
|
|
@@ -27,11 +28,12 @@ function myClassDecorator(spec: MyClassMetadata): ClassDecorator {
|
|
|
27
28
|
return ClassDecoratorFactory.createDecorator<MyClassMetadata>(
|
|
28
29
|
'metadata-key-for-my-class-decorator',
|
|
29
30
|
spec,
|
|
31
|
+
{decoratorName: '@myClassDecorator'},
|
|
30
32
|
);
|
|
31
33
|
}
|
|
32
34
|
```
|
|
33
35
|
|
|
34
|
-
|
|
36
|
+
Alternatively, we can instantiate the factory and create a decorator:
|
|
35
37
|
|
|
36
38
|
```ts
|
|
37
39
|
function myClassDecorator(spec: MyClassMetadata): ClassDecorator {
|
|
@@ -50,7 +52,7 @@ Now we can use `@myClassDecorator` to add metadata to a class as follows:
|
|
|
50
52
|
class MyController {}
|
|
51
53
|
```
|
|
52
54
|
|
|
53
|
-
|
|
55
|
+
### To create a method decorator
|
|
54
56
|
|
|
55
57
|
```ts
|
|
56
58
|
import {MethodDecoratorFactory} from '@loopback/metadata';
|
|
@@ -85,7 +87,115 @@ class MyController {
|
|
|
85
87
|
}
|
|
86
88
|
```
|
|
87
89
|
|
|
88
|
-
|
|
90
|
+
### To create a decorator that can be used multiple times on a single method
|
|
91
|
+
|
|
92
|
+
Instead of a single immutable object to be merged, the
|
|
93
|
+
`MethodMultiDecoratorFactory` reduced parameters into a flat array of items.
|
|
94
|
+
When fetching the metadata later, you will receive it as an array.
|
|
95
|
+
|
|
96
|
+
```ts
|
|
97
|
+
import {MethodMultiDecoratorFactory} from '@loopback/metadata';
|
|
98
|
+
|
|
99
|
+
function myMultiMethodDecorator(spec: object): MethodDecorator {
|
|
100
|
+
return MethodMultiDecoratorFactory.createDecorator<object>(
|
|
101
|
+
'metadata-key-for-my-method-multi-decorator',
|
|
102
|
+
spec,
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Now, you can use it multiple times on a method:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
class MyController {
|
|
111
|
+
@myMultiMethodDecorator({x: 1})
|
|
112
|
+
@myMultiMethodDecorator({y: 2})
|
|
113
|
+
@myMultiMethodDecorator({z: 3})
|
|
114
|
+
public point() {}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
class MyOtherController {
|
|
118
|
+
@myMultiMethodDecorator([{x: 1}, {y: 2}, {z: 3}])
|
|
119
|
+
public point() {}
|
|
120
|
+
}
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
And when you access this data:
|
|
124
|
+
|
|
125
|
+
```ts
|
|
126
|
+
const arrayOfSpecs = MetadataInspector.getMethodMetadata<object>(
|
|
127
|
+
'metadata-key-for-my-method-multi-decorator',
|
|
128
|
+
constructor.prototype,
|
|
129
|
+
op,
|
|
130
|
+
);
|
|
131
|
+
|
|
132
|
+
// [{z: 3}, {y: 2}, {x: 1}]
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
Typescript
|
|
136
|
+
[applies decorators in reverse order](https://www.typescriptlang.org/docs/handbook/decorators.html)
|
|
137
|
+
per class, from the parent down. The metadata array resurned by `getOwnMetadata`
|
|
138
|
+
will be in this order:
|
|
139
|
+
|
|
140
|
+
```ts
|
|
141
|
+
class Parent {
|
|
142
|
+
@myMultiMethodDecorator('A') // second
|
|
143
|
+
@myMultiMethodDecorator('B') // first
|
|
144
|
+
public greet() {}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
class Child extends Parent {
|
|
148
|
+
@myMultiMethodDecorator(['C', 'D']) // [third, fourth]
|
|
149
|
+
public greet() {}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
class Grandchild extends Child {
|
|
153
|
+
@myMultiMethodDecorator('E') // sixth
|
|
154
|
+
@myMultiMethodDecorator('F') // fifth
|
|
155
|
+
public greet() {}
|
|
156
|
+
}
|
|
157
|
+
// getMethodMetadata = ['B', 'A', 'C', 'D', 'F', 'E']
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
You can also create a decorator that takes an object that can contain an array:
|
|
161
|
+
|
|
162
|
+
```ts
|
|
163
|
+
interface Point {
|
|
164
|
+
x?: number;
|
|
165
|
+
y?: number;
|
|
166
|
+
z?: number;
|
|
167
|
+
}
|
|
168
|
+
interface GeometryMetadata {
|
|
169
|
+
points: Point[];
|
|
170
|
+
}
|
|
171
|
+
function geometry(...points: Point[]): MethodDecorator {
|
|
172
|
+
return MethodMultiDecoratorFactory.createDecorator<GeometryMetadata>(
|
|
173
|
+
'metadata-key-for-my-method-multi-decorator',
|
|
174
|
+
points,
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
class MyGeoController {
|
|
179
|
+
@geometry({x: 1})
|
|
180
|
+
@geometry({x: 2}, {y: 3})
|
|
181
|
+
@geometry({z: 5})
|
|
182
|
+
public abstract() {}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
const arrayOfSpecs = MetadataInspector.getMethodMetadata<GeometryMetadata>(
|
|
186
|
+
'metadata-key-for-my-method-multi-decorator',
|
|
187
|
+
constructor.prototype,
|
|
188
|
+
op,
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
// [
|
|
192
|
+
// { points: [{x: 1}]},
|
|
193
|
+
// { points: [{x:2}, {y:3}]},
|
|
194
|
+
// { points: [{z: 5}]},
|
|
195
|
+
// ]
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### To create a property decorator
|
|
89
199
|
|
|
90
200
|
```ts
|
|
91
201
|
import {PropertyDecoratorFactory} from '@loopback/metadata';
|
|
@@ -95,7 +205,7 @@ export interface MyPropertyMetadata {
|
|
|
95
205
|
description?: string;
|
|
96
206
|
}
|
|
97
207
|
|
|
98
|
-
function
|
|
208
|
+
function myPropertyDecorator(spec: MyPropertyMetadata): PropertyDecorator {
|
|
99
209
|
return PropertyDecoratorFactory.createDecorator<MyPropertyMetadata>(
|
|
100
210
|
'metadata-key-for-my-property-decorator',
|
|
101
211
|
spec,
|
|
@@ -118,7 +228,7 @@ class MyController {
|
|
|
118
228
|
}
|
|
119
229
|
```
|
|
120
230
|
|
|
121
|
-
|
|
231
|
+
### To create a parameter decorator
|
|
122
232
|
|
|
123
233
|
```ts
|
|
124
234
|
import {ParameterDecoratorFactory} from '@loopback/metadata';
|
|
@@ -128,7 +238,7 @@ export interface MyParameterMetadata {
|
|
|
128
238
|
description?: string;
|
|
129
239
|
}
|
|
130
240
|
|
|
131
|
-
function
|
|
241
|
+
function myParameterDecorator(spec: MyParameterMetadata): ParameterDecorator {
|
|
132
242
|
return ParameterDecoratorFactory.createDecorator<MyParameterMetadata>(
|
|
133
243
|
'metadata-key-for-my-parameter-decorator',
|
|
134
244
|
spec,
|
|
@@ -136,34 +246,29 @@ function myParameterdDecorator(spec: MyParameterMetadata): ParameterDecorator {
|
|
|
136
246
|
}
|
|
137
247
|
```
|
|
138
248
|
|
|
139
|
-
Now we can use `@myParameterDecorator` to add metadata to a parameter as
|
|
249
|
+
Now we can use `@myParameterDecorator` to add metadata to a parameter as
|
|
250
|
+
follows:
|
|
140
251
|
|
|
141
252
|
```ts
|
|
142
253
|
class MyController {
|
|
143
254
|
constructor(
|
|
144
|
-
@myParameterDecorator({name: 'logging-prefix'})
|
|
145
|
-
public
|
|
146
|
-
@myParameterDecorator({name: 'logging-level'})
|
|
147
|
-
public level: number,
|
|
255
|
+
@myParameterDecorator({name: 'logging-prefix'}) public prefix: string,
|
|
256
|
+
@myParameterDecorator({name: 'logging-level'}) public level: number,
|
|
148
257
|
) {}
|
|
149
258
|
|
|
150
259
|
myMethod(
|
|
151
|
-
@myParameterDecorator({name: 'x'})
|
|
152
|
-
|
|
153
|
-
@myParameterDecorator({name: 'y'})
|
|
154
|
-
y: number,
|
|
260
|
+
@myParameterDecorator({name: 'x'}) x: number,
|
|
261
|
+
@myParameterDecorator({name: 'y'}) y: number,
|
|
155
262
|
) {}
|
|
156
263
|
|
|
157
264
|
static myStaticMethod(
|
|
158
|
-
@myParameterDecorator({name: 'a'})
|
|
159
|
-
|
|
160
|
-
@myParameterDecorator({name: 'b'})
|
|
161
|
-
b: string,
|
|
265
|
+
@myParameterDecorator({name: 'a'}) a: string,
|
|
266
|
+
@myParameterDecorator({name: 'b'}) b: string,
|
|
162
267
|
) {}
|
|
163
268
|
}
|
|
164
269
|
```
|
|
165
270
|
|
|
166
|
-
|
|
271
|
+
### To create method decorator for parameters
|
|
167
272
|
|
|
168
273
|
```ts
|
|
169
274
|
import {MethodParameterDecoratorFactory} from '@loopback/metadata';
|
|
@@ -183,149 +288,150 @@ function myMethodParameterDecorator(
|
|
|
183
288
|
}
|
|
184
289
|
```
|
|
185
290
|
|
|
186
|
-
Now we can use `@myMethodParameterDecorator` to add metadata to a parameter
|
|
187
|
-
|
|
291
|
+
Now we can use `@myMethodParameterDecorator` to add metadata to a parameter as
|
|
292
|
+
follows:
|
|
188
293
|
|
|
189
294
|
```ts
|
|
190
295
|
class MyController {
|
|
191
296
|
@myMethodParameterDecorator({name: 'x'})
|
|
192
297
|
@myMethodParameterDecorator({name: 'y'})
|
|
193
|
-
myMethod(
|
|
194
|
-
|
|
195
|
-
y: number,
|
|
196
|
-
) {}
|
|
298
|
+
myMethod(x: number, y: number) {}
|
|
299
|
+
}
|
|
197
300
|
```
|
|
198
301
|
|
|
199
302
|
**WARNING**: Using method decorators to provide metadata for parameters is
|
|
200
303
|
strongly discouraged for a few reasons:
|
|
201
304
|
|
|
202
|
-
1.
|
|
203
|
-
2.
|
|
305
|
+
1. Method decorators cannot be applied to a constructor
|
|
306
|
+
2. Method decorators depends on the positions to match parameters
|
|
204
307
|
|
|
205
308
|
We recommend that `ParameterDecorator` be used instead.
|
|
206
309
|
|
|
207
|
-
|
|
310
|
+
### Decorator options
|
|
208
311
|
|
|
209
312
|
An object of type `DecoratorOptions` can be passed in to create decorator
|
|
210
313
|
functions. There are two flags for the options:
|
|
211
314
|
|
|
212
|
-
- allowInheritance: Controls if inherited metadata will be honored. Default to
|
|
315
|
+
- allowInheritance: Controls if inherited metadata will be honored. Default to
|
|
316
|
+
`true`.
|
|
213
317
|
- cloneInputSpec: Controls if the value of `spec` argument will be cloned.
|
|
214
|
-
Sometimes we use shared spec for the decoration, but the decorator function
|
|
215
|
-
might need to mutate the object. Cloning the input spec makes it safe to use
|
|
216
|
-
the same spec (`template`) to decorate different members. Default to `true`.
|
|
318
|
+
Sometimes we use shared spec for the decoration, but the decorator function
|
|
319
|
+
might need to mutate the object. Cloning the input spec makes it safe to use
|
|
320
|
+
the same spec (`template`) to decorate different members. Default to `true`.
|
|
321
|
+
- decoratorName: Name for the decorator such as `@inject` for error and
|
|
322
|
+
debugging messages.
|
|
217
323
|
|
|
218
|
-
|
|
324
|
+
### Customize inheritance of metadata
|
|
219
325
|
|
|
220
326
|
By default, the decorator factories allow inheritance with the following rules:
|
|
221
327
|
|
|
222
|
-
1.
|
|
223
|
-
|
|
224
|
-
|
|
328
|
+
1. If the metadata is an object, we merge the `spec` argument from the
|
|
329
|
+
decorator function into the inherited value from base classes. For metadata
|
|
330
|
+
of array and other primitive types, the `spec` argument is used if provided.
|
|
225
331
|
|
|
226
|
-
- We can override `inherit` method of the decorator factory to customize
|
|
227
|
-
|
|
332
|
+
- We can override `inherit` method of the decorator factory to customize how
|
|
333
|
+
to resolve `spec` against the inherited metadata. For example:
|
|
228
334
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
335
|
+
```ts
|
|
336
|
+
protected inherit(inheritedMetadata: T | undefined | null): T {
|
|
337
|
+
// Ignore the inherited metadata
|
|
338
|
+
return this.spec;
|
|
339
|
+
}
|
|
340
|
+
```
|
|
235
341
|
|
|
236
|
-
2.
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
342
|
+
2. Method/property/parameter level metadata is applied to the class or its
|
|
343
|
+
prototype as a map keyed method/property names. We think this approach is
|
|
344
|
+
better than keeping metadata at method/property level as it's not easy to
|
|
345
|
+
inspect a class to find static/instance methods and properties with
|
|
346
|
+
decorations. The metadata for a class is illustrated below:
|
|
241
347
|
|
|
242
348
|
- MyClass (the constructor function itself)
|
|
243
349
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
3.
|
|
314
|
-
to a given target member (class/method/property/parameter) more than
|
|
315
|
-
For example, the following usage will report an error at runtime.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
350
|
+
```ts
|
|
351
|
+
{
|
|
352
|
+
// Class level metadata
|
|
353
|
+
'my-class-decorator-key': MyClassMetadata,
|
|
354
|
+
// Static method (including the constructor) parameter metadata
|
|
355
|
+
'my-static-parameter-decorator-key': {
|
|
356
|
+
'': [MyConstructorParameterMetadata], // Constructor parameter metadata
|
|
357
|
+
'myStaticMethod1': [MyStaticMethodParameterMetadata],
|
|
358
|
+
'myStaticMethod2': [MyStaticMethodParameterMetadata],
|
|
359
|
+
},
|
|
360
|
+
// Static method metadata
|
|
361
|
+
'my-static-method-decorator-key': {
|
|
362
|
+
'myStaticMethod1': MyStaticMethodMetadata,
|
|
363
|
+
'myStaticMethod2': MyStaticMethodMetadata,
|
|
364
|
+
},
|
|
365
|
+
// Static property metadata
|
|
366
|
+
'my-static-property-decorator-key': {
|
|
367
|
+
'myStaticMethod1': MyStaticPropertyMetadata,
|
|
368
|
+
'myStaticMethod1': MyStaticPropertyMetadata,
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
- MyClass.prototype
|
|
374
|
+
|
|
375
|
+
```ts
|
|
376
|
+
{
|
|
377
|
+
// Instance method parameter metadata
|
|
378
|
+
'my-instance-parameter-decorator-key': {
|
|
379
|
+
'myMethod1': [MyMethodParameterMetadata],
|
|
380
|
+
'myMethod2': [MyMethodParameterMetadata],
|
|
381
|
+
},
|
|
382
|
+
// Instance method metadata
|
|
383
|
+
'my-instance-method-decorator-key': {
|
|
384
|
+
'myMethod1': MyMethodMetadata,
|
|
385
|
+
'myMethod2': MyMethodMetadata,
|
|
386
|
+
},
|
|
387
|
+
// Instance property metadata
|
|
388
|
+
'my-instance-property-decorator-key': {
|
|
389
|
+
'myProperty1': MyPropertyMetadata,
|
|
390
|
+
'myProperty2': MyPropertyMetadata,
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
The following methods in `DecoratorFactory` allow subclasses to customize how to
|
|
396
|
+
merge the `spec` with existing metadata for a class, methods, properties, and
|
|
397
|
+
method parameters. Please note `M` is a map for methods/properties/parameters.
|
|
398
|
+
|
|
399
|
+
```ts
|
|
400
|
+
protected mergeWithInherited(
|
|
401
|
+
inheritedMetadata: M,
|
|
402
|
+
target: Object,
|
|
403
|
+
member?: string,
|
|
404
|
+
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
|
|
405
|
+
): M {
|
|
406
|
+
// ...
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
protected mergeWithOwn(
|
|
410
|
+
ownMetadata: M,
|
|
411
|
+
target: Object,
|
|
412
|
+
member?: string,
|
|
413
|
+
descriptorOrIndex?: TypedPropertyDescriptor<any> | number,
|
|
414
|
+
): M {
|
|
415
|
+
// ...
|
|
416
|
+
}
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
3. The default implementation throws errors if the same decorator function is
|
|
420
|
+
applied to a given target member (class/method/property/parameter) more than
|
|
421
|
+
once. For example, the following usage will report an error at runtime.
|
|
422
|
+
|
|
423
|
+
```ts
|
|
424
|
+
@myClassDecorator({name: 'my-controller'})
|
|
425
|
+
@myClassDecorator({name: 'your-controller'})
|
|
426
|
+
class MyController {}
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
### Inspect metadata
|
|
324
430
|
|
|
325
431
|
`MetadataInspector` provides API to inspect metadata from a class and its
|
|
326
432
|
members.
|
|
327
433
|
|
|
328
|
-
|
|
434
|
+
### Inspect metadata of a class
|
|
329
435
|
|
|
330
436
|
```ts
|
|
331
437
|
import {MetadataInspector} from '@loopback/metadata';
|
|
@@ -336,7 +442,7 @@ const meta = MetadataInspector.getClassMetadata(
|
|
|
336
442
|
);
|
|
337
443
|
```
|
|
338
444
|
|
|
339
|
-
|
|
445
|
+
### Inspect own metadata of a class
|
|
340
446
|
|
|
341
447
|
```ts
|
|
342
448
|
import {MetadataInspector} from '@loopback/metadata';
|
|
@@ -350,7 +456,7 @@ const meta = MetadataInspector.getClassMetadata<MyClassMetaData>(
|
|
|
350
456
|
);
|
|
351
457
|
```
|
|
352
458
|
|
|
353
|
-
|
|
459
|
+
### Inspect metadata of a method
|
|
354
460
|
|
|
355
461
|
```ts
|
|
356
462
|
import {MetadataInspector} from '@loopback/metadata';
|
|
@@ -367,7 +473,7 @@ const myMethod = MetadataInspector.getMethodMetaData<MyMethodMetadata>(
|
|
|
367
473
|
);
|
|
368
474
|
```
|
|
369
475
|
|
|
370
|
-
|
|
476
|
+
### Inspect metadata of a property
|
|
371
477
|
|
|
372
478
|
```ts
|
|
373
479
|
import {MetadataInspector} from '@loopback/metadata';
|
|
@@ -384,7 +490,7 @@ const myProp = MetadataInspector.getMethodMetaData<MyMethodMetadata>(
|
|
|
384
490
|
);
|
|
385
491
|
```
|
|
386
492
|
|
|
387
|
-
|
|
493
|
+
### Inspect metadata of method parameters
|
|
388
494
|
|
|
389
495
|
```ts
|
|
390
496
|
import {MetadataInspector} from '@loopback/metadata';
|
|
@@ -412,7 +518,26 @@ const allParamsForConstructor =
|
|
|
412
518
|
);
|
|
413
519
|
```
|
|
414
520
|
|
|
415
|
-
|
|
521
|
+
### Use strong-typed metadata access key
|
|
522
|
+
|
|
523
|
+
You can use MetadataAccessor to provide type checks for metadata access via
|
|
524
|
+
keys. For example,
|
|
525
|
+
|
|
526
|
+
```ts
|
|
527
|
+
const CLASS_KEY = MetadataAccessor.create<MyClassMetadata, ClassDecorator>(
|
|
528
|
+
'my-class-decorator-key',
|
|
529
|
+
);
|
|
530
|
+
|
|
531
|
+
// Create a class decorator with the key
|
|
532
|
+
const myClassDecorator = ClassDecoratorFactory.createDecorator(CLASS_KEY);
|
|
533
|
+
|
|
534
|
+
// Inspect a class with the key
|
|
535
|
+
const myClassMeta = MetadataInspector.getClassMetaData(CLASS_KEY, MyController);
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
Please note MetadataKey can be an instance of MetadataAccessor or a string.
|
|
539
|
+
|
|
540
|
+
### Inspect design-time metadata of properties/methods
|
|
416
541
|
|
|
417
542
|
```ts
|
|
418
543
|
import {MetadataInspector} from '@loopback/metadata';
|
|
@@ -435,16 +560,14 @@ const myMethod = MetadataInspector.getDesignTypeForMethod(
|
|
|
435
560
|
|
|
436
561
|
## Installation
|
|
437
562
|
|
|
438
|
-
```
|
|
439
|
-
|
|
563
|
+
```sh
|
|
564
|
+
npm install --save @loopback/metadata
|
|
440
565
|
```
|
|
441
566
|
|
|
442
567
|
## Contributions
|
|
443
568
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
information on how to contribute please refer to the
|
|
447
|
-
[Contribution Guide](https://loopback.io/doc/en/contrib/index.html).
|
|
569
|
+
- [Guidelines](https://github.com/loopbackio/loopback-next/blob/master/docs/CONTRIBUTING.md)
|
|
570
|
+
- [Join the team](https://github.com/loopbackio/loopback-next/issues/110)
|
|
448
571
|
|
|
449
572
|
## Tests
|
|
450
573
|
|
|
@@ -453,7 +576,7 @@ Run `npm test` from the root folder.
|
|
|
453
576
|
## Contributors
|
|
454
577
|
|
|
455
578
|
See
|
|
456
|
-
[all contributors](https://github.com/
|
|
579
|
+
[all contributors](https://github.com/loopbackio/loopback-next/graphs/contributors).
|
|
457
580
|
|
|
458
581
|
## License
|
|
459
582
|
|