Skip to content

Commit 9333437

Browse files
author
Ugo evola
committed
initial commit
0 parents  commit 9333437

20 files changed

+690
-0
lines changed

Diff for: .gitignore

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# compiled output
2+
/dist
3+
/node_modules
4+
5+
# Logs
6+
logs
7+
*.log
8+
npm-debug.log*
9+
pnpm-debug.log*
10+
yarn-debug.log*
11+
yarn-error.log*
12+
lerna-debug.log*
13+
publish.sh
14+
15+
# OS
16+
.DS_Store
17+
18+
# Tests
19+
/coverage
20+
/.nyc_output
21+
22+
# IDEs and editors
23+
/.idea
24+
.project
25+
.classpath
26+
.c9/
27+
*.launch
28+
.settings/
29+
*.sublime-workspace
30+
31+
# IDE - VSCode
32+
.vscode/*
33+
!.vscode/settings.json
34+
!.vscode/tasks.json
35+
!.vscode/launch.json
36+
!.vscode/extensions.json

Diff for: README.md

+137
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
# TS-mapstruct
2+
3+
TS-Mapstruct is an approach of the JAVA [MapStruct](https://mapstruct.org/) addapted in **TypeScript**.
4+
It's a code generator that simplifies the implementation of mappings over configuration approach.
5+
6+
## Installation
7+
8+
```
9+
npm install ts-mapstruct
10+
```
11+
## prerequisites
12+
13+
The DTO used in the mapper must have well named getters and setters in camelCase for each mapped properties.\
14+
It is recommended that the DTO constructor can be empty for simplify the code, but it is not a problem if it cannot.
15+
## Usage
16+
For the exemple, I will take a **UserMapper** that maps a **UserDto** into **UserEntity**.
17+
### DTO
18+
19+
```ts
20+
export class UserDto {
21+
private fname: string;
22+
private lname: string;
23+
private bdate: number;
24+
private isMajor: boolean;
25+
private gender: GenderEnum;
26+
27+
constructor() {}
28+
29+
getFname(): string {
30+
return this.fname;
31+
}
32+
33+
setFname(fname: string): void {
34+
return this.fname = fname;
35+
}
36+
37+
// **OTHER GETTERS AND SETTERS**
38+
}
39+
```
40+
```ts
41+
export class UserEntity {
42+
private fullName: string;
43+
private cn: string;
44+
private sn: string;
45+
private bdate: number;
46+
private isMajor: boolean;
47+
private lastConnexionTime: number;
48+
49+
constructor(fullName?: string) {
50+
this.fullName = fullName;
51+
}
52+
53+
// **GETTERS AND SETTERS**
54+
}
55+
```
56+
### Mapper
57+
58+
Create a Mapper class that wrap the mapping functions.\
59+
It is necessary to type the arguments and the return value of each function.\
60+
This function must also return an object with the good type without which it will not work.\
61+
That's why it simplifies the code to have an empty constructor for the DTO.\
62+
Finally decorate your method with the **@Mappings** decorator by passing the different mapping options.
63+
64+
```ts
65+
export class UserMapper {
66+
67+
/*-------------------*\
68+
UserDto -> User
69+
\*-------------------*/
70+
71+
@Mappings(
72+
{ target: 'fullName', expression: 'getConcatProperties(fname, lname)' },
73+
{ target: 'cn', source: 'fname' },
74+
{ target: 'sn', source: 'sname' },
75+
{ target: 'lastConnexionTime', value: Date.now()},
76+
)
77+
entityFromDto(_userDto: UserDto): UserEntity {
78+
return new UserEntity;
79+
}
80+
81+
entitiesFromDtos(userDto: UserDto[]): UserEntity[] {
82+
return userDto.map(this.entityFromDto);
83+
}
84+
85+
/*-------------------*\
86+
Mapping methods
87+
\*-------------------*/
88+
89+
getConcatProperties(...properties: [...any, string?]): string {
90+
...
91+
}
92+
}
93+
```
94+
95+
In this case, the fullName will be computed with the expression passed in expression options.\
96+
The porperties bdate and isMajor will automatically retrieve their match value from the DTO.\
97+
The property lastConnexionTime is set with the value passed in the value option.\
98+
The others are mapped with the value of the DTO's property passed to the source option.\
99+
And the gender property is ignored.
100+
101+
### Mapping Options
102+
| Properties | Description | Required |
103+
| ----------- | ----------- | ------------ |
104+
| target | The target name property | true |
105+
| source | The source name property | false |
106+
| value | A direct value | false |
107+
| expression | A JS expression | false |
108+
109+
You must provide exactly one of the non required properties in the @Mappings decorator, an Exception will be throw otherwise.
110+
111+
### Supplied Mapping Functions
112+
the mapper provides some functions to pass via the "expression" property to facilitate the mapping:
113+
```ts
114+
/**
115+
* concatenates each property provided in the running order.
116+
* You have the possibility to define a separator passed at the last index
117+
* @params properties: properties to concat
118+
* @return string: the concatenation of each properties
119+
* @required each property must be a string
120+
*/
121+
getConcatProperties(...properties: [...string, string?]): string
122+
```
123+
## Exceptions thrown
124+
125+
**BadExpressionExceptionMapper**
126+
127+
**EmptySourceNameExceptionMapper**
128+
129+
**IllegalMappingOptionsExceptionMapper**
130+
131+
**IllegalObjectAccessExceptionMapper**
132+
133+
**IllegalPropertyKeyExceptionMapper**
134+
135+
**IllegalPropertyValueExceptionMapper**
136+
137+
**InvalidSourceNameExceptionMapper**

Diff for: index.ts

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export * from './src/decorators/mappings.decorator'
2+
export * from './src/models/mapping-options'
3+
export * from './src/shared/mapping-functions'

Diff for: package-lock.json

+181
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: package.json

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
{
2+
"name": "ts-mapstruct",
3+
"version": "1.0.1",
4+
"main": "dist/index.js",
5+
"types": "dist/index.d.ts",
6+
"files": [
7+
"/dist"
8+
],
9+
"repository": {
10+
"type": "git",
11+
"url": "https://github.com/ugoevola/ts-mapstruct"
12+
},
13+
"author": "",
14+
"license": "ISC",
15+
"description": "",
16+
"dependencies": {
17+
"@nestjs/common": "^8.0.6",
18+
"class-validator": "^0.13.2",
19+
"lodash": "^4.17.21",
20+
"reflect-metadata": "^0.1.13"
21+
},
22+
"devDependencies": {
23+
"@types/express": "^4.17.13",
24+
"@types/lodash": "^4.14.182",
25+
"@types/sanitizer": "0.0.28",
26+
"rxjs": "^6.5.4"
27+
}
28+
}

Diff for: publish.sh

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
#!/bin/bash
2+
tsc
3+
npm -f unpublish
4+
npm publish --access public

0 commit comments

Comments
 (0)