Skip to content

Commit

Permalink
feat(class-transformers): support array for EnumFallback decorator
Browse files Browse the repository at this point in the history
  • Loading branch information
amarlankri committed Dec 21, 2023
1 parent 7213b43 commit 6d649d5
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 11 deletions.
18 changes: 18 additions & 0 deletions packages/class-transformers/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,21 @@ class User {
public role?: UserRole;
}
```

It works with array too:
```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 an array element is not "ADMIN" or "READER", then the role will be "READER".
})
public roles: UserRole[];
}
```
30 changes: 19 additions & 11 deletions packages/class-transformers/src/enum-fallback.decorator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,31 @@ export interface EnumFallbackOptions<T> {
/**
* Return given literal value if it is included in the specific enum type.
* Otherwise, return the value provided by the given fallback function.
* If the value is an array, the fallback function will be applied to each element.
*/
export const EnumFallback = <T>(
params: EnumFallbackOptions<T>,
transformOptions?: TransformOptions,
): PropertyDecorator => {
const { type, fallback } = params;
): PropertyDecorator =>
Transform((transformParams) => {
const value = transformParams.value;

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);
if (Array.isArray(value)) {
return value.map((element) => transformEnumValue(element, params));
} else {
return transformEnumValue(value, params);
}
}, transformOptions);

const transformEnumValue = <T>(value: T, { type, fallback }: EnumFallbackOptions<T>): T => {
// eslint-disable-next-line no-null/no-null
if (value === undefined || value === null) {
return value;
}, transformOptions);
}

if (!Object.values(type).includes(value)) {
return fallback(value);
}

return value;
};
11 changes: 11 additions & 0 deletions packages/class-transformers/test/enum-fallback-decorator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,15 @@ describe('EnumFallback Decorator', () => {

expect(user.role).toEqual('WRITER');
});

it('should return the fallback value for each invalid element if the property is an array', async () => {
class User {
@EnumFallback({ type: UserRole, fallback: () => UserRole.READER })
public roles?: UserRole[];
}

const user = plainToInstance(User, { roles: ['WRITER', 'ADMIN'] });

expect(user.roles).toEqual([UserRole.READER, UserRole.ADMIN]);
});
});

0 comments on commit 6d649d5

Please sign in to comment.