Last active
August 29, 2019 16:05
-
-
Save mrmurphy/76862048b17572753b80c5ebed62704b to your computer and use it in GitHub Desktop.
Using ADTs to form invariants around application logic.
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
// These types enhance safety around binary data that we want to synthesize onto | |
// a record, but store in S3 instead of in Postgres. If the encoder for the | |
// wrapping type requires that a field has a type of `S3Data.Outgoing.t`, then | |
// the type system will ensure that the data has been loaded up from S3 before | |
// it gets sent back to the user. In the same way, if the wrapping type uses | |
// `Incoming.t` at the API layer, and just `t` at the database layer, then the | |
// type system ensures that some action has been taken to save the binary to S3 | |
// before writing to the database. | |
module Saved = { | |
type t = | |
| Saved | |
| NotUsed; | |
let encodeForDb = t => { | |
switch (t) { | |
| NotUsed => Obj.magic(Js.undefined) | |
| _ => Obj.magic(BufferBuddy.fromString("Y")) | |
}; | |
}; | |
let decodeFromDb = json => { | |
switch (Js.Json.classify(json)) { | |
| Js.Json.JSONObject(_) => Saved | |
| _ => NotUsed | |
}; | |
}; | |
}; | |
module Incoming = { | |
type t = | |
| Unsaved(Node.Buffer.t) | |
| NotUsed; | |
let decodeFromApi = json => { | |
open Json.Decode; | |
let asB64String = optional(string, json); | |
switch (asB64String) { | |
| Some(str) => Unsaved(BufferBuddy.fromStringWithEncoding(str, `base64)) | |
| None => NotUsed | |
}; | |
}; | |
}; | |
module Loaded = { | |
type t = | |
| Loaded(Node.Buffer.t) | |
| NotUsed; | |
let getWithDefault = (t, a) => | |
switch (t) { | |
| Loaded(b) => b | |
| NotUsed => a | |
}; | |
let encodeForApi = t => { | |
switch (t) { | |
| Loaded(buf) => | |
buf->BufferBuddy.toStringWithEncoding("base64")->Json.Encode.string | |
| NotUsed => Js.Json.null | |
}; | |
}; | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment