Last active
November 20, 2017 15:45
-
-
Save hoodunit/c1b1e9bd02b851135fa2668b5a6db066 to your computer and use it in GitHub Desktop.
PureScript: representing JSON values with many nested optional fields
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
-- PureScript representation for the JSON object | |
-- accepted by an API. | |
newtype Job = Job | |
{ apiVersion :: (NullOrUndefined String) | |
, kind :: (NullOrUndefined String) | |
, metadata :: (NullOrUndefined MetaV1.ObjectMeta) | |
, spec :: (NullOrUndefined JobSpec) | |
, status :: (NullOrUndefined JobStatus) } | |
derive instance newtypeJob :: Newtype Job _ | |
derive instance genericJob :: Generic Job _ | |
instance showJob :: Show Job where show = genericShow | |
instance decodeJob :: Decode Job | |
where decode = genericDecode jsonOptions | |
instance encodeJob :: Encode Job | |
where encode = genericEncode jsonOptions | |
jsonOptions :: Options | |
jsonOptions = defaultOptions { unwrapSingleConstructors = true } | |
-- Type class for creating an empty value so you can only | |
-- specify the fields you want. | |
-- Making it a type class allows you to use the same name | |
-- for different types of objects (and makes it less likely | |
-- that names collide). | |
instance hasNewJob :: HasNew Job where | |
new = Job | |
{ apiVersion: NullOrUndefined Nothing | |
, kind: NullOrUndefined Nothing | |
, metadata: NullOrUndefined Nothing | |
, spec: NullOrUndefined Nothing | |
, status: NullOrUndefined Nothing } | |
class HasNew a where | |
new :: a | |
-- Helper lenses give a nicer syntax for setting and updating | |
-- fields, especially when the fields are deeply nested. | |
-- The lenses are polymorphic so you can use the same lens | |
-- on different types of objects as long as the objects are | |
-- a newtype with a field of some specific name containing a | |
-- newtype. | |
apiVersion :: forall s a r r'. Newtype s { apiVersion :: r | r' } => Newtype r a => Lens' s a | |
apiVersion = _Newtype <<< prop (SProxy :: SProxy "apiVersion") <<< _Newtype | |
kind :: forall s a r r'. Newtype s { kind :: r | r' } => Newtype r a => Lens' s a | |
kind = _Newtype <<< prop (SProxy :: SProxy "kind") <<< _Newtype | |
-- Example usage: | |
-- Create a Job here with all empty values, then update it | |
-- using lenses. The lens syntax is convenient and powerful, | |
-- although the weird operators will be a barrier to getting | |
-- started. | |
testJob :: Job | |
testJob = | |
(new :: Job) | |
# apiVersion ?~ "batch/v1" | |
# kind ?~ "Job" | |
# metadata ?~ (new | |
# labels ?~ (StrMap.fromFoldable | |
[ Tuple "service" "search-test" ]) | |
# name ?~ "search-test" | |
# namespace ?~ "default") | |
# spec ?~ (new | |
# activeDeadlineSeconds ?~ 600 | |
# completions ?~ 1 | |
# template ?~ (new | |
# metadata ?~ (new | |
# name ?~ "search-test" | |
# labels ?~ StrMap.fromFoldable | |
[ Tuple "service" "search-test" ]) | |
# spec ?~ (new | |
# containers ?~ | |
[ new | |
# command ?~ ["/bin/bash", "-c", "npm test || true"] | |
# image ?~ "search-test:test" | |
# imagePullPolicy ?~ "Never" | |
# name ?~ "app" | |
# env ?~ | |
[ new # name ?~ "ES_HOSTS" # value ?~ "http://elastic:changeme@localhost:9200" | |
, new # name ?~ "ES_CURRENT_INDEX" # value ?~ "testing" | |
, new # name ?~ "ES_WEB_INDEX_ALIAS" # value ?~ "testing_web" | |
, new # name ?~ "ES_WORKER_INDEX_ALIAS" # value ?~ "testing_worker" | |
, new # name ?~ "LOG_LEVEL" # value ?~ "error" | |
, new # name ?~ "NEW_RELIC_ENABLED" # value ?~ "false" | |
, new # name ?~ "APP_ENV" # value ?~ "testing" | |
, new # name ?~ "NODE_ENV" # value ?~ "production" ] | |
, new | |
# args ?~ | |
[ "-e", "bootstrap.memory_lock=true" | |
, "-e", "discovery.type=single-node" | |
, "-e", "xpack.security.enabled=false" ] | |
# command ?~ ["/bin/bash", "bin/es-docker"] | |
# image ?~ "docker.elastic.co/elasticsearch/elasticsearch:5.4.0" | |
# imagePullPolicy ?~ "IfNotPresent" | |
# name ?~ "es" | |
# env ?~ [ new # name ?~ "ES_JAVA_OPTS" # value ?~ "-Xms512m -Xmx512m" ] | |
# ports ?~ [ new # containerPort ?~ 9200 # hostPort ?~ 9200 ]] | |
# restartPolicy ?~ "Never" | |
# terminationGracePeriodSeconds ?~ 30 | |
# dnsPolicy ?~ "ClusterFirst" | |
# schedulerName ?~ "default-scheduler"))) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment