Skip to content

Commit

Permalink
add getRaw method to ObjectType
Browse files Browse the repository at this point in the history
  • Loading branch information
pgayvallet committed May 26, 2020
1 parent 84993c6 commit 442b6d7
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 4 deletions.
65 changes: 65 additions & 0 deletions packages/kbn-config-schema/src/types/object_type.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,3 +374,68 @@ test('handles optional properties', () => {

expect(foo).toBeDefined();
});

describe('#getRaw', () => {
it('returns a copy of the initial properties of the ObjectType', () => {
const props = {
string: schema.string(),
number: schema.number(),
};

const type = schema.object(props);

expect(type.getRaw()).toStrictEqual(props);
});

it('returns a different copy each time', () => {
const type = schema.object({
string: schema.string(),
number: schema.number(),
});

const props1 = type.getRaw();
const props2 = type.getRaw();

expect(props1).not.toBe(props2);
});

it('allows to extend an existing schema by adding new properties', () => {
const origin = schema.object({
initial: schema.string(),
});

const extended = schema.object({
...origin.getRaw(),
added: schema.number(),
});

expect(() => {
extended.validate({ initial: 'foo' });
}).toThrowErrorMatchingInlineSnapshot(
`"[added]: expected value of type [number] but got [undefined]"`
);

expect(() => {
extended.validate({ initial: 'foo', added: 42 });
}).not.toThrowError();
});

it('allows to extend an existing schema by removing properties', () => {
const origin = schema.object({
string: schema.string(),
number: schema.number(),
});

const { number, ...rest } = origin.getRaw();

const extended = schema.object({ ...rest });

expect(() => {
extended.validate({ string: 'foo', number: 12 });
}).toThrowErrorMatchingInlineSnapshot(`"[number]: definition for this key is missing"`);

expect(() => {
extended.validate({ string: 'foo' });
}).not.toThrowError();
});
});
31 changes: 27 additions & 4 deletions packages/kbn-config-schema/src/types/object_type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,8 @@ export type ObjectTypeOptions<P extends Props = any> = TypeOptions<ObjectResultT
UnknownOptions;

export class ObjectType<P extends Props = any> extends Type<ObjectResultType<P>> {
private props: Record<string, AnySchema>;
private props: P;
private propSchemas: Record<string, AnySchema>;

constructor(props: P, { unknowns = 'forbid', ...typeOptions }: ObjectTypeOptions<P> = {}) {
const schemaKeys = {} as Record<string, AnySchema>;
Expand All @@ -77,7 +78,29 @@ export class ObjectType<P extends Props = any> extends Type<ObjectResultType<P>>
.options({ stripUnknown: { objects: unknowns === 'ignore' } });

super(schema, typeOptions);
this.props = schemaKeys;

this.props = props;
this.propSchemas = schemaKeys;
}

/**
* Return a copy of the raw properties used to create this `ObjectType` that can be used to
* create a new schema.
*
* @example
* ```ts
* const origin = schema.object({
* initial: schema.string(),
* });
*
* const extended = schema.object({
* ...origin.getRaw(),
* added: schema.number(),
* });
* ```
*/
public getRaw(): P {
return { ...this.props };
}

protected handleError(type: string, { reason, value }: Record<string, any>) {
Expand All @@ -95,10 +118,10 @@ export class ObjectType<P extends Props = any> extends Type<ObjectResultType<P>>
}

validateKey(key: string, value: any) {
if (!this.props[key]) {
if (!this.propSchemas[key]) {
throw new Error(`${key} is not a valid part of this schema`);
}
const { value: validatedValue, error } = this.props[key].validate(value);
const { value: validatedValue, error } = this.propSchemas[key].validate(value);
if (error) {
throw new ValidationError(error as any, key);
}
Expand Down

0 comments on commit 442b6d7

Please sign in to comment.