@dipscope/type-manager 4.1.1 → 5.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/CHANGELOG.md +27 -0
- package/README.md +140 -320
- package/alias.d.ts +3 -7
- package/custom-data.d.ts +3 -8
- package/{core/default-value-resolver.d.ts → default-value-resolver.d.ts} +0 -0
- package/default-value.d.ts +4 -8
- package/discriminant.d.ts +5 -8
- package/discriminator.d.ts +3 -8
- package/factories/type-factory.d.ts +3 -3
- package/factory.d.ts +15 -8
- package/functions/get-own-reflect-metadata.d.ts +9 -0
- package/functions/get-reflect-metadata.d.ts +10 -0
- package/functions/get-words.d.ts +8 -0
- package/functions/index.d.ts +16 -0
- package/functions/is-arrow-function.d.ts +8 -0
- package/functions/is-ctor-function.d.ts +8 -0
- package/functions/is-data-view.d.ts +8 -0
- package/functions/is-float-32-array.d.ts +8 -0
- package/functions/is-float-64-array.d.ts +8 -0
- package/functions/is-int-16-array.d.ts +8 -0
- package/functions/is-int-32-array.d.ts +8 -0
- package/functions/is-int-8-array.d.ts +8 -0
- package/functions/is-uint-16-array.d.ts +8 -0
- package/functions/is-uint-32-array.d.ts +8 -0
- package/functions/is-uint-8-array.d.ts +8 -0
- package/functions/is-uint-8-clamped-array.d.ts +8 -0
- package/functions/name-of.d.ts +8 -0
- package/{core/generic-argument.d.ts → generic-argument.d.ts} +0 -0
- package/{core/generic-metadata.d.ts → generic-metadata.d.ts} +0 -0
- package/index.d.ts +39 -9
- package/index.js +1 -2
- package/{core/inject-index.d.ts → inject-index.d.ts} +0 -0
- package/{core/inject-metadata.d.ts → inject-metadata.d.ts} +17 -1
- package/{core/inject-options.d.ts → inject-options.d.ts} +2 -2
- package/inject.d.ts +2 -2
- package/injector.d.ts +13 -8
- package/injectors/singleton-injector.d.ts +2 -2
- package/{core/log-level.d.ts → log-level.d.ts} +0 -0
- package/{core/log.d.ts → log.d.ts} +41 -11
- package/{core/metadata.d.ts → metadata.d.ts} +0 -0
- package/naming-convention.d.ts +12 -8
- package/naming-conventions/camel-case-naming-convention.d.ts +1 -1
- package/naming-conventions/flat-case-naming-convention.d.ts +1 -1
- package/naming-conventions/flat-upper-case-naming-convention.d.ts +1 -1
- package/naming-conventions/kebab-case-naming-convention.d.ts +1 -1
- package/naming-conventions/kebab-upper-case-naming-convention.d.ts +1 -1
- package/naming-conventions/pascal-case-naming-convention.d.ts +1 -1
- package/naming-conventions/snake-case-naming-convention.d.ts +1 -1
- package/naming-conventions/snake-upper-case-naming-convention.d.ts +1 -1
- package/package.json +15 -8
- package/property-metadata.d.ts +309 -0
- package/{core/property-name.d.ts → property-name.d.ts} +0 -0
- package/{core/property-options.d.ts → property-options.d.ts} +18 -2
- package/property.d.ts +3 -2
- package/{core/reference-callback.d.ts → reference-callback.d.ts} +1 -1
- package/reference-handler.d.ts +28 -8
- package/reference-handlers/direct-reference-handler.d.ts +11 -12
- package/reference-handlers/lead-reference-handler.d.ts +11 -12
- package/reference-handlers/path-reference-handler.d.ts +11 -12
- package/{core/reference-key.d.ts → reference-key.d.ts} +0 -0
- package/reference-value-getter.d.ts +7 -0
- package/reference-value-setter.d.ts +7 -0
- package/{core/reference-value.d.ts → reference-value.d.ts} +0 -0
- package/serializer-context-options.d.ts +43 -0
- package/{core/serializer-context.d.ts → serializer-context.d.ts} +153 -39
- package/serializer.d.ts +24 -8
- package/serializers/array-buffer-serializer.d.ts +3 -3
- package/serializers/array-serializer.d.ts +3 -3
- package/serializers/boolean-serializer.d.ts +3 -3
- package/serializers/data-view-serializer.d.ts +3 -3
- package/serializers/date-serializer.d.ts +3 -3
- package/serializers/float-32-array-serializer.d.ts +3 -3
- package/serializers/float-64-array-serializer.d.ts +3 -3
- package/serializers/int-16-array-serializer.d.ts +3 -3
- package/serializers/int-32-array-serializer.d.ts +3 -3
- package/serializers/int-8-array-serializer.d.ts +3 -3
- package/serializers/map-serializer.d.ts +3 -3
- package/serializers/number-serializer.d.ts +3 -3
- package/serializers/set-serializer.d.ts +3 -3
- package/serializers/string-serializer.d.ts +3 -3
- package/serializers/type-serializer.d.ts +3 -3
- package/serializers/uint-16-array-serializer.d.ts +3 -3
- package/serializers/uint-32-array-serializer.d.ts +3 -3
- package/serializers/uint-8-array-serializer.d.ts +3 -3
- package/serializers/uint-8-clamped-array-serializer.d.ts +3 -3
- package/{core/type-abstraction.d.ts → type-abstraction.d.ts} +0 -0
- package/{core/type-argument.d.ts → type-argument.d.ts} +0 -0
- package/{core/type-context-entry.d.ts → type-context-entry.d.ts} +0 -0
- package/{core/type-context.d.ts → type-context.d.ts} +0 -0
- package/{core/type-ctor.d.ts → type-ctor.d.ts} +0 -0
- package/{core/type-fn.d.ts → type-fn.d.ts} +0 -0
- package/{core/type-like.d.ts → type-like.d.ts} +0 -0
- package/type-manager-options.d.ts +5 -5
- package/type-manager.d.ts +10 -10
- package/{core/type-metadata-resolver.d.ts → type-metadata-resolver.d.ts} +0 -0
- package/{core/type-metadata-symbol.d.ts → type-metadata-symbol.d.ts} +0 -0
- package/{core/type-metadata.d.ts → type-metadata.d.ts} +183 -15
- package/{core/type-name.d.ts → type-name.d.ts} +0 -0
- package/{core/type-options-base.d.ts → type-options-base.d.ts} +9 -19
- package/{core/type-options.d.ts → type-options.d.ts} +28 -2
- package/{core/type-resolver.d.ts → type-resolver.d.ts} +0 -0
- package/type.d.ts +1 -1
- package/core/alias.d.ts +0 -6
- package/core/custom-data.d.ts +0 -6
- package/core/default-value.d.ts +0 -7
- package/core/discriminant.d.ts +0 -8
- package/core/discriminator.d.ts +0 -6
- package/core/factory.d.ts +0 -18
- package/core/fn.d.ts +0 -316
- package/core/index.d.ts +0 -44
- package/core/index.js +0 -2
- package/core/index.js.map +0 -1
- package/core/injector.d.ts +0 -16
- package/core/naming-convention.d.ts +0 -15
- package/core/property-metadata.d.ts +0 -178
- package/core/reference-handler.d.ts +0 -32
- package/core/reference-value-initializer.d.ts +0 -8
- package/core/reference-value-resolver.d.ts +0 -8
- package/core/serializer-context-options.d.ts +0 -63
- package/core/serializer.d.ts +0 -27
- package/deserializable.d.ts +0 -11
- package/deserialized-default-value.d.ts +0 -11
- package/factories/index.js +0 -2
- package/factories/index.js.map +0 -1
- package/index.js.map +0 -1
- package/injectable.d.ts +0 -10
- package/injectors/index.js +0 -2
- package/injectors/index.js.map +0 -1
- package/naming-conventions/index.js +0 -2
- package/naming-conventions/index.js.map +0 -1
- package/preserve-discriminator.d.ts +0 -10
- package/reference-handlers/index.js +0 -2
- package/reference-handlers/index.js.map +0 -1
- package/serializable.d.ts +0 -11
- package/serialized-default-value.d.ts +0 -11
- package/serializers/index.js +0 -2
- package/serializers/index.js.map +0 -1
- package/type-and-property.d.ts +0 -12
- package/use-default-value.d.ts +0 -10
- package/use-implicit-conversion.d.ts +0 -10
package/README.md
CHANGED
|
@@ -19,23 +19,24 @@ If you like or are using this project please give it a star. Thanks!
|
|
|
19
19
|
* [Type decorator](#type-decorator)
|
|
20
20
|
* [Property decorator](#property-decorator)
|
|
21
21
|
* [Inject decorator](#inject-decorator)
|
|
22
|
-
* [Defining
|
|
23
|
-
* [Alias
|
|
24
|
-
* [Custom data
|
|
25
|
-
* [Default value
|
|
26
|
-
* [Deserializable
|
|
27
|
-
* [Discriminant
|
|
28
|
-
* [Discriminator
|
|
29
|
-
* [Factory
|
|
30
|
-
* [Injectable
|
|
31
|
-
* [Injector
|
|
32
|
-
* [Naming convention
|
|
33
|
-
* [Preserve discriminator
|
|
34
|
-
* [
|
|
35
|
-
* [
|
|
36
|
-
* [
|
|
37
|
-
* [
|
|
38
|
-
* [Use
|
|
22
|
+
* [Defining decorator options](#defining-decorator-options)
|
|
23
|
+
* [Alias option](#alias-option)
|
|
24
|
+
* [Custom data option](#custom-data-option)
|
|
25
|
+
* [Default value option](#default-value-option)
|
|
26
|
+
* [Deserializable option](#deserializable-option)
|
|
27
|
+
* [Discriminant option](#discriminant-option)
|
|
28
|
+
* [Discriminator option](#discriminator-option)
|
|
29
|
+
* [Factory option](#factory-option)
|
|
30
|
+
* [Injectable option](#injectable-option)
|
|
31
|
+
* [Injector option](#injector-option)
|
|
32
|
+
* [Naming convention option](#naming-convention-option)
|
|
33
|
+
* [Preserve discriminator option](#preserve-discriminator-option)
|
|
34
|
+
* [Preserve null option](#preserve-null-option)
|
|
35
|
+
* [Reference handler option](#reference-handler-option)
|
|
36
|
+
* [Serializable option](#serializable-option)
|
|
37
|
+
* [Serializer option](#serializer-option)
|
|
38
|
+
* [Use default value option](#use-default-value-option)
|
|
39
|
+
* [Use implicit conversion option](#use-implicit-conversion-option)
|
|
39
40
|
* [Defining configuration manually](#defining-configuration-manually)
|
|
40
41
|
* [Configuring global options](#configuring-global-options)
|
|
41
42
|
* [Configuring options per type](#configuring-options-per-type)
|
|
@@ -154,7 +155,18 @@ for (const user of users)
|
|
|
154
155
|
}
|
|
155
156
|
```
|
|
156
157
|
|
|
157
|
-
Now we can use all power provided by `JavaScript` class instances.
|
|
158
|
+
Now we can use all power provided by `JavaScript` class instances.
|
|
159
|
+
|
|
160
|
+
Furthermore `TypeManager.TS` provides you:
|
|
161
|
+
|
|
162
|
+
* Reflection abilities at runtime;
|
|
163
|
+
* Support for generic types;
|
|
164
|
+
* Handling of cyclic object references and different ways of serialization when they appear;
|
|
165
|
+
* Ability to configure serialization of 3rd party classes;
|
|
166
|
+
* Support for polymorphic types;
|
|
167
|
+
* Great alternative for similar packages like [class-transformer](https://github.com/typestack/class-transformer), [TypedJSON](https://github.com/JohnWeisz/TypedJSON) and [jackson-js](https://github.com/pichillilorenzo/jackson-js);
|
|
168
|
+
|
|
169
|
+
Want to know more? Let's dive into the details.
|
|
158
170
|
|
|
159
171
|
## Installation
|
|
160
172
|
|
|
@@ -166,7 +178,7 @@ npm i @dipscope/type-manager
|
|
|
166
178
|
|
|
167
179
|
TypeScript needs to run with the `experimentalDecorators` and `emitDecoratorMetadata` options enabled when using decorator annotations. So make sure you have properly configured your `tsconfig.json` file.
|
|
168
180
|
|
|
169
|
-
|
|
181
|
+
_If you want additional type-safety and reduced syntax you may wish to install [reflect-metadata](https://github.com/rbuckton/reflect-metadata). This step is on your choice and fully optional. When installed it must be available globally to work. This can usually be done with `import 'reflect-metadata';` in your main index file._
|
|
170
182
|
|
|
171
183
|
## How it works?
|
|
172
184
|
|
|
@@ -195,8 +207,7 @@ Here we have a `User` class with `Type` and `Property` decorators assigned to it
|
|
|
195
207
|
The same configuration can be rewritten using declarative style.
|
|
196
208
|
|
|
197
209
|
```typescript
|
|
198
|
-
import { TypeManager } from '@dipscope/type-manager';
|
|
199
|
-
import { PropertyName, PropertyOptions } from '@dipscope/type-manager/core';
|
|
210
|
+
import { TypeManager, PropertyName, PropertyOptions } from '@dipscope/type-manager';
|
|
200
211
|
|
|
201
212
|
export class User
|
|
202
213
|
{
|
|
@@ -254,7 +265,7 @@ At first glance, it may seems that there is no difference but creating an instan
|
|
|
254
265
|
|
|
255
266
|
## Defining decorators
|
|
256
267
|
|
|
257
|
-
|
|
268
|
+
There are few decorators which controls the main flow. This are `Type`, `Property` and `Inject` decorators. Let's go through each of them.
|
|
258
269
|
|
|
259
270
|
### Type decorator
|
|
260
271
|
|
|
@@ -287,7 +298,7 @@ export class User
|
|
|
287
298
|
|
|
288
299
|
This call defines a type alias which can be later used to resolve a type for a property at runtime. We will talk about details in the property decorator section. Also we defined custom serializer for a type which is an implementation of `Serializer` interface. This serializer will be used later to serialize and deserialize a type including all custom logic of your choice. You can read more about [creating a custom serializer](#defining-custom-serializer) in a separate section.
|
|
289
300
|
|
|
290
|
-
There are more options can be provided for a type, so check `TypeOptions` definition or section with [
|
|
301
|
+
There are more options can be provided for a type, so check `TypeOptions` definition or section with [decorator options](#defining-decorator-options) below.
|
|
291
302
|
|
|
292
303
|
### Property decorator
|
|
293
304
|
|
|
@@ -343,7 +354,7 @@ export class User
|
|
|
343
354
|
}
|
|
344
355
|
```
|
|
345
356
|
|
|
346
|
-
This option configures an alias so `username` property will be used instead of `name` when deserializing from object. There are plenty of configure options, so check `PropertyOptions` definition or section with [
|
|
357
|
+
This option configures an alias so `username` property will be used instead of `name` when deserializing from object. There are plenty of configure options, so check `PropertyOptions` definition or section with [decorator options](#defining-decorator-options) below. For example you can make some properties serializable only or define custom property serialization.
|
|
347
358
|
|
|
348
359
|
Now let's have a look at more complex definitions with generic types. This are `Array<TType>`, `Map<TKey, TValue>` and others. To declare one of this you have to use extra argument available for `Property` decorator. Generic arguments are always passed as array to exactly see them within a source code.
|
|
349
360
|
|
|
@@ -597,16 +608,18 @@ When a string key is provided then a certain value will be resolved from JSON co
|
|
|
597
608
|
When a certain type is provided it will be resolved from the dependency injection container. If you are going to use internal type injector then you should register injectable types as the following. By default singleton injector is used to resolve such services.
|
|
598
609
|
|
|
599
610
|
```typescript
|
|
600
|
-
import {
|
|
611
|
+
import { Type } from '@dipscope/type-manager';
|
|
601
612
|
|
|
602
|
-
@
|
|
613
|
+
@Type({
|
|
614
|
+
injectable: true
|
|
615
|
+
})
|
|
603
616
|
export class UserService
|
|
604
617
|
{
|
|
605
618
|
public property: string;
|
|
606
619
|
}
|
|
607
620
|
```
|
|
608
621
|
|
|
609
|
-
In most cases you will work in environment where dependency injection system is already setted up. In this case you have to implement custom `Injector` to be used instead of our default one. Besides you should follow the steps to register injectable services specified by the vendor.
|
|
622
|
+
In most cases you will work in environment where dependency injection system is already setted up. In this case you have to implement custom `Injector` to be used instead of our default one. Besides you should follow the steps to register injectable services specified by the vendor. You can read more about [creating a custom injector](#defining-custom-injector) in a separate section.
|
|
610
623
|
|
|
611
624
|
If you are using [reflect-metadata](https://github.com/rbuckton/reflect-metadata) the injection of services can be simplified.
|
|
612
625
|
|
|
@@ -629,26 +642,13 @@ export class User
|
|
|
629
642
|
|
|
630
643
|
Note that now you don't have to specify injection for types explicitly. However injection of values by key from JSON context still present. It's because argument names cannot be resolved using reflection.
|
|
631
644
|
|
|
632
|
-
## Defining
|
|
633
|
-
|
|
634
|
-
`Type` and `Property` decorators provide full configuration for your classes using configure options but there is a way to define this extra options using decorators if you want. Each helper decorator exactly much the name of a certain configure option.
|
|
645
|
+
## Defining decorator options
|
|
635
646
|
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
This decorator can be used both on type and property to define an alias.
|
|
639
|
-
|
|
640
|
-
```typescript
|
|
641
|
-
import { Type, Property, Alias } from '@dipscope/type-manager';
|
|
647
|
+
`Type` and `Property` decorators provide full configuration for your classes using configure options. In this section we will go through each of them.
|
|
642
648
|
|
|
643
|
-
|
|
644
|
-
@Alias('User')
|
|
645
|
-
export class User
|
|
646
|
-
{
|
|
647
|
-
@Property(String) @Alias('username') public name: string;
|
|
648
|
-
}
|
|
649
|
-
```
|
|
649
|
+
### Alias option
|
|
650
650
|
|
|
651
|
-
|
|
651
|
+
This option can be used both on type and property to define an alias.
|
|
652
652
|
|
|
653
653
|
```typescript
|
|
654
654
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -666,22 +666,9 @@ Alias defined for a class can be used later for resolving property types. Note t
|
|
|
666
666
|
|
|
667
667
|
Alias defined for a property declares that property name differs from one specified in JSON. In our case `username` will be used instead of `name` during JSON serialization and deserialization.
|
|
668
668
|
|
|
669
|
-
### Custom data
|
|
670
|
-
|
|
671
|
-
This decorator can be used to provide any custom data for type or property.
|
|
672
|
-
|
|
673
|
-
```typescript
|
|
674
|
-
import { Type, Property, CustomData } from '@dipscope/type-manager';
|
|
675
|
-
|
|
676
|
-
@Type()
|
|
677
|
-
@CustomData({ rank: 1 })
|
|
678
|
-
export class User
|
|
679
|
-
{
|
|
680
|
-
@Property(String) @CustomData({ order: 1 }) public name: string;
|
|
681
|
-
}
|
|
682
|
-
```
|
|
669
|
+
### Custom data option
|
|
683
670
|
|
|
684
|
-
|
|
671
|
+
This option can be used to provide any custom data for type or property.
|
|
685
672
|
|
|
686
673
|
```typescript
|
|
687
674
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -697,36 +684,23 @@ export class User
|
|
|
697
684
|
|
|
698
685
|
This custom data later can be accessed in serializers, factories, injectors or your code and used accordingly. Read more about [defining custom data](#defining-custom-data) in a separate section.
|
|
699
686
|
|
|
700
|
-
### Default value
|
|
701
|
-
|
|
702
|
-
This decorator is used to define a default value when one is undefined. It can be used on type or property.
|
|
703
|
-
|
|
704
|
-
```typescript
|
|
705
|
-
import { Type, Property, DefaultValue } from '@dipscope/type-manager';
|
|
706
|
-
|
|
707
|
-
@Type()
|
|
708
|
-
@DefaultValue(() => new User())
|
|
709
|
-
export class User
|
|
710
|
-
{
|
|
711
|
-
@Property(String) @DefaultValue('BestName') public name: string;
|
|
712
|
-
}
|
|
713
|
-
```
|
|
687
|
+
### Default value option
|
|
714
688
|
|
|
715
|
-
This
|
|
689
|
+
This option is used to define a default value when one is undefined. It can be used on type or property.
|
|
716
690
|
|
|
717
691
|
```typescript
|
|
718
|
-
import { Type, Property
|
|
692
|
+
import { Type, Property } from '@dipscope/type-manager';
|
|
719
693
|
|
|
720
|
-
@Type(
|
|
721
|
-
|
|
722
|
-
|
|
694
|
+
@Type({
|
|
695
|
+
defaultValue: () => new User()
|
|
696
|
+
})
|
|
723
697
|
export class User
|
|
724
698
|
{
|
|
725
|
-
@Property(String
|
|
699
|
+
@Property(String, { defaultValue: 'BestName' }) public name: string;
|
|
726
700
|
}
|
|
727
701
|
```
|
|
728
702
|
|
|
729
|
-
|
|
703
|
+
This will affect both serialized and deserialized default value. This will fit perfectly for most types. You can also specify serialized and deserialized default value explicitly for complex types by using two other options.
|
|
730
704
|
|
|
731
705
|
```typescript
|
|
732
706
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -737,27 +711,15 @@ import { Type, Property } from '@dipscope/type-manager';
|
|
|
737
711
|
})
|
|
738
712
|
export class User
|
|
739
713
|
{
|
|
740
|
-
@Property(String, { serializedDefaultValue: '
|
|
714
|
+
@Property(String, { serializedDefaultValue: 'SerializedName', deserializedDefaultValue: 'DeserializedName' }) public name: string;
|
|
741
715
|
}
|
|
742
716
|
```
|
|
743
717
|
|
|
744
|
-
As you can see it accepts an arrow function or a certain value. Both are valid for type and property. Using default values is turned off by default. You can enable them using `
|
|
745
|
-
|
|
746
|
-
### Deserializable decorator
|
|
747
|
-
|
|
748
|
-
This decorator is used to enable or disable deserialization for a certain property.
|
|
749
|
-
|
|
750
|
-
```typescript
|
|
751
|
-
import { Type, Property, Deserializable } from '@dipscope/type-manager';
|
|
718
|
+
As you can see it accepts an arrow function or a certain value. Both are valid for type and property. Using default values is turned off by default. You can enable them using `useDefaultValue` option per type and property or enable globally using `TypeManager` configure method.
|
|
752
719
|
|
|
753
|
-
|
|
754
|
-
export class User
|
|
755
|
-
{
|
|
756
|
-
@Property(String) @Deserializable() public name: string;
|
|
757
|
-
}
|
|
758
|
-
```
|
|
720
|
+
### Deserializable option
|
|
759
721
|
|
|
760
|
-
|
|
722
|
+
This option is used to enable or disable deserialization for a certain property.
|
|
761
723
|
|
|
762
724
|
```typescript
|
|
763
725
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -771,22 +733,9 @@ export class User
|
|
|
771
733
|
|
|
772
734
|
By default all properties are deserializable.
|
|
773
735
|
|
|
774
|
-
### Discriminant
|
|
736
|
+
### Discriminant option
|
|
775
737
|
|
|
776
|
-
This
|
|
777
|
-
|
|
778
|
-
```typescript
|
|
779
|
-
import { Type, Property, Discriminant } from '@dipscope/type-manager';
|
|
780
|
-
|
|
781
|
-
@Type()
|
|
782
|
-
@Discriminant('Company.Api.Entities.User')
|
|
783
|
-
export class User
|
|
784
|
-
{
|
|
785
|
-
@Property(String) public name: string;
|
|
786
|
-
}
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
Such declaration is an alternative for:
|
|
738
|
+
This option is used to define a custom discriminant for a type which is later used during serialization and deserialization of polymorphic types.
|
|
790
739
|
|
|
791
740
|
```typescript
|
|
792
741
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -802,22 +751,9 @@ export class User
|
|
|
802
751
|
|
|
803
752
|
You can read more about handling of polymorphic types in this [section](#configuring-usage-of-polymorphic-types).
|
|
804
753
|
|
|
805
|
-
### Discriminator
|
|
806
|
-
|
|
807
|
-
This decorator can be used to define a custom property which stores discriminant of polymorphic type.
|
|
808
|
-
|
|
809
|
-
```typescript
|
|
810
|
-
import { Type, Property, Discriminator } from '@dipscope/type-manager';
|
|
811
|
-
|
|
812
|
-
@Type()
|
|
813
|
-
@Discriminator('__typename__')
|
|
814
|
-
export class User
|
|
815
|
-
{
|
|
816
|
-
@Property(String) public name: string;
|
|
817
|
-
}
|
|
818
|
-
```
|
|
754
|
+
### Discriminator option
|
|
819
755
|
|
|
820
|
-
|
|
756
|
+
This option can be used to define a custom property which stores discriminant of polymorphic type.
|
|
821
757
|
|
|
822
758
|
```typescript
|
|
823
759
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -833,22 +769,9 @@ export class User
|
|
|
833
769
|
|
|
834
770
|
In common use cases discriminator should be set globally using `TypeManager` configure method. Using this option on a type level makes sense only if discriminator differs from the global one. You can read more about handling of polymorphic types in this [section](#configuring-usage-of-polymorphic-types).
|
|
835
771
|
|
|
836
|
-
### Factory
|
|
837
|
-
|
|
838
|
-
This decorator can be used to register a handler which should be used for constructing a type instead of default one.
|
|
839
|
-
|
|
840
|
-
```typescript
|
|
841
|
-
import { Type, Property, Factory } from '@dipscope/type-manager';
|
|
842
|
-
|
|
843
|
-
@Type()
|
|
844
|
-
@Factory(new UserFactory())
|
|
845
|
-
export class User
|
|
846
|
-
{
|
|
847
|
-
@Property(String) public name: string;
|
|
848
|
-
}
|
|
849
|
-
```
|
|
772
|
+
### Factory option
|
|
850
773
|
|
|
851
|
-
|
|
774
|
+
This option can be used to register a handler which should be used for constructing a type instead of default one.
|
|
852
775
|
|
|
853
776
|
```typescript
|
|
854
777
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -864,22 +787,9 @@ export class User
|
|
|
864
787
|
|
|
865
788
|
This may be useful in cases when you want to init some special application specific properties. Read more about [defining custom factory](#defining-custom-factory) in a separate section.
|
|
866
789
|
|
|
867
|
-
### Injectable
|
|
868
|
-
|
|
869
|
-
This decorator is used to register a type in dependency injection container.
|
|
870
|
-
|
|
871
|
-
```typescript
|
|
872
|
-
import { Injectable } from '@dipscope/type-manager';
|
|
873
|
-
|
|
874
|
-
@Type()
|
|
875
|
-
@Injectable()
|
|
876
|
-
export class UserService
|
|
877
|
-
{
|
|
878
|
-
public property: string;
|
|
879
|
-
}
|
|
880
|
-
```
|
|
790
|
+
### Injectable option
|
|
881
791
|
|
|
882
|
-
|
|
792
|
+
This option is used to register a type in dependency injection container.
|
|
883
793
|
|
|
884
794
|
```typescript
|
|
885
795
|
import { Type } from '@dipscope/type-manager';
|
|
@@ -912,24 +822,11 @@ export class User
|
|
|
912
822
|
}
|
|
913
823
|
```
|
|
914
824
|
|
|
915
|
-
In most cases you will work in environment where dependency injection system is already setted up. In this case you have to implement custom `Injector` to be used instead of our default one. Besides you should follow the steps to register injectable services specified by the vendor.
|
|
916
|
-
|
|
917
|
-
### Injector decorator
|
|
918
|
-
|
|
919
|
-
This decorator can be used to define a custom injector implementation which should be used in a type scope.
|
|
825
|
+
In most cases you will work in environment where dependency injection system is already setted up. In this case you have to implement custom `Injector` to be used instead of our default one. Besides you should follow the steps to register injectable services specified by the vendor. You can read more about [creating a custom injector](#defining-custom-injector) in a separate section.
|
|
920
826
|
|
|
921
|
-
|
|
922
|
-
import { Type, Property, Injector } from '@dipscope/type-manager';
|
|
923
|
-
|
|
924
|
-
@Type()
|
|
925
|
-
@Injector(new UserInjector())
|
|
926
|
-
export class User
|
|
927
|
-
{
|
|
928
|
-
@Property(String) public name: string;
|
|
929
|
-
}
|
|
930
|
-
```
|
|
827
|
+
### Injector option
|
|
931
828
|
|
|
932
|
-
|
|
829
|
+
This option can be used to define a custom injector implementation which should be used in a type scope.
|
|
933
830
|
|
|
934
831
|
```typescript
|
|
935
832
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -945,27 +842,12 @@ export class User
|
|
|
945
842
|
|
|
946
843
|
In most cases this is not required and the common use case is to specify injector globally instead. You can read more about [defining custom injector](#defining-custom-injector) in a separate section.
|
|
947
844
|
|
|
948
|
-
### Naming convention
|
|
949
|
-
|
|
950
|
-
This decorator can be used both on type and property to provide custom naming strategy.
|
|
951
|
-
|
|
952
|
-
```typescript
|
|
953
|
-
import { Type, Property, NamingConvention } from '@dipscope/type-manager';
|
|
954
|
-
import { CamelCaseNamingConvention, SnakeCaseNamingConvention } from '@dipscope/type-manager/naming-conventions';
|
|
955
|
-
|
|
956
|
-
@Type()
|
|
957
|
-
@NamingConvention(new CamelCaseNamingConvention())
|
|
958
|
-
export class User
|
|
959
|
-
{
|
|
960
|
-
@Property(String) @NamingConvention(new SnakeCaseNamingConvention()) public name: string;
|
|
961
|
-
}
|
|
962
|
-
```
|
|
845
|
+
### Naming convention option
|
|
963
846
|
|
|
964
|
-
|
|
847
|
+
This option can be used both on type and property to provide custom naming strategy.
|
|
965
848
|
|
|
966
849
|
```typescript
|
|
967
|
-
import { Type, Property } from '@dipscope/type-manager';
|
|
968
|
-
import { CamelCaseNamingConvention, SnakeCaseNamingConvention } from '@dipscope/type-manager/naming-conventions';
|
|
850
|
+
import { Type, Property, CamelCaseNamingConvention, SnakeCaseNamingConvention } from '@dipscope/type-manager';
|
|
969
851
|
|
|
970
852
|
@Type({
|
|
971
853
|
namingConvention: new CamelCaseNamingConvention()
|
|
@@ -978,22 +860,9 @@ export class User
|
|
|
978
860
|
|
|
979
861
|
In most cases this is not required and the common use case is to specify naming strategy globally instead. You can read more about [configuring naming convention](#configuring-naming-convention) in a separate section.
|
|
980
862
|
|
|
981
|
-
### Preserve discriminator
|
|
863
|
+
### Preserve discriminator option
|
|
982
864
|
|
|
983
|
-
This
|
|
984
|
-
|
|
985
|
-
```typescript
|
|
986
|
-
import { Type, Property, PreserveDiscriminator } from '@dipscope/type-manager';
|
|
987
|
-
|
|
988
|
-
@Type()
|
|
989
|
-
@PreserveDiscriminator()
|
|
990
|
-
export class User
|
|
991
|
-
{
|
|
992
|
-
@Property(String) public name: string;
|
|
993
|
-
}
|
|
994
|
-
```
|
|
995
|
-
|
|
996
|
-
Such declaration is an alternative for:
|
|
865
|
+
This option defines if discriminator should be preserved in objects during serialization and deserialization.
|
|
997
866
|
|
|
998
867
|
```typescript
|
|
999
868
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -1009,27 +878,30 @@ export class User
|
|
|
1009
878
|
|
|
1010
879
|
By default discriminator is not preserved and only used during deserialization of polymorphic types. You can read more about handling of polymorphic types in this [section](#configuring-usage-of-polymorphic-types).
|
|
1011
880
|
|
|
1012
|
-
###
|
|
881
|
+
### Preserve null option
|
|
1013
882
|
|
|
1014
|
-
This
|
|
883
|
+
This option defines if null values should be preserved during serialization and deserialization.
|
|
1015
884
|
|
|
1016
885
|
```typescript
|
|
1017
|
-
import { Type, Property
|
|
1018
|
-
import { DirectReferenceHandler, LeadReferenceHandler } from '@dipscope/type-manager/reference-handlers';
|
|
886
|
+
import { Type, Property } from '@dipscope/type-manager';
|
|
1019
887
|
|
|
1020
|
-
@Type(
|
|
1021
|
-
|
|
888
|
+
@Type({
|
|
889
|
+
preserveNull: true
|
|
890
|
+
})
|
|
1022
891
|
export class User
|
|
1023
892
|
{
|
|
1024
|
-
@Property(String
|
|
893
|
+
@Property(String, { preserveNull: false }) public name: string;
|
|
1025
894
|
}
|
|
1026
895
|
```
|
|
1027
896
|
|
|
1028
|
-
|
|
897
|
+
By default null values are preserved. You can set it to `false` per type, property or globally using `TypeManager` configure method. This will result in treating null values as undefined so you will get all related behaviours like setting default values.
|
|
898
|
+
|
|
899
|
+
### Reference handler option
|
|
900
|
+
|
|
901
|
+
This option can be used both on type and property to specify how references to the same objects should be handled during serialization and deserialization.
|
|
1029
902
|
|
|
1030
903
|
```typescript
|
|
1031
|
-
import { Type, Property } from '@dipscope/type-manager';
|
|
1032
|
-
import { DirectReferenceHandler, LeadReferenceHandler } from '@dipscope/type-manager/reference-handlers';
|
|
904
|
+
import { Type, Property, DirectReferenceHandler, LeadReferenceHandler } from '@dipscope/type-manager';
|
|
1033
905
|
|
|
1034
906
|
@Type({
|
|
1035
907
|
referenceHandler: new DirectReferenceHandler()
|
|
@@ -1042,21 +914,9 @@ export class User
|
|
|
1042
914
|
|
|
1043
915
|
In most cases this is not required and the common use case is to specify reference handler globally instead. You can read more about [configuring reference handler](#configuring-reference-handler) in a separate section.
|
|
1044
916
|
|
|
1045
|
-
### Serializable
|
|
1046
|
-
|
|
1047
|
-
This decorator is used to enable or disable serialization for a certain property.
|
|
1048
|
-
|
|
1049
|
-
```typescript
|
|
1050
|
-
import { Type, Property, Serializable } from '@dipscope/type-manager';
|
|
1051
|
-
|
|
1052
|
-
@Type()
|
|
1053
|
-
export class User
|
|
1054
|
-
{
|
|
1055
|
-
@Property(String) @Serializable() public name: string;
|
|
1056
|
-
}
|
|
1057
|
-
```
|
|
917
|
+
### Serializable option
|
|
1058
918
|
|
|
1059
|
-
|
|
919
|
+
This option is used to enable or disable serialization for a certain property.
|
|
1060
920
|
|
|
1061
921
|
```typescript
|
|
1062
922
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -1070,22 +930,9 @@ export class User
|
|
|
1070
930
|
|
|
1071
931
|
By default all properties are serializable.
|
|
1072
932
|
|
|
1073
|
-
### Serializer
|
|
1074
|
-
|
|
1075
|
-
This decorator is used to define custom serializer for a type or property.
|
|
1076
|
-
|
|
1077
|
-
```typescript
|
|
1078
|
-
import { Type, Property, Serializer } from '@dipscope/type-manager';
|
|
1079
|
-
|
|
1080
|
-
@Type()
|
|
1081
|
-
@Serializer(new UserSerializer())
|
|
1082
|
-
export class User
|
|
1083
|
-
{
|
|
1084
|
-
@Property(String) @Serializer(new UserNameSerializer()) public name: string;
|
|
1085
|
-
}
|
|
1086
|
-
```
|
|
933
|
+
### Serializer option
|
|
1087
934
|
|
|
1088
|
-
|
|
935
|
+
This option is used to define custom serializer for a type or property.
|
|
1089
936
|
|
|
1090
937
|
```typescript
|
|
1091
938
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -1101,22 +948,9 @@ export class User
|
|
|
1101
948
|
|
|
1102
949
|
Custom serializer should be an implementation of `Serializer` interface. You can read more about [creating a custom serializer](#defining-custom-serializer) in a separate section.
|
|
1103
950
|
|
|
1104
|
-
### Use default value
|
|
1105
|
-
|
|
1106
|
-
This decorator enables or disables using default value per type or property.
|
|
951
|
+
### Use default value option
|
|
1107
952
|
|
|
1108
|
-
|
|
1109
|
-
import { Type, Property, UseDefaultValue } from '@dipscope/type-manager';
|
|
1110
|
-
|
|
1111
|
-
@Type()
|
|
1112
|
-
@UseDefaultValue()
|
|
1113
|
-
export class User
|
|
1114
|
-
{
|
|
1115
|
-
@Property(String) @UseDefaultValue(false) public name: string;
|
|
1116
|
-
}
|
|
1117
|
-
```
|
|
1118
|
-
|
|
1119
|
-
Such declaration is an alternative for:
|
|
953
|
+
This option enables or disables using default value per type or property.
|
|
1120
954
|
|
|
1121
955
|
```typescript
|
|
1122
956
|
import { Type, Property } from '@dipscope/type-manager';
|
|
@@ -1132,22 +966,10 @@ export class User
|
|
|
1132
966
|
|
|
1133
967
|
Using default values is turned off by default. You can enable them globally using `TypeManager` configure method.
|
|
1134
968
|
|
|
1135
|
-
### Use implicit conversion
|
|
969
|
+
### Use implicit conversion option
|
|
1136
970
|
|
|
1137
971
|
By default if declared type will not match provided during serialization or deserialization an error will be logged and result value will be undefined. This means that for example assigning `Number` to `String` will not work as `StringSerializer` expects `String`. However `Number` and other types can be converted to `String` for you when implicit conversion is enabled.
|
|
1138
972
|
|
|
1139
|
-
```typescript
|
|
1140
|
-
import { Type, Property, UseImplicitConversion } from '@dipscope/type-manager';
|
|
1141
|
-
|
|
1142
|
-
@Type()
|
|
1143
|
-
export class User
|
|
1144
|
-
{
|
|
1145
|
-
@Property(String) @UseImplicitConversion() public name: string;
|
|
1146
|
-
}
|
|
1147
|
-
```
|
|
1148
|
-
|
|
1149
|
-
Such declaration is an alternative for:
|
|
1150
|
-
|
|
1151
973
|
```typescript
|
|
1152
974
|
import { Type, Property } from '@dipscope/type-manager';
|
|
1153
975
|
|
|
@@ -1158,7 +980,7 @@ export class User
|
|
|
1158
980
|
}
|
|
1159
981
|
```
|
|
1160
982
|
|
|
1161
|
-
With this any value which can be converted to `String` will be converted properly. Such behaviour works for other built in serializers and supported for custom ones. By default implicit conversion is turned off. You can enable it using `
|
|
983
|
+
With this any value which can be converted to `String` will be converted properly. Such behaviour works for other built in serializers and supported for custom ones. By default implicit conversion is turned off. You can enable it using `useImplicitConversion` option per type and property or enable globally using `TypeManager` configure method.
|
|
1162
984
|
|
|
1163
985
|
## Defining configuration manually
|
|
1164
986
|
|
|
@@ -1171,8 +993,7 @@ We have separate methods to configure each type manager option, so the provided
|
|
|
1171
993
|
There are several options which can be configured globally. For example let's override using of default value option so we don't have to specify it explicitly per type or property.
|
|
1172
994
|
|
|
1173
995
|
```typescript
|
|
1174
|
-
import { TypeManagerOptions } from '@dipscope/type-manager';
|
|
1175
|
-
import { TypeOptionsBase } from '@dipscope/type-manager/core';
|
|
996
|
+
import { TypeManagerOptions, TypeOptionsBase } from '@dipscope/type-manager';
|
|
1176
997
|
|
|
1177
998
|
const typeOptionsBase: TypeOptionsBase<any> = {
|
|
1178
999
|
useDefaultValue: true
|
|
@@ -1193,8 +1014,7 @@ Here is an example of declarative configuration which can be used for 3rd party
|
|
|
1193
1014
|
|
|
1194
1015
|
```typescript
|
|
1195
1016
|
import { DateTime } from '@external-library';
|
|
1196
|
-
import { TypeManagerOptions } from '@dipscope/type-manager';
|
|
1197
|
-
import { TypeFn, TypeOptions, PropertyName, PropertyOptions } from '@dipscope/type-manager/core';
|
|
1017
|
+
import { TypeManagerOptions, TypeFn, TypeOptions, PropertyName, PropertyOptions } from '@dipscope/type-manager';
|
|
1198
1018
|
|
|
1199
1019
|
const dateTimeOptions: TypeOptions<DateTime> = {
|
|
1200
1020
|
alias: 'DateTime',
|
|
@@ -1399,8 +1219,7 @@ In some cases your `Discriminator` or `Discriminant` values will not match to ou
|
|
|
1399
1219
|
To change `Discriminator` globally you have to use `TypeManager` configure method.
|
|
1400
1220
|
|
|
1401
1221
|
```typescript
|
|
1402
|
-
import { TypeManagerOptions } from '@dipscope/type-manager';
|
|
1403
|
-
import { TypeOptionsBase } from '@dipscope/type-manager/core';
|
|
1222
|
+
import { TypeManagerOptions, TypeOptionsBase } from '@dipscope/type-manager';
|
|
1404
1223
|
|
|
1405
1224
|
const typeOptionsBase: TypeOptionsBase<any> = {
|
|
1406
1225
|
discriminator: '$customType'
|
|
@@ -1416,8 +1235,7 @@ TypeManager.configure(typeManagerOptions);
|
|
|
1416
1235
|
To change `Discriminant` you have to use per type configuration.
|
|
1417
1236
|
|
|
1418
1237
|
```typescript
|
|
1419
|
-
import { TypeManagerOptions } from '@dipscope/type-manager';
|
|
1420
|
-
import { TypeFn, TypeOptions, PropertyName, PropertyOptions } from '@dipscope/type-manager/core';
|
|
1238
|
+
import { TypeManagerOptions, TypeFn, TypeOptions, PropertyName, PropertyOptions } from '@dipscope/type-manager';
|
|
1421
1239
|
|
|
1422
1240
|
const rectangleOptions: TypeOptions<Rectangle> = {
|
|
1423
1241
|
discriminant: 'Company.Api.Entities.Rectangle'
|
|
@@ -1445,32 +1263,36 @@ TypeManager.configure(typeManagerOptions);
|
|
|
1445
1263
|
As an alternative you can change `Discriminant` as the following using decorators.
|
|
1446
1264
|
|
|
1447
1265
|
```typescript
|
|
1448
|
-
import { Type, Property
|
|
1266
|
+
import { Type, Property } from '@dipscope/type-manager';
|
|
1449
1267
|
|
|
1450
|
-
@Type(
|
|
1451
|
-
|
|
1268
|
+
@Type({
|
|
1269
|
+
discriminant: 'Company.Api.Entities.Shape'
|
|
1270
|
+
})
|
|
1452
1271
|
export abstract class Shape
|
|
1453
1272
|
{
|
|
1454
1273
|
@Property(String) public title: string;
|
|
1455
1274
|
}
|
|
1456
1275
|
|
|
1457
|
-
@Type(
|
|
1458
|
-
|
|
1276
|
+
@Type({
|
|
1277
|
+
discriminant: 'Company.Api.Entities.Rectangle'
|
|
1278
|
+
})
|
|
1459
1279
|
export class Rectangle extends Shape
|
|
1460
1280
|
{
|
|
1461
1281
|
@Property(Number) public width: number;
|
|
1462
1282
|
@Property(Number) public height: number;
|
|
1463
1283
|
}
|
|
1464
1284
|
|
|
1465
|
-
@Type(
|
|
1466
|
-
|
|
1285
|
+
@Type({
|
|
1286
|
+
discriminant: 'Company.Api.Entities.Square'
|
|
1287
|
+
})
|
|
1467
1288
|
export class Square extends Shape
|
|
1468
1289
|
{
|
|
1469
1290
|
@Property(Number) public width: number;
|
|
1470
1291
|
}
|
|
1471
1292
|
|
|
1472
|
-
@Type(
|
|
1473
|
-
|
|
1293
|
+
@Type({
|
|
1294
|
+
discriminant: 'Company.Api.Entities.Circle'
|
|
1295
|
+
})
|
|
1474
1296
|
export class Circle extends Shape
|
|
1475
1297
|
{
|
|
1476
1298
|
@Property(Number) public radius: number;
|
|
@@ -1480,8 +1302,7 @@ export class Circle extends Shape
|
|
|
1480
1302
|
By default `Discriminator` is not preserved inside objects and only used during deserialization. You can change this behavior by enabling preserving of discriminator globally or per type.
|
|
1481
1303
|
|
|
1482
1304
|
```typescript
|
|
1483
|
-
import { TypeManagerOptions } from '@dipscope/type-manager';
|
|
1484
|
-
import { TypeOptionsBase } from '@dipscope/type-manager/core';
|
|
1305
|
+
import { TypeManagerOptions, TypeOptionsBase } from '@dipscope/type-manager';
|
|
1485
1306
|
|
|
1486
1307
|
const typeOptionsBase: TypeOptionsBase<any> = {
|
|
1487
1308
|
preserveDiscriminator: true
|
|
@@ -1559,14 +1380,14 @@ But what to do if we don't control the JSON naming convention so it comes to us
|
|
|
1559
1380
|
We can still parse such a JSON by specifying an alias for each property but this will become a pain in a while.
|
|
1560
1381
|
|
|
1561
1382
|
```typescript
|
|
1562
|
-
import { Type, Property
|
|
1383
|
+
import { Type, Property } from '@dipscope/type-manager';
|
|
1563
1384
|
|
|
1564
1385
|
@Type()
|
|
1565
1386
|
export class User
|
|
1566
1387
|
{
|
|
1567
1388
|
@Property(String) public name: string;
|
|
1568
|
-
@Property(Number
|
|
1569
|
-
@Property(DateTime
|
|
1389
|
+
@Property(Number, { alias: 'login_count' }) public loginCount: number;
|
|
1390
|
+
@Property(DateTime, { alias: 'created_at' }) public createdAt: DateTime;
|
|
1570
1391
|
}
|
|
1571
1392
|
```
|
|
1572
1393
|
|
|
@@ -1584,9 +1405,7 @@ export class User
|
|
|
1584
1405
|
To set one we have to configure global options.
|
|
1585
1406
|
|
|
1586
1407
|
```typescript
|
|
1587
|
-
import { TypeManagerOptions } from '@dipscope/type-manager';
|
|
1588
|
-
import { TypeOptionsBase } from '@dipscope/type-manager/core';
|
|
1589
|
-
import { SnakeCaseNamingConvention } from '@dipscope/type-manager/naming-conventions';
|
|
1408
|
+
import { TypeManagerOptions, TypeOptionsBase, SnakeCaseNamingConvention } from '@dipscope/type-manager';
|
|
1590
1409
|
|
|
1591
1410
|
const typeOptionsBase: TypeOptionsBase<any> = {
|
|
1592
1411
|
namingConvention: new SnakeCaseNamingConvention()
|
|
@@ -1657,9 +1476,7 @@ Here are results returned by different reference handlers:
|
|
|
1657
1476
|
As you can see `DirectReferenceHandler` does not make changes to your data and completely fine until you have to convert circular reference structure to a string. `JSON.stringify` method which we are using under the hood does not support such conversions so you will encounter an error. In this case you can select another reference handler. For example `PathReferenceHandler` which produces JSON string using JSONPath format for circular references supported by many libraries. Or you can simply ignore circular reference when it should be converted to a string and use `LeadReferenceHandler`. To change default reference handler you have to use `TypeManager` configure methods.
|
|
1658
1477
|
|
|
1659
1478
|
```typescript
|
|
1660
|
-
import { TypeManagerOptions } from '@dipscope/type-manager';
|
|
1661
|
-
import { TypeOptionsBase } from '@dipscope/type-manager/core';
|
|
1662
|
-
import { PathReferenceHandler } from '@dipscope/type-manager/reference-handlers';
|
|
1479
|
+
import { TypeManagerOptions, TypeOptionsBase, PathReferenceHandler } from '@dipscope/type-manager';
|
|
1663
1480
|
|
|
1664
1481
|
const typeOptionsBase: TypeOptionsBase<any> = {
|
|
1665
1482
|
referenceHandler: new PathReferenceHandler()
|
|
@@ -1683,13 +1500,14 @@ Our goal is to cover as much use cases as possible without making you to write a
|
|
|
1683
1500
|
You can attach you custom metadata to our decorators using `customData` option available on `Type` and `Property`.
|
|
1684
1501
|
|
|
1685
1502
|
```typescript
|
|
1686
|
-
import { Type, Property
|
|
1503
|
+
import { Type, Property } from '@dipscope/type-manager';
|
|
1687
1504
|
|
|
1688
|
-
@Type(
|
|
1689
|
-
|
|
1505
|
+
@Type({
|
|
1506
|
+
customData: { rank: 1 }
|
|
1507
|
+
})
|
|
1690
1508
|
class User
|
|
1691
1509
|
{
|
|
1692
|
-
@Property(String
|
|
1510
|
+
@Property(String, { customData: { priority: 10 } }) public name: string;
|
|
1693
1511
|
}
|
|
1694
1512
|
```
|
|
1695
1513
|
|
|
@@ -1716,7 +1534,8 @@ for (const propertyMetadata of userMetadata.propertyMetadataMap.values())
|
|
|
1716
1534
|
You can create your own serializer or replace built in one. First you have to implement `Serializer` interface. It declares `serialize` and `deserialize` methods. Serialize method is called during conversion of `JavaScript` object instance into a plain object. Deserialize method is called during backward conversion. Here is an example of possible definition for custom `DateTime` class.
|
|
1717
1535
|
|
|
1718
1536
|
```typescript
|
|
1719
|
-
import { Serializer, TypeLike, SerializerContext
|
|
1537
|
+
import { Serializer, TypeLike, SerializerContext } from '@dipscope/type-manager';
|
|
1538
|
+
import { Fn } from '@app/module';
|
|
1720
1539
|
|
|
1721
1540
|
export class DateTimeSerializer implements Serializer<DateTime>
|
|
1722
1541
|
{
|
|
@@ -1739,7 +1558,7 @@ export class DateTimeSerializer implements Serializer<DateTime>
|
|
|
1739
1558
|
|
|
1740
1559
|
if (serializerContext.log.errorEnabled)
|
|
1741
1560
|
{
|
|
1742
|
-
serializerContext.log.error(`${serializerContext.path}:
|
|
1561
|
+
serializerContext.log.error(`${serializerContext.path}: cannot serialize value as date time.`, x);
|
|
1743
1562
|
}
|
|
1744
1563
|
|
|
1745
1564
|
return undefined;
|
|
@@ -1764,7 +1583,7 @@ export class DateTimeSerializer implements Serializer<DateTime>
|
|
|
1764
1583
|
|
|
1765
1584
|
if (serializerContext.log.errorEnabled)
|
|
1766
1585
|
{
|
|
1767
|
-
serializerContext.log.error(`${serializerContext.path}:
|
|
1586
|
+
serializerContext.log.error(`${serializerContext.path}: cannot deserialize value as date time.`, x);
|
|
1768
1587
|
}
|
|
1769
1588
|
|
|
1770
1589
|
return undefined;
|
|
@@ -1781,8 +1600,9 @@ When you are finished with definitions there are two possible ways to register a
|
|
|
1781
1600
|
```typescript
|
|
1782
1601
|
import { Type, Serializer } from '@dipscope/type-manager';
|
|
1783
1602
|
|
|
1784
|
-
@Type(
|
|
1785
|
-
|
|
1603
|
+
@Type({
|
|
1604
|
+
serializer: new DateTimeSerializer()
|
|
1605
|
+
})
|
|
1786
1606
|
export class DateTime
|
|
1787
1607
|
{
|
|
1788
1608
|
...
|
|
@@ -1807,7 +1627,7 @@ With declarative configuration it is possible to override built in serializers i
|
|
|
1807
1627
|
In modern world we are always use some kind of framework to build our application. It is definitely already have a configured dependency injection container so let's configure `TypeManager` for using it instead of build in one. You have to implement `Injector` interface with only one method. Here how it may look like in `Angular`.
|
|
1808
1628
|
|
|
1809
1629
|
```typescript
|
|
1810
|
-
import { Injector, TypeMetadata } from '@dipscope/type-manager
|
|
1630
|
+
import { Injector, TypeMetadata } from '@dipscope/type-manager';
|
|
1811
1631
|
import { Injector as AngularInjector } from '@angular/core';
|
|
1812
1632
|
|
|
1813
1633
|
export class CustomInjector implements Injector
|
|
@@ -1848,8 +1668,7 @@ Now types will be resolved using framework injector.
|
|
|
1848
1668
|
When you want to apply additional logic to how types are constructed you can specify custom factory globally or per type. Let's say you want to init some properties based on your custom data specified for a type. You can do this by extending default `TypeFactory`.
|
|
1849
1669
|
|
|
1850
1670
|
```typescript
|
|
1851
|
-
import { TypeContext, Injector } from '@dipscope/type-manager
|
|
1852
|
-
import { TypeFactory } from '@dipscope/type-manager/factories';
|
|
1671
|
+
import { TypeContext, Injector, TypeFactory } from '@dipscope/type-manager';
|
|
1853
1672
|
|
|
1854
1673
|
export class CustomTypeFactory extends TypeFactory
|
|
1855
1674
|
{
|
|
@@ -1876,11 +1695,12 @@ export class CustomTypeFactory extends TypeFactory
|
|
|
1876
1695
|
When you are finished with definitions there are two possible ways to register a factory. You can use decorators.
|
|
1877
1696
|
|
|
1878
1697
|
```typescript
|
|
1879
|
-
import { Type, Factory
|
|
1698
|
+
import { Type, Factory } from '@dipscope/type-manager';
|
|
1880
1699
|
|
|
1881
|
-
@Type(
|
|
1882
|
-
|
|
1883
|
-
|
|
1700
|
+
@Type({
|
|
1701
|
+
customData: { rank: 1 },
|
|
1702
|
+
factory: new CustomTypeFactory()
|
|
1703
|
+
})
|
|
1884
1704
|
export class User
|
|
1885
1705
|
{
|
|
1886
1706
|
...
|
|
@@ -1909,13 +1729,13 @@ TypeManager.configureTypeOptionsBase({
|
|
|
1909
1729
|
To define custom naming convention you have to implement `NamingConvention` interface with only one `convert` method. Here is an example implementation of camel case naming convention.
|
|
1910
1730
|
|
|
1911
1731
|
```typescript
|
|
1912
|
-
import { NamingConvention,
|
|
1732
|
+
import { NamingConvention, getWords } from '@dipscope/type-manager';
|
|
1913
1733
|
|
|
1914
1734
|
export class CamelCaseNamingConvention implements NamingConvention
|
|
1915
1735
|
{
|
|
1916
1736
|
public convert(name: string): string
|
|
1917
1737
|
{
|
|
1918
|
-
return
|
|
1738
|
+
return getWords(name).reduce(this.reduce, '');
|
|
1919
1739
|
}
|
|
1920
1740
|
|
|
1921
1741
|
private reduce(result: string, word: string, index: number): string
|
|
@@ -1937,7 +1757,7 @@ export class CamelCaseNamingConvention implements NamingConvention
|
|
|
1937
1757
|
}
|
|
1938
1758
|
```
|
|
1939
1759
|
|
|
1940
|
-
Public `convert` method receives a property name as it declared in a class. You have to call internal `
|
|
1760
|
+
Public `convert` method receives a property name as it declared in a class. You have to call internal `getWords` function on it which will split property name into array of the words. In the `reduce` function you can combine this words to whatever string you want. When you are finished with definitions you have to register custom naming convention for a `TypeManager`.
|
|
1941
1761
|
|
|
1942
1762
|
```typescript
|
|
1943
1763
|
import { TypeManager } from '@dipscope/type-manager';
|