-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(objectschemaasarray utility): converts object schema to array wi…
…th map function and rules Function that takes object type schema, optional data, pick. omit and order rules and map callback, returns an array of map callback results. Map callback maps list of object fields after filtering and ordering according to pick, omit and order rules. BREAKING CHANGE: orderFields and filter functions are deleted from the export re #57
- Loading branch information
Showing
9 changed files
with
254 additions
and
42 deletions.
There are no files selected for viewing
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
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 @@ | ||
import {CoreSchemaMetaSchema} from '../models'; | ||
|
||
export const allFields = ( | ||
{type, properties}: CoreSchemaMetaSchema, | ||
additional: Record<string, any> | ||
) => { | ||
if (type !== 'object' || !properties) { | ||
throw Error('Object schema is required'); | ||
} | ||
|
||
return Object.keys({ | ||
...properties, | ||
...additional | ||
}); | ||
}; |
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,14 @@ | ||
import {filterFields} from './filter-fields'; | ||
import {orderFields} from './order-fields'; | ||
|
||
export const filterAndOrderFields = ( | ||
fields: string[], | ||
pick?: string[], | ||
omit?: string[], | ||
order?: string[] | ||
) => { | ||
return orderFields( | ||
filterFields(fields, pick, omit), | ||
order && order.length > 0 ? order : pick ?? [] | ||
); | ||
}; |
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 @@ | ||
export function filterFields( | ||
fields: string[], | ||
toPick?: string[], | ||
toOmit?: string[] | ||
): string[] { | ||
if (toPick) { | ||
return fields.filter(prop => toPick.includes(prop)); | ||
} | ||
|
||
if (toOmit) { | ||
return fields.filter(prop => !toOmit.includes(prop)); | ||
} | ||
|
||
return fields; | ||
} |
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,45 @@ | ||
import {CoreSchemaMetaSchema} from '../models'; | ||
|
||
import {allFields} from './all-fields'; | ||
import {filterAndOrderFields} from './filter-and-order-fields'; | ||
|
||
type Rules = { | ||
pick?: string[]; | ||
omit?: string[]; | ||
order?: string[]; | ||
}; | ||
|
||
export type ObjectSchemaAsArrayMapResult = { | ||
field: string; | ||
originalSchema: CoreSchemaMetaSchema | undefined; | ||
}; | ||
|
||
export const objectSchemaAsArrayMapFn = ( | ||
field: string, | ||
schema: CoreSchemaMetaSchema | ||
): ObjectSchemaAsArrayMapResult => ({ | ||
field, | ||
originalSchema: | ||
schema.properties![field] ?? | ||
(typeof schema.additionalProperties === 'object' | ||
? schema.additionalProperties | ||
: undefined) | ||
}); | ||
|
||
export const objectSchemaAsArray = <T>( | ||
schema: CoreSchemaMetaSchema, | ||
data: Record<string, any>, | ||
{pick, omit, order}: Rules = {}, | ||
mapFunction: (field: string, schema: CoreSchemaMetaSchema) => T | ||
) => { | ||
if (schema.type !== 'object' || !schema.properties) { | ||
throw Error('Object schema is required'); | ||
} | ||
|
||
return filterAndOrderFields( | ||
allFields(schema, schema.additionalProperties ? data : {}), | ||
pick, | ||
omit, | ||
order | ||
).map(field => mapFunction(field, schema)); | ||
}; |
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 @@ | ||
export function orderFields(source: string[], rules?: string[]): string[] { | ||
if (!rules || !rules.length) { | ||
return source; | ||
} | ||
const orderedByRules = rules.filter(rule => source.includes(rule)); | ||
const orderedByDefault = source.filter(field => !rules.includes(field)); | ||
return orderedByRules.concat(orderedByDefault); | ||
} |
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,141 @@ | ||
import { | ||
CoreSchemaMetaSchema, | ||
objectSchemaAsArray, | ||
objectSchemaAsArrayMapFn | ||
} from '../src'; | ||
|
||
describe('Convert Object Schema to Array', () => { | ||
const schema: CoreSchemaMetaSchema = { | ||
type: 'object', | ||
properties: { | ||
a: { | ||
type: 'string', | ||
title: 'A' | ||
}, | ||
b: { | ||
type: 'number', | ||
title: 'B' | ||
}, | ||
c: { | ||
type: 'boolean', | ||
title: 'C', | ||
maxLength: 10 | ||
}, | ||
d: { | ||
type: 'array', | ||
title: 'D', | ||
items: { | ||
type: 'string' | ||
} | ||
} | ||
} | ||
}; | ||
|
||
const expectedData = Object.keys(schema.properties!).map(field => ({ | ||
field, | ||
originalSchema: schema.properties![field] | ||
})); | ||
|
||
it('should throw if schema type is not object', () => { | ||
expect(() => | ||
objectSchemaAsArray({type: 'array'}, {}, {}, () => null) | ||
).toThrow(); | ||
}); | ||
|
||
it('should do basic conversion', () => { | ||
expect( | ||
objectSchemaAsArray(schema, {}, {}, objectSchemaAsArrayMapFn) | ||
).toEqual(expectedData); | ||
}); | ||
|
||
describe('with additional properties', () => { | ||
it('should use data fields, if `additionalProperties` is true', () => { | ||
expect( | ||
objectSchemaAsArray( | ||
{...schema, additionalProperties: true}, | ||
{e: 'e'}, | ||
{}, | ||
objectSchemaAsArrayMapFn | ||
) | ||
).toEqual([...expectedData, {field: 'e'}]); | ||
}); | ||
|
||
it('should use data fields, if `additionalProperties` is schema', () => { | ||
expect( | ||
objectSchemaAsArray( | ||
{...schema, additionalProperties: {type: 'string'}}, | ||
{e: 'e'}, | ||
{}, | ||
objectSchemaAsArrayMapFn | ||
) | ||
).toEqual([ | ||
...expectedData, | ||
{field: 'e', originalSchema: {type: 'string'}} | ||
]); | ||
}); | ||
}); | ||
|
||
describe('with rules', () => { | ||
it('should pick fields', () => { | ||
expect( | ||
objectSchemaAsArray( | ||
{...schema, additionalProperties: true}, | ||
{e: 'e'}, | ||
{pick: ['a', 'b', 'c', 'e']}, | ||
objectSchemaAsArrayMapFn | ||
) | ||
).toEqual([ | ||
...expectedData.filter(({field}) => field !== 'd'), | ||
{field: 'e'} | ||
]); | ||
}); | ||
|
||
it('should omit fields', () => { | ||
expect( | ||
objectSchemaAsArray( | ||
{...schema, additionalProperties: true}, | ||
{e: 'e'}, | ||
{omit: ['d']}, | ||
objectSchemaAsArrayMapFn | ||
) | ||
).toEqual([ | ||
...expectedData.filter(({field}) => field !== 'd'), | ||
{field: 'e'} | ||
]); | ||
}); | ||
|
||
it('should order pick result', () => { | ||
expect( | ||
objectSchemaAsArray( | ||
{...schema, additionalProperties: true}, | ||
{e: 'e'}, | ||
{pick: ['a', 'b', 'c', 'e'], order: ['e', 'a']}, | ||
objectSchemaAsArrayMapFn | ||
) | ||
).toEqual([ | ||
{field: 'e'}, | ||
expectedData.find(({field}) => field === 'a'), | ||
...expectedData.filter( | ||
({field}) => field !== 'd' && field !== 'a' | ||
) | ||
]); | ||
}); | ||
|
||
it('should order omit result', () => { | ||
expect( | ||
objectSchemaAsArray( | ||
{...schema, additionalProperties: true}, | ||
{e: 'e'}, | ||
{omit: ['d'], order: ['e', 'a']}, | ||
objectSchemaAsArrayMapFn | ||
) | ||
).toEqual([ | ||
{field: 'e'}, | ||
expectedData.find(({field}) => field === 'a'), | ||
...expectedData.filter( | ||
({field}) => field !== 'd' && field !== 'a' | ||
) | ||
]); | ||
}); | ||
}); | ||
}); |