Skip to content

Instantly share code, notes, and snippets.

@bloodyowl
Created November 11, 2020 22:20
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bloodyowl/448e04f473bee1c5fcdb6f080e276add to your computer and use it in GitHub Desktop.
Save bloodyowl/448e04f473bee1c5fcdb6f080e276add to your computer and use it in GitHub Desktop.
open Belt
type serializedValue
external asSerializedValue: 'a => serializedValue = "%identity"
type serializedComparator
external asSerializedComparator: 'a => serializedComparator = "%identity"
type serialized
external asSerialized: 'a => serialized = "%identity"
type value = [#objectId(string) | #bool(bool) | #int(int) | #float(float) | #string(string) | #null]
let objectId = string => #objectId(string)
let bool = bool => #bool(bool)
let int = int => #int(int)
let float = float => #float(float)
let string = string => #string(string)
let null = #null
type bsonType = [
| #double
| #string
| #object
| #array
| #binData
| #objectId
| #bool
| #date
| #null
| #regex
| #javascript
| #int
| #timestamp
| #long
| #decimal
]
let serializeValue = (. value: value): serializedValue =>
switch value {
| #objectId(id) => asSerializedValue({"$oid": id})
| #bool(bool) => asSerializedValue(bool)
| #int(int) => asSerializedValue(int)
| #float(float) => asSerializedValue(float)
| #string(string) => asSerializedValue(string)
| #null => asSerializedValue(Js.Null.empty)
}
type regex = {regex: string, options: string}
type rec comparator = [
| #isEqual(value)
| #isNotEqual(value)
| #isNotIn(array<value>)
| #isIn(array<value>)
| #isLowerThan(value)
| #isLowerThanOrEqual(value)
| #isGreaterThan(value)
| #isGreaterThanOrEqual(value)
| #matchesRegex(regex)
| #exists(bool)
| #elemMatch(t)
| #isOfType(bsonType)
]
and t = [#query(array<(string, comparator)>) | #oneOf(array<t>) | #allOf(array<t>)]
let isEqual = value => #isEqual(value)
let isNotEqual = value => #isNotEqual(value)
let isIn = value => #isIn(value)
let isNotIn = value => #isNotIn(value)
let isLowerThan = value => #isLowerThan(value)
let isLowerThanOrEqual = value => #isLowerThanOrEqual(value)
let isGreaterThan = value => #isGreaterThan(value)
let isGreaterThanOrEqual = value => #isGreaterThanOrEqual(value)
let matchesRegex = value => #matchesRegex(value)
let exists = bool => #exists(bool)
let elemMatch = value => #elemMatch(value)
let isOfType = value => #isOfType(value)
let query = query => #query(query)
let oneOf = queries => #oneOf(queries)
let allOf = queries => #allOf(queries)
let allOfOption = queries => {
switch queries->Array.keepMap(x => x) {
| [] => None
| [query] => Some(query)
| queries => Some(#allOf(queries))
}
}
let rec serializeComparator = (. comparator: comparator): serializedComparator =>
switch comparator {
| #isEqual(value) => asSerializedComparator(serializeValue(. value))
| #isNotEqual(value) => asSerializedComparator({"$ne": serializeValue(. value)})
| #isIn(value) => asSerializedComparator({"$in": value->Array.mapU(serializeValue)})
| #isNotIn(value) => asSerializedComparator({"$nin": value->Array.mapU(serializeValue)})
| #isLowerThan(value) => asSerializedComparator({"$lt": serializeValue(. value)})
| #isLowerThanOrEqual(value) => asSerializedComparator({"$lte": serializeValue(. value)})
| #isGreaterThan(value) => asSerializedComparator({"$gt": serializeValue(. value)})
| #isGreaterThanOrEqual(value) => asSerializedComparator({"$gte": serializeValue(. value)})
| #matchesRegex({regex, options}) =>
asSerializedComparator({"$regex": regex, "$options": options})
| #exists(value) => asSerializedComparator({"$exists": value})
| #elemMatch(value) => asSerializedComparator({"$elemMatch": serialize(value)})
| #isOfType(value) => asSerializedComparator({"$type": value})
}
and makeDict = value => {
open Js.Dict
map(serializeComparator, fromArray(value))
}
and serialize = (value: t) => {
switch value {
| #query(value) => asSerialized(makeDict(value))
| #oneOf(value) =>
asSerialized({
"$or": value->Array.map(serialize),
})
| #allOf(value) =>
asSerialized({
"$and": value->Array.map(serialize),
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment