Skip to content

Commit 5f1a1b3

Browse files
committed
feat(decorators): IsOptional
Signed-off-by: Lexus Drumgold <[email protected]>
1 parent 2b4cdba commit 5f1a1b3

File tree

3 files changed

+56
-0
lines changed

3 files changed

+56
-0
lines changed
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/**
2+
* @file Functional Tests - IsOptional
3+
* @module sneusers/decorators/tests/functional/IsOptional
4+
*/
5+
6+
import { IsString, validate } from 'class-validator'
7+
import TestSubject from '../is-optional.decorator'
8+
9+
describe('functional:decorators/IsOptional', () => {
10+
it('should ignore property validators if value is undefined', async () => {
11+
// Arrange
12+
class TestModel {
13+
@IsString()
14+
@TestSubject()
15+
public readonly $property: string | undefined = undefined
16+
}
17+
18+
// Act + Expect
19+
expect(await validate(new TestModel())).to.be.an('array').that.is.empty
20+
})
21+
})

src/decorators/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,5 @@
77
*/
88

99
export { default as IsNullable } from './is-nullable.decorator'
10+
export { default as IsOptional } from './is-optional.decorator'
1011
export { default as IsTimestamp } from './is-timestamp.decorator'
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
/**
2+
* @file Decorators - IsOptional
3+
* @module sneusers/decorators/IsOptional
4+
*/
5+
6+
import { isUndefined, type ObjectUnknown } from '@flex-development/tutils'
7+
import {
8+
getMetadataStorage,
9+
ValidationTypes,
10+
type ValidationOptions
11+
} from 'class-validator'
12+
import { ValidationMetadata } from 'class-validator/esm2015/metadata/ValidationMetadata'
13+
14+
/**
15+
* Ignores all validators if a property value is `undefined`.
16+
*
17+
* @param {ValidationOptions} [options] - Validation options
18+
* @return {PropertyDecorator} Property decorator
19+
*/
20+
const IsOptional = (options: ValidationOptions = {}): PropertyDecorator => {
21+
return function (obj: object, name: string | symbol): void {
22+
getMetadataStorage().addValidationMetadata(
23+
new ValidationMetadata({
24+
constraints: [(obj: ObjectUnknown) => !isUndefined(obj[name])],
25+
propertyName: name as string,
26+
target: obj.constructor,
27+
type: ValidationTypes.CONDITIONAL_VALIDATION,
28+
validationOptions: options
29+
})
30+
)
31+
}
32+
}
33+
34+
export default IsOptional

0 commit comments

Comments
 (0)