Last active
December 9, 2019 19:07
-
-
Save reidev275/e1e3519e67ff29664712da9cbe96b459 to your computer and use it in GitHub Desktop.
A dsl for filtering resources. Useful as a way to serialize and transfer filters
This file contains hidden or 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
import { Filter } from "./filterDsl" | |
// a sample data model | |
interface JobPosting { | |
manager: string; | |
position: string; | |
} | |
//a filter of the data model | |
const query: Filter<JobPosting> = and( | |
equals("position", "Manager"), | |
oneOf("manager", "LIMOGES", "COLPACK") | |
); | |
//underlying data representation | |
console.log(query) | |
//{ kind: 'And', | |
// a: { kind: 'Equals', field: 'position', val: 'Manager' }, | |
// b: | |
// { kind: 'Or', | |
// a: { kind: 'Equals', field: 'manager', val: 'LIMOGES' }, | |
// b: { kind: 'Equals', field: 'manager', val: 'COLPACK' } } } | |
//sql created by interpreting the data model | |
console.log(interpret(query)) | |
//([position] = 'Manager' and ([manager] = 'LIMOGES' or [manager] = 'COLPACK')) |
This file contains hidden or 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
export type Filter<A> = | |
| { kind: "Equals"; field: keyof A; val: any } | |
| { kind: "Greater"; field: keyof A; val: any } | |
| { kind: "Less"; field: keyof A; val: any } | |
| { kind: "And"; a: Filter<A>; b: Filter<A> } | |
| { kind: "Or"; a: Filter<A>; b: Filter<A> }; | |
//core | |
export const equals = <A>(field: keyof A, val: any): Filter<A> => ({ | |
kind: "Equals", | |
field, | |
val | |
}); | |
export const greater = <A>(field: keyof A, val: any): Filter<A> => ({ | |
kind: "Greater", | |
field, | |
val | |
}); | |
export const less = <A>(field: keyof A, val: any): Filter<A> => ({ | |
kind: "Less", | |
field, | |
val | |
}); | |
export const and = <A>(a: Filter<A>, b: Filter<A>): Filter<A> => ({ | |
kind: "And", | |
a, | |
b | |
}); | |
export const or = <A>(a: Filter<A>, b: Filter<A>): Filter<A> => ({ | |
kind: "Or", | |
a, | |
b | |
}); | |
/* | |
* Derived operations | |
* These combine core language features to extend the language | |
*/ | |
//greater than or equal | |
export const gte = <A>(field: keyof A, val: any): Filter<A> => | |
or(greater(field, val), equals(field, val)); | |
//less than or equal | |
export const lte = <A>(field: keyof A, val: any): Filter<A> => | |
or(less(field, val), equals(field, val)); | |
//combine 1 to many filters returning true if all are true (and) | |
export const all = <A>(...dsl: Filter<A>[]): Filter<A> => | |
dsl.reduce((p, c) => and(p, c)); | |
//combine 1 to many filters returning true if any are true (or) | |
export const any = <A>(...dsl: Filter<A>[]): Filter<A> => | |
dsl.reduce((p, c) => or(p, c)); | |
//essentially sql's in operator. Given a field and a collection of values | |
//this returns true if any are true. | |
export const oneOf = <A>(field: keyof A, ...vals: any[]): Filter<A> => | |
any(...vals.map(x => equals(field, x))); |
This file contains hidden or 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
interpret { Filter } from "./filterDsl" | |
const interpret = <A>(dsl: Filter<A>): string => { | |
switch (dsl.kind) { | |
case "Equals": | |
return `[${dsl.field}] = '${dsl.val}'`; | |
case "Greater": | |
return `[${dsl.field}] > '${dsl.val}'`; | |
case "Less": | |
return `[${dsl.field}] < '${dsl.val}'`; | |
case "And": | |
return `(${interpret(dsl.a)} and ${interpret(dsl.b)})`; | |
case "Or": | |
return `(${interpret(dsl.a)} or ${interpret(dsl.b)})`; | |
} | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment