packages feed

json-spec-elm 0.3.0.0 → 0.3.0.1

raw patch · 2 files changed

+142/−31 lines, 2 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

json-spec-elm.cabal view
@@ -1,6 +1,6 @@ cabal-version:       3.0 name:                json-spec-elm-version:             0.3.0.0+version:             0.3.0.1 synopsis:            Elm code generate for `json-spec`. description:                               Produce elm types, encoders, and decoders from a
src/Data/JsonSpec/Elm.hs view
@@ -12,6 +12,87 @@ {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} +{-|+  This module provide a way to generate Elm types, encoders, and+  decoders for [json-spec](https://hackage.haskell.org/package/json-spec)+  [Specification](https://hackage.haskell.org/package/json-spec/docs/Data-JsonSpec.html#t:Specification)s++  Generally you will probably want `elmDefs`, but sometimes you might+  want to directly use the methods of `HasType`.++  Since not every part of a 'Specification' may have a name, we can+  generate encoders and decoders for anonymous Elm types like records,+  as well as named Elm types and type aliases. This package figures out+  how to name things given the following rules:++  * If a name appears in a 'JsonLet' binding, then it gets a name in Elm as a+    type or type alias.++  * If a second 'JsonLet' binding, with exactly one definition, of the+    form @JsonLet '[ '(name, def) ] (JsonRef name)@ appears as the RHS of+    a 'JsonLet'binding, then that is interpreted as a constructor name,+    and the generated Elm definition will be a regular type instead of a+    type alias. See 'Named' for an easy shorthand way to spell @JsonLet '[+    '(name, def) ] (JsonRef name)@++  * For any 'Named' leaf of a tree of 'JsonEither's, the name is interpreted as+    a data constructor name, otherwise a data constructor name is+    auto-generated.++    == Examples:++    === Type alias++    The specification++    > Named "MyType" JsonString++    will produce the Elm type++    > type alias MyType = String++    === Type with a constructor++    The specification++    > Named "MyType" (Named "MyDataConstructor" JsonString)++    will produce the Elm type++    > type MyType = MyDataConstructor String++    === Sum Type++    Note that the /root/ of a tree of 'JsonEither's /must/ be named, because+    Elm has no way to represent anonymous sum types.++    The specification++    > Named "MySumType"+    >   ( JsonEither+    >       (Named "AnInt" JsonInt)+    >       ( JsonEither+    >           JsonFloat -- note the omitted name+    >           ( Named "AString" JsonString) +    >       )+    >   )++    will produce the Elm type++    > type MySumType+    >   = AnInt Int+    >   | MySumType_2 Float -- auto-generated constructor name.+    >   | AString String++    == Producing actual Elm code+    +    This package gets you as far as having a collection of+    'Definition's in hand, which come from the 'elm-syntax'+    package. You will need to use the pretty printing+    features of that package to actually produce code. See+    https://hackage.haskell.org/package/elm-syntax/docs/Language-Elm-Pretty.html,+    or you can look at the source code for the tests in this package.+-} module Data.JsonSpec.Elm (   elmDefs,   Definitions,@@ -51,6 +132,12 @@ import qualified Language.Elm.Type as Type  +{-|+  Generate Elm type, encoder, and decoder 'Definition's for all /named/+  types in a 'Specification'. Note that this will not produce any types,+  decoders, or encoders for anonymous parts of the 'Specification',+  since we wouldn't know what to names to give those things in Elm.+-} elmDefs   :: forall spec. (HasType spec)   => Proxy (spec :: Specification)@@ -92,9 +179,31 @@         ) : more  +{-|+  Translates 'Specification's into "anonymous" Elm types (where+  "anonymous" really means the RHS of a definition, which could be truly+  anonymous but might in fact be a reference to something previously named+  'Definition').+-} class HasType (spec :: Specification) where++  {-|+    Produce the anonymous Elm type for the spec, collecting any necessary+    'Definition's along the way.+  -}   typeOf :: forall v. Definitions (Type v)++  {-|+    Produce the Elm Decode for the spec, collecting any necessary+    'Definition's along the way+  -}   decoderOf :: Definitions (Expression Void)+++  {-|+    Produce the Elm Encoder for the spec, collecting any necessary+    'Definition's along the way.+  -}   encoderOf :: Definitions (Expression Void) instance HasType JsonString where   typeOf = pure "String.String"@@ -231,36 +340,7 @@       defs @def       encoderOf @(JsonLet more spec) instance {- HasType (JsonEither left right) -}-    ( TypeError-        ( Lits.Text "Elm doesn't support anonymous sum types, so if you "-          :<>: Lits.Text "want to use (possibly nested) `JsonEither` "-          :<>: Lits.Text "you must give it a name using `JsonLet`, e.g:"-          :$$: Lits.Text ""-          :$$: Lits.Text "> JsonLet"-          :$$: Lits.Text ">   '[ '( \"MySum\""-          :$$: Lits.Text ">       , JsonEither"-          :$$: Lits.Text ">           ( JsonEither"-          :$$: Lits.Text ">               JsonInt"-          :$$: Lits.Text ">               JsonString"-          :$$: Lits.Text ">           )"-          :$$: Lits.Text ">           ( JsonEither"-          :$$: Lits.Text ">               JsonFloat"-          :$$: Lits.Text ">               JsonBool"-          :$$: Lits.Text ">           )"-          :$$: Lits.Text ">       )"-          :$$: Lits.Text ">    ]"-          :$$: Lits.Text ">    (JsonRef \"MySum\")"-          :$$: Lits.Text ""-          :$$: Lits.Text "This will produce the Elm type"-          :$$: Lits.Text ""-          :$$: Lits.Text "> type MySum"-          :$$: Lits.Text ">   = MySum_1 Int"-          :$$: Lits.Text ">   | MySum_2 String"-          :$$: Lits.Text ">   | MySum_3 Float"-          :$$: Lits.Text ">   | MySum_4 Bool"-          :$$: Lits.Text ""-        )-    )+    (TypeError AnonSumTypeError)   =>     HasType (JsonEither left right)   where@@ -574,5 +654,36 @@   making sure sum type data constructors have meaningful names. -} type Named name def = JsonLet '[ '(name, def) ] (JsonRef name)+++type AnonSumTypeError =+  ( Lits.Text "Elm doesn't support anonymous sum types, so if you "+    :<>: Lits.Text "want to use (possibly nested) `JsonEither` "+    :<>: Lits.Text "you must give it a name using `JsonLet`, e.g:"+    :$$: Lits.Text ""+    :$$: Lits.Text "> JsonLet"+    :$$: Lits.Text ">   '[ '( \"MySum\""+    :$$: Lits.Text ">       , JsonEither"+    :$$: Lits.Text ">           ( JsonEither"+    :$$: Lits.Text ">               JsonInt"+    :$$: Lits.Text ">               JsonString"+    :$$: Lits.Text ">           )"+    :$$: Lits.Text ">           ( JsonEither"+    :$$: Lits.Text ">               JsonFloat"+    :$$: Lits.Text ">               JsonBool"+    :$$: Lits.Text ">           )"+    :$$: Lits.Text ">       )"+    :$$: Lits.Text ">    ]"+    :$$: Lits.Text ">    (JsonRef \"MySum\")"+    :$$: Lits.Text ""+    :$$: Lits.Text "This will produce the Elm type"+    :$$: Lits.Text ""+    :$$: Lits.Text "> type MySum"+    :$$: Lits.Text ">   = MySum_1 Int"+    :$$: Lits.Text ">   | MySum_2 String"+    :$$: Lits.Text ">   | MySum_3 Float"+    :$$: Lits.Text ">   | MySum_4 Bool"+    :$$: Lits.Text ""+  )