From 9e0c42f930abd6f87e31298c36730336bba7030a Mon Sep 17 00:00:00 2001 From: Todd Kennedy Date: Fri, 24 May 2019 11:25:14 -0700 Subject: [PATCH] [feat] add reach-like functionality to object In #36804 we need to validate a `Partial` object which may or may not have all the required keys attached to it. This is the type of use-case for `Joi.reach`, so we should expose a reach-like method on the object validation class so that you can return the validator for a specific key on an object. --- .../src/types/object_type.test.ts | 16 ++++++++++++++++ .../kbn-config-schema/src/types/object_type.ts | 8 ++++++++ 2 files changed, 24 insertions(+) diff --git a/packages/kbn-config-schema/src/types/object_type.test.ts b/packages/kbn-config-schema/src/types/object_type.test.ts index e0eaabadb8ef5..e78c930487908 100644 --- a/packages/kbn-config-schema/src/types/object_type.test.ts +++ b/packages/kbn-config-schema/src/types/object_type.test.ts @@ -199,3 +199,19 @@ test('includes namespace in failure when wrong value type', () => { expect(() => type.validate(value, {}, 'foo-namespace')).toThrowErrorMatchingSnapshot(); }); + +test('reach returns a valid schema component', () => { + const type = schema.object({ + foo: schema.boolean(), + }); + + const fooSchema = type.reach('foo'); + const value = false; + expect(() => fooSchema.validate(value)).toBeTruthy(); + + try { + type.reach('bar'); + } catch (err) { + expect(err.message).toBe('bar is not a valid part of this schema'); + } +}); diff --git a/packages/kbn-config-schema/src/types/object_type.ts b/packages/kbn-config-schema/src/types/object_type.ts index e61fcd90ef016..bd7d18434bacf 100644 --- a/packages/kbn-config-schema/src/types/object_type.ts +++ b/packages/kbn-config-schema/src/types/object_type.ts @@ -31,6 +31,8 @@ export type TypeOf> = RT['type']; export type ObjectResultType

= Readonly<{ [K in keyof P]: TypeOf }>; export class ObjectType

extends Type> { + private props: Record; + constructor(props: P, options: TypeOptions<{ [K in keyof P]: TypeOf }> = {}) { const schemaKeys = {} as Record; for (const [key, value] of Object.entries(props)) { @@ -44,6 +46,7 @@ export class ObjectType

extends Type> .default(); super(schema, options); + this.props = schemaKeys; } protected handleError(type: string, { reason, value }: Record) { @@ -57,4 +60,9 @@ export class ObjectType

extends Type> return reason[0]; } } + + reach(key: string) { + if (!this.props[key]) throw new Error(`${key} is not a valid part of this schema`); + return this.props[key]; + } }