-
Notifications
You must be signed in to change notification settings - Fork 40
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(class-transformers): add the EnumFallback decorator
- Loading branch information
1 parent
a1bcd4e
commit c895953
Showing
9 changed files
with
199 additions
and
6 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# Nestjs class transformers | ||
|
||
Extends [class-transformers package](https://github.com/typestack/class-transformer) with additional features. | ||
|
||
## Installation | ||
|
||
```bash | ||
npm install --save @algoan/nestjs-class-transformers | ||
``` | ||
|
||
## EnumFallback | ||
|
||
### Usage | ||
|
||
```ts | ||
import { EnumFallback } from '@algoan/nestjs-class-transformers'; | ||
|
||
export enum UserRole { | ||
ADMIN = 'ADMIN', | ||
READER = 'READER', | ||
} | ||
|
||
class User { | ||
@EnumFallback({ | ||
type: UserRole, | ||
fallback: (value: UserRole) => UserRole.READER // if the role is not "ADMIN" or "READER", then the role will be "READER". | ||
}) | ||
public role?: UserRole; | ||
} | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
module.exports = { | ||
...require('../jest.common'), | ||
|
||
coverageDirectory: "coverage", | ||
collectCoverageFrom: ["./src/**/*.ts"], | ||
|
||
rootDir: ".", | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
{ | ||
"name": "@algoan/nestjs-class-transformers", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "index.js", | ||
"scripts": { | ||
"build": "tsc -p .", | ||
"test:cov": "jest --coverage", | ||
"test": "jest" | ||
}, | ||
"author": "", | ||
"license": "ISC", | ||
"dependencies": { | ||
"class-transformer": "^0.5.1" | ||
} | ||
} |
40 changes: 40 additions & 0 deletions
40
packages/class-transformers/src/enum-fallback.decorator.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import { Transform, TransformOptions } from 'class-transformer'; | ||
|
||
/** | ||
* Options for EnumFallback decorator. | ||
*/ | ||
export interface EnumFallbackOptions<T> { | ||
/** | ||
* The enum type to check against. | ||
*/ | ||
type: { [s: string]: T }; | ||
/** | ||
* A function that returns the fallback value. | ||
* @param value The invalid value. | ||
*/ | ||
fallback: (value: T) => T; | ||
} | ||
|
||
/** | ||
* Return given literal value if it is included in the specific enum type. | ||
* Otherwise, return the value provided by the given fallback function. | ||
*/ | ||
export const EnumFallback = <T>( | ||
params: EnumFallbackOptions<T>, | ||
transformOptions?: TransformOptions, | ||
): PropertyDecorator => { | ||
const { type, fallback } = params; | ||
|
||
return Transform(({ value }) => { | ||
// eslint-disable-next-line no-null/no-null | ||
if (value === undefined || value === null) { | ||
return value; | ||
} | ||
|
||
if (!Object.values(type).includes(value)) { | ||
return fallback(value); | ||
} | ||
|
||
return value; | ||
}, transformOptions); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export * from './enum-fallback.decorator'; |
66 changes: 66 additions & 0 deletions
66
packages/class-transformers/test/enum-fallback-decorator.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
/* eslint-disable no-null/no-null */ | ||
/* eslint-disable max-classes-per-file */ | ||
import { plainToInstance } from 'class-transformer'; | ||
import { EnumFallback } from '../src'; | ||
|
||
describe('EnumFallback Decorator', () => { | ||
enum UserRole { | ||
ADMIN = 'ADMIN', | ||
READER = 'READER', | ||
} | ||
|
||
it('should return the given value if it is valid', async () => { | ||
class User { | ||
@EnumFallback({ type: UserRole, fallback: () => UserRole.READER }) | ||
public role?: UserRole; | ||
} | ||
|
||
const user = plainToInstance(User, { role: 'ADMIN' }); | ||
|
||
expect(user.role).toEqual(UserRole.ADMIN); | ||
}); | ||
|
||
it('should return the fallback value if the given value is invalid', async () => { | ||
class User { | ||
@EnumFallback({ type: UserRole, fallback: () => UserRole.READER }) | ||
public role?: UserRole; | ||
} | ||
|
||
const user = plainToInstance(User, { role: 'WRITER' }); | ||
|
||
expect(user.role).toEqual(UserRole.READER); | ||
}); | ||
|
||
it('should return undefined if the given value is undefined', async () => { | ||
class User { | ||
@EnumFallback({ type: UserRole, fallback: () => UserRole.READER }) | ||
public role?: UserRole; | ||
} | ||
|
||
const user = plainToInstance(User, { role: undefined }); | ||
|
||
expect(user.role).toBeUndefined(); | ||
}); | ||
|
||
it('should return undefined if the given value is null', async () => { | ||
class User { | ||
@EnumFallback({ type: UserRole, fallback: () => UserRole.READER }) | ||
public role?: UserRole; | ||
} | ||
|
||
const user = plainToInstance(User, { role: null }); | ||
|
||
expect(user.role).toBe(null); | ||
}); | ||
|
||
it('should take into account the transform options', async () => { | ||
class User { | ||
@EnumFallback({ type: UserRole, fallback: () => UserRole.READER }, { groups: ['group1'] }) | ||
public role?: UserRole; | ||
} | ||
|
||
const user = plainToInstance(User, { role: 'WRITER' }, { groups: ['group2'] }); | ||
|
||
expect(user.role).toEqual('WRITER'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
{ | ||
"extends": "../tsconfig.base.json", | ||
"compilerOptions": { | ||
"declaration": true, | ||
"experimentalDecorators": true, | ||
"outDir": "dist", | ||
}, | ||
"include": [ | ||
"./src/**/*", | ||
"./test/**/*.ts" | ||
], | ||
"exclude": [ | ||
"node_modules" | ||
] | ||
} |