on develop help sign in
Adding request/media bodies to method schema
commit6bf9bec8371f2a33373dc00bef1764295abc932d authorBrendan Hay <brendan.g.hay@gmail.com> dateThu 1 Oct 2015, 10:16 (11 years ago) parent4babe4f
16 files changed+143−343
gen/LICENSE−6 gen/src/Gen/AST.hs+3−161 gen/src/Gen/AST/Flatten.hs+47−32 gen/src/Gen/AST/Render.hs+2−11 gen/src/Gen/AST/Solve.hs+7−5 gen/src/Gen/IO.hs−4 gen/src/Gen/Syntax.hs+11−1 gen/src/Gen/Text.hs+3−1 gen/src/Gen/Tree.hs−2 gen/src/Gen/Types.hs+21−32 gen/src/Gen/Types/Data.hs+1−23 gen/src/Gen/Types/Id.hs+8−18 gen/src/Gen/Types/NS.hs+2−9 gen/src/Gen/Types/Schema.hs+38−30 gen/src/Main.hs−2 gen/static/LICENSE−6
gen/LICENSE−6
@@ -365,9 +365,3 @@ file in a relevant directory) where a recipient would be likely to look
365365for such a notice.
366366
367367You may add additional accurate notices of copyright ownership.
368−
369−Exhibit B - "Incompatible With Secondary Licenses" Notice
370−---------------------------------------------------------
371−
372− This Source Code Form is "Incompatible With Secondary Licenses", as
373− defined by the Mozilla Public License, v. 2.0.
gen/src/Gen/AST.hs+3−161
@@ -1,16 +1,3 @@
1−{-# LANGUAGE DataKinds #-}
2−{-# LANGUAGE DeriveGeneric #-}
3−{-# LANGUAGE FlexibleContexts #-}
4−{-# LANGUAGE FlexibleInstances #-}
5−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
6−{-# LANGUAGE KindSignatures #-}
7−{-# LANGUAGE LambdaCase #-}
8−{-# LANGUAGE OverloadedStrings #-}
9−{-# LANGUAGE RankNTypes #-}
10−{-# LANGUAGE RecordWildCards #-}
11−{-# LANGUAGE TemplateHaskell #-}
12−{-# LANGUAGE TupleSections #-}
13−
141-- Module : Gen.AST
152-- Copyright : (c) 2015 Brendan Hay
163-- License : Mozilla Public License, v. 2.0.
@@ -20,28 +7,13 @@
207
218module Gen.AST where
229
23−import Control.Applicative
24−import Control.Error
25−import Control.Lens hiding (lens)
2610import Control.Monad.Except
2711import Control.Monad.State.Strict
28−import Data.Char
29−import qualified Data.HashMap.Strict as Map
30−import Data.Maybe
31−import Data.Semigroup ((<>))
32−import qualified Data.Text as Text
33−import qualified Data.Text.Lazy as LText
34−import qualified Data.Text.Lazy.Builder as Build
3512import Debug.Trace
36−import Gen.AST.Flatten (flatten)
37−import Gen.AST.Render (render)
38−import Gen.AST.Solve (solve)
39−import Gen.Formatting
13+import Gen.AST.Flatten (flatten)
14+import Gen.AST.Render (render)
15+import Gen.AST.Solve (solve)
4016import Gen.Types
41−import HIndent
42−import Language.Haskell.Exts.Build (name)
43−import Language.Haskell.Exts.Pretty
44−import Prelude hiding (sum)
4517
4618runAST :: Versions -> Service (Fix Schema) -> Either Error Library
4719runAST v s = evalState (runExceptT go) (initial s)
@@ -50,133 +22,3 @@ runAST v s = evalState (runExceptT go) (initial s)
5022 gs <- flatten s
5123 (api, ds) <- render =<< solve gs
5224 pure $! Library v gs api ds
53−
54−-- flatten :: Parsed -> AST Flattened
55−-- flatten svc = do
56−-- _ <- Map.traverseWithKey typ (_svcSchemas svc)
57−-- ps <- Map.traverseWithKey (prm "") (_svcParameters svc)
58−-- a <- api ps (_svcApi svc)
59−-- ss <- uses schemas Map.keys
60−-- pure $! svc { _svcSchemas = ss, _svcParameters = Map.elems ps, _svcApi = a }
61−-- where
62−-- typ :: Id -> Fix Schema -> AST Id
63−-- typ n (Fix f) = go f >>= ins n
64−-- where
65−-- go = \case
66−-- Obj i ps -> Obj i <$> Map.traverseWithKey (prop n) ps
67−-- Arr i (Fix e) -> Arr i <$> prop n "item" (Fix (e & required .~ True))
68−
69−-- Enum i vs ds -> pure (Enum i vs ds)
70−-- Lit i x -> pure (Lit i x)
71−-- Ref i r -> pure (Ref i r)
72−-- Any i -> pure (Any i)
73−
74−-- prop :: Id -> Local -> Fix Schema -> AST Id
75−-- prop p l (Fix f) = go f >>= ins this
76−-- where
77−-- go = \case
78−-- Obj i ps -> Obj i <$> Map.traverseWithKey (prop this) ps
79−-- Arr i (Fix e) -> Arr i <$> prop this "item" (Fix (e & required .~ True))
80−
81−-- Enum i vs ds -> pure (Enum i vs ds)
82−-- Lit i x -> pure (Lit i x)
83−-- Ref i r -> pure (Ref i r)
84−-- Any i -> pure (Any i)
85−
86−-- this = mkProp p l
87−
88−-- prm :: Id -> Local -> Param (Fix Schema) -> AST (Param Id)
89−-- prm p l x = do
90−-- n <- prop p l (_prmSchema x)
91−-- pure $! x { _prmSchema = n }
92−
93−-- api :: Map Local (Param Id) -> Resource (Fix Schema) -> AST (Resource Id)
94−-- api qs = \case
95−-- Top rs -> Top <$> Map.traverseWithKey sub rs
96−-- Sub ms -> Sub <$> Map.traverseWithKey (verb "") ms
97−-- where
98−-- sub l = \case
99−-- Top rs -> Top <$> Map.traverseWithKey sub rs
100−-- Sub ms -> Sub <$> Map.traverseWithKey (verb l) ms
101−
102−-- verb p l m = do
103−-- let (_, i, _) = vname (svcAbbrev svc) (_mId m)
104−-- rs <- Map.traverseWithKey (prm i) (_mParameters m)
105−-- _ <- ins i $
106−-- Obj (Info (_mDescription m) Nothing False Nothing) (Map.map _prmSchema (rs <> qs))
107−-- pure $! m { _mParameters = rs <> qs }
108−
109−-- ins :: Id -> Schema Id -> AST Id
110−-- ins n x = do
111−-- ms <- uses schemas (Map.lookup n)
112−-- case ms of
113−-- Just y | x /= y -> throwError $
114−-- format ("Schema exists: " % stext % " - " % fid %
115−-- "\nCurrent: " % shown % "\nTried: " % shown)
116−-- (_svcCanonicalName svc) n y x
117−-- _ -> schemas %= Map.insert n x
118−
119−-- return n
120−
121−
122−-- runAST :: Parsed -> Either Error Printed
123−-- runAST svc = evalState (runExceptT go) initial
124−-- where
125−-- go = do
126−-- x <- flatten svc
127−-- reserve x
128−-- solveAll x >>= render
129−
130−-- solveAll :: Flattened -> AST Typed
131−-- solveAll svc = do
132−-- ss <- traverse solve (_svcSchemas svc)
133−-- ps <- traverse (traverse solve) (_svcParameters svc)
134−-- a <- traverse solve (_svcApi svc)
135−-- pure $! svc { _svcSchemas = ss, _svcParameters = ps, _svcApi = a }
136−
137−-- data PP
138−-- = Indent
139−-- | Print
140−-- | None
141−-- deriving (Eq)
142−
143−-- pp :: Pretty a => PP -> a -> AST Rendered
144−-- pp i x
145−-- | i == Indent = result (reformat johanTibell Nothing p)
146−-- | otherwise = pure p
147−-- where
148−-- result = hoistEither . bimap e Build.toLazyText
149−
150−-- e = flip mappend (", when formatting: " <> p) . LText.pack
151−
152−-- p = LText.dropWhile isSpace
153−-- . LText.pack
154−-- $ prettyPrintStyleMode s m x
155−
156−-- s = style
157−-- { mode = PageMode
158−-- , lineLength = 80
159−-- , ribbonsPerLine = 1.5
160−-- }
161−
162−-- m | i == Print = defaultMode
163−-- | i == Indent = defaultMode
164−-- | otherwise = defaultMode
165−-- { layout = PPNoLayout
166−-- , spacing = False
167−-- }
168−
169−-- -- FIXME: dirty hack to render smart ctor parameter comments.
170−-- comments :: Map Local Solved -> Rendered -> Rendered
171−-- comments (Map.toList -> rs) =
172−-- LText.replace " :: " "\n :: "
173−-- . LText.intercalate "\n -> "
174−-- . zipWith rel ps
175−-- . map LText.strip
176−-- . LText.splitOn "->"
177−-- where
178−-- ks = filter (parameter . _schema . snd) rs
179−-- ps = map (Just . fst) ks ++ repeat Nothing
180−
181−-- rel Nothing t = t
182−-- rel (Just l) t = t <> " -- ^ '" <> LText.fromStrict (local l) <> "'"
gen/src/Gen/AST/Flatten.hs+47−32
@@ -24,24 +24,14 @@ module Gen.AST.Flatten
2424
2525import Control.Applicative
2626import Control.Error
27−import Control.Lens hiding (lens)
27+import Control.Lens hiding (lens)
2828import Control.Monad.Except
29−import Control.Monad.State.Strict
30−import Data.Char
31−import qualified Data.HashMap.Strict as Map
29+import qualified Data.HashMap.Strict as Map
3230import Data.Maybe
33−import Data.Semigroup ((<>))
34−import qualified Data.Text as Text
35−import qualified Data.Text.Lazy as LText
36−import qualified Data.Text.Lazy.Builder as Build
37−import Debug.Trace
38−import Debug.Trace
31+import Data.Semigroup ((<>))
3932import Gen.Formatting
4033import Gen.Types
41−import HIndent
42−import Language.Haskell.Exts.Build (name)
43−import Language.Haskell.Exts.Pretty
44−import Prelude hiding (sum)
34+import Prelude hiding (sum)
4535
4636flatten :: Service (Fix Schema) -> AST (Service Global)
4737flatten s = do
@@ -91,7 +81,15 @@ schema g ml (Fix f) = go f >>= insert this
9181 Obj Nothing <$> Map.traverseWithKey (localSchema this) ps
9282
9383globalParam :: Local -> Param (Fix Schema) -> AST (Param Global)
94−globalParam = localParam ""
84+globalParam l = case l of
85+ "alt" -> overrideParam l Alt
86+ "key" -> overrideParam l Key
87+ "oauth_token" -> overrideParam l OAuthToken
88+ _ -> localParam "" l
89+
90+overrideParam :: Local -> Lit -> Param (Fix Schema) -> AST (Param Global)
91+overrideParam l v p =
92+ localParam "" l $ p { _pParam = Fix (SLit (p ^. info) v) }
9593
9694localParam :: Global -> Local -> Param (Fix Schema) -> AST (Param Global)
9795localParam g l p = do
@@ -118,27 +116,44 @@ method :: Map Local (Param Global)
118116method qs suf m@Method {..} = do
119117 ps <- Map.traverseWithKey (localParam _mId) _mParameters
120118 cn <- use sCanonicalName
119+
121120 let (_, typ, _) = mname cn suf _mId
122− params = ps <> qs
123− void $ insert typ (fresh params)
121+
122+ b <- body typ
123+
124+ let params = ps <> qs
125+ fields = b (upload (Map.map _pParam params))
126+
127+ void $ insert typ (SObj schemaInfo (Obj Nothing fields))
124128 pure $! m { _mParameters = params }
125129 where
126− fresh ps = SObj info' $ Obj Nothing (Map.map _pParam ps)
127−
128− info' = Info
129− { _iId = Nothing
130− , _iDescription = _mDescription
131− , _iDefault = Nothing
132− , _iRequired = False
133− , _iPattern = Nothing
134− , _iMinimum = Nothing
135− , _iMaximum = Nothing
136− , _iRepeated = False
137− , _iAnnotations = mempty
138− }
130+ schemaInfo = emptyInfo { _iDescription = _mDescription }
131+
132+ bodyInfo = requiredInfo { _iDescription = Just "Multipart request metadata." }
133+
134+ body p = case _mRequest of
135+ Nothing -> pure id
136+ Just x -> do
137+ let f = localise (ref x)
138+ g <- localSchema p f (Fix (SRef bodyInfo x))
139+ pure (Map.insert f g)
140+
141+ upload
142+ | _mSupportsMediaUpload = Map.insert "media" "Body"
143+ | otherwise = id
144+
145+ download = id
146+
147+ -- media
148+ -- insert 'media' property of type 'Body'
149+ -- insert 'mediaType' property of type 'MediaType'
150+
151+ -- ensure the rendering of api aliases gets request bodies
152+ -- set to 'Multipart'
153+
154+ -- error if multipart + simple is not supported.
139155
140−setRequired :: Fix Schema -> Fix Schema
141−setRequired (Fix e) = Fix (e & iRequired .~ True)
156+ -- otherwise ensure servants 'ReqBody' is set.
142157
143158insert :: Global -> Schema Global -> AST Global
144159insert g s = do
gen/src/Gen/AST/Render.hs+2−11
@@ -26,27 +26,17 @@ import Control.Applicative
2626import Control.Error
2727import Control.Lens hiding (enum, lens)
2828import Control.Monad.Except
29−import Data.CaseInsensitive (CI)
30−import qualified Data.CaseInsensitive as CI
31−import Data.Char
32−import Data.Hashable
29+import Data.Char (isSpace)
3330import qualified Data.HashMap.Strict as Map
34−import qualified Data.HashSet as Set
35−import Data.List (intersect)
3631import Data.Maybe
3732import Data.Semigroup ((<>))
38−import Data.Text (Text)
3933import qualified Data.Text as Text
4034import qualified Data.Text.Lazy as LText
4135import qualified Data.Text.Lazy.Builder as Build
42−import Data.Text.Manipulate
43−import Debug.Trace
4436import Gen.AST.Solve (getSolved)
4537import Gen.Formatting
4638import Gen.Syntax
47−import Gen.Text
4839import Gen.Types
49−import Gen.Types.Data
5040import HIndent
5141import Language.Haskell.Exts.Build (name)
5242import Language.Haskell.Exts.Pretty
@@ -190,6 +180,7 @@ pp i x
190180 , spacing = False
191181 }
192182
183+
193184-- FIXME: dirty hack to render smart ctor parameter comments.
194185comments :: Map Local Solved -> Rendered -> Rendered
195186comments (Map.toList -> rs) =
gen/src/Gen/AST/Solve.hs+7−5
@@ -38,7 +38,6 @@ import Data.Semigroup ((<>))
3838import Data.Text (Text)
3939import qualified Data.Text as Text
4040import Data.Text.Manipulate
41−import Debug.Trace
4241import Gen.Formatting
4342import Gen.Text
4443import Gen.Types
@@ -83,7 +82,7 @@ getSchema g = do
8382 Just x -> pure x
8483 Nothing -> throwError $
8584 format ("Missing Schema: " % gid % "\n" % shown)
86− g (map dname (Map.keys ss))
85+ g (map global (Map.keys ss))
8786
8887getType :: Global -> AST TType
8988getType g = loc "getType" g $ memo typed g go
@@ -118,6 +117,9 @@ getDerive g = loc "getDerive" g $ memo derived g go
118117 Bool -> enum
119118 Time -> base
120119 Date -> base
120+ Body -> base
121+ Alt -> base
122+ Key -> base
121123 -- FIXME: Add numeric cases
122124 _ -> [DNum, DIntegral, DReal] <> enum
123125
@@ -215,9 +217,6 @@ acronymPrefixes (global -> g) = map CI.mk (xs ++ map suffix ys ++ zs)
215217 -- SomeTestTType -> Som
216218 r6 = Text.take limit <$> listToMaybe (splitWords a)
217219
218−loc :: String -> Global -> a -> a
219−loc n g = id -- trace (n ++ ": " ++ Text.unpack (fromKey g))
220−
221220memo :: Lens' Memo (Map Global a)
222221 -> Global
223222 -> (Schema Global -> AST a)
@@ -230,3 +229,6 @@ memo l g f = do
230229 x <- f =<< getSchema g
231230 l %= Map.insert g x
232231 pure x
232+
233+loc :: String -> Global -> a -> a
234+loc _ _ = id -- trace (n ++ ": " ++ Text.unpack (fromKey g))
gen/src/Gen/IO.hs−4
@@ -13,11 +13,7 @@ module Gen.IO where
1313
1414import Control.Error
1515import Control.Monad.Except
16−import Control.Monad.State
1716import Data.ByteString (ByteString)
18−import qualified Data.HashMap.Strict as Map
19−import Data.Text (Text)
20−import qualified Data.Text as Text
2117import qualified Data.Text.Lazy as LText
2218import Data.Text.Lazy.Builder (toLazyText)
2319import qualified Data.Text.Lazy.IO as LText
gen/src/Gen/Syntax.hs+11−1
@@ -29,7 +29,7 @@ import Gen.Text
2929import Gen.Types
3030import Language.Haskell.Exts.Build
3131import Language.Haskell.Exts.SrcLoc
32−import Language.Haskell.Exts.Syntax hiding (Int, Lit)
32+import Language.Haskell.Exts.Syntax hiding (Alt, Int, Lit)
3333
3434urlSig :: Name -> Decl
3535urlSig n = TypeSig noLoc [n] (TyCon "BaseUrl")
@@ -331,6 +331,11 @@ externalLit = \case
331331 Int32 -> TyCon "Int32"
332332 Int64 -> TyCon "Int64"
333333
334+ Alt -> TyCon "Alt"
335+ Key -> TyCon "Key"
336+ OAuthToken -> TyCon "OAuthToken"
337+ Body -> TyCon "Body"
338+
334339internalLit :: Lit -> Type
335340internalLit = \case
336341 Text -> TyCon "Text"
@@ -346,6 +351,11 @@ internalLit = \case
346351 Int32 -> TyCon "Int32"
347352 Int64 -> TyCon "Int64"
348353
354+ Alt -> TyCon "Alt"
355+ Key -> TyCon "Key"
356+ OAuthToken -> TyCon "OAuthToken"
357+ Body -> TyCon "Body"
358+
349359mapping :: TType -> Exp -> Exp
350360mapping t e = infixE e "." (go t)
351361 where
gen/src/Gen/Text.hs+3−1
@@ -58,7 +58,7 @@ renameAbbrev = mconcat
5858 . stripSuffix " API"
5959
6060renameField :: Text -> Text
61−renameField = lowerHead . toCamel
61+renameField = lowerHead . upperAcronym . toCamel
6262
6363renameBranch :: Text -> Text
6464renameBranch t
@@ -196,6 +196,8 @@ upperAcronym x = Fold.foldl' (flip (uncurry RE.replaceAll)) x xs
196196 , ("Nat", "NAT")
197197 , ("Youtube", "YouTube")
198198 , ("Cnc", "CNC")
199+ , ("Oauth", "OAuth")
200+ , ("Ocr$", "OCR")
199201 ]
200202
201203acronyms :: [(String, String)]
gen/src/Gen/Tree.hs−2
@@ -28,8 +28,6 @@ import Control.Monad.Except
2828import Data.Aeson hiding (json)
2929import Data.Bifunctor
3030import Data.Foldable (foldr')
31−import qualified Data.HashMap.Strict as Map
32−import qualified Data.List.NonEmpty as NE
3331import Data.Monoid
3432import Data.Text (Text)
3533import qualified Data.Text as Text
gen/src/Gen/Types.hs+21−32
@@ -33,48 +33,33 @@ module Gen.Types
3333 , module Gen.Types.Data
3434 ) where
3535
36−import Control.Applicative
37−import Control.Lens hiding ((.=))
36+import Control.Lens hiding ((.=))
3837import Control.Monad.Except
3938import Control.Monad.State.Strict
40−import Data.Aeson hiding (Array, Bool, String)
41−import qualified Data.Aeson as A
42−import Data.Aeson.TH
43−import Data.CaseInsensitive (CI)
44−import qualified Data.CaseInsensitive as CI
45−import Data.Char
46−import Data.Function (on)
47−import qualified Data.HashMap.Strict as Map
48−import qualified Data.HashSet as Set
49−import Data.List (groupBy, sort, sortOn)
50−import Data.List.NonEmpty (NonEmpty (..))
51−import qualified Data.List.NonEmpty as NE
52−import Data.Maybe
39+import Data.Aeson hiding (Array, Bool, String)
40+import Data.CaseInsensitive (CI)
41+import Data.Function (on)
42+import qualified Data.HashMap.Strict as Map
43+import qualified Data.HashSet as Set
44+import Data.List (sort)
5345import Data.Ord
54−import Data.Semigroup ((<>))
55−import Data.Text (Text)
56−import qualified Data.Text as Text
57−import qualified Data.Text.Lazy as LText
58−import qualified Data.Text.Lazy.Builder as Build
59−import Data.Text.Manipulate
60−import qualified Data.Text.Read as Read
61−import qualified Filesystem.Path.CurrentOS as Path
46+import Data.Semigroup ((<>))
47+import Data.Text (Text)
48+import qualified Data.Text as Text
49+import qualified Data.Text.Lazy as LText
50+import qualified Data.Text.Lazy.Builder as Build
51+import qualified Filesystem.Path.CurrentOS as Path
6252import Formatting
63−import Gen.Orphans ()
64−import Gen.Text
65−import Gen.TH
53+import Gen.Orphans ()
6654import Gen.Types.Data
6755import Gen.Types.Help
6856import Gen.Types.Id
6957import Gen.Types.Map
7058import Gen.Types.NS
7159import Gen.Types.Schema
72−import GHC.Generics
7360import GHC.TypeLits
74−import Language.Haskell.Exts (Name)
75−import Language.Haskell.Exts.Pretty (Pretty, prettyPrint)
76−import Prelude hiding (Enum)
77−import Text.EDE (Template)
61+import Prelude hiding (Enum)
62+import Text.EDE (Template)
7863
7964type Set = Set.HashSet
8065type Error = LText.Text
@@ -280,7 +265,11 @@ data Memo = Memo
280265 }
281266
282267initial :: Service (Fix Schema) -> Memo
283−initial s = Memo s mempty mempty mempty mempty mempty mempty
268+initial s = Memo s mempty mempty core mempty mempty mempty
269+ where
270+ core = Map.fromList
271+ [ ("Body", SLit requiredInfo Body)
272+ ]
284273
285274-- reserve :: Flattened -> AST ()
286275-- reserve svc = do
gen/src/Gen/Types/Data.hs+1−23
@@ -24,42 +24,20 @@
2424
2525module Gen.Types.Data where
2626
27−import Control.Applicative
28−import Control.Lens hiding ((.=))
2927import Data.Aeson hiding (Array, Bool, String)
30−import qualified Data.Aeson as A
31−import Data.Aeson.TH
32−import Data.Char
33−import Data.Function (on)
34−import qualified Data.HashMap.Strict as Map
35−import qualified Data.HashSet as Set
36−import Data.List (groupBy, sort, sortOn)
37−import Data.List.NonEmpty (NonEmpty (..))
38−import qualified Data.List.NonEmpty as NE
28+import Data.List (sortOn)
3929import Data.Maybe
40−import Data.Ord
41−import Data.Semigroup ((<>))
4230import Data.Text (Text)
4331import qualified Data.Text as Text
4432import qualified Data.Text.Lazy as LText
45−import qualified Data.Text.Lazy.Builder as Build
4633import Data.Text.Manipulate
47−import qualified Data.Text.Read as Read
48−import qualified Filesystem.Path.CurrentOS as Path
49−import Formatting
5034import Gen.Orphans ()
51−import Gen.Text
52−import Gen.TH
5335import Gen.Types.Help
5436import Gen.Types.Id
55−import Gen.Types.Map
5637import Gen.Types.NS
57−import GHC.Generics
58−import GHC.TypeLits
5938import Language.Haskell.Exts (Name)
6039import Language.Haskell.Exts.Pretty (Pretty, prettyPrint)
6140import Prelude hiding (Enum)
62−import Text.EDE (Template)
6341
6442default (Text)
6543
gen/src/Gen/Types/Id.hs+8−18
@@ -23,6 +23,7 @@ module Gen.Types.Id
2323
2424 , global
2525 , local
26+ , localise
2627
2728 , gid
2829 , lid
@@ -42,27 +43,13 @@ module Gen.Types.Id
4243 , pname
4344 ) where
4445
45−import Control.Applicative
46−import Control.Lens hiding (pre, (.=))
4746import Data.Aeson hiding (Bool, String)
48−import Data.Aeson.TH
49−import qualified Data.Attoparsec.Text as A
50−import Data.Bifunctor
5147import qualified Data.CaseInsensitive as CI
52−import Data.Char
53−import Data.Foldable (foldMap)
54−import Data.Function (on)
5548import Data.Hashable
56−import qualified Data.HashMap.Strict as Map
57−import Data.List.NonEmpty (NonEmpty (..))
58−import qualified Data.List.NonEmpty as NE
59−import Data.Maybe
60−import Data.Ord
6149import Data.Semigroup hiding (Sum)
6250import Data.String
6351import Data.Text (Text)
6452import qualified Data.Text as Text
65−import qualified Data.Text.Lazy as LText
6653import qualified Data.Text.Lazy.Builder as Build
6754import Data.Text.Manipulate
6855import Formatting
@@ -71,8 +58,7 @@ import Gen.Text
7158import Gen.Types.Map
7259import GHC.Generics (Generic)
7360import Language.Haskell.Exts.Build
74−import Language.Haskell.Exts.Pretty (prettyPrint)
75−import Language.Haskell.Exts.Syntax (Name)
61+import Language.Haskell.Exts.Syntax (Exp, Name)
7662
7763aname :: Text -> Name
7864aname = name . Text.unpack . (<> "API") . upperHead . Text.replace "." ""
@@ -80,7 +66,7 @@ aname = name . Text.unpack . (<> "API") . upperHead . Text.replace "." ""
8066mname :: Text -> Suffix -> Global -> (Name, Global, Text)
8167mname abrv (Suffix suf) (Global g) =
8268 ( name . Text.unpack $ mconcat n <> suf -- Action service type alias.
83− , Global (n <> ["'"]) -- Action data type.
69+ , Global n -- (n <> ["'"]) -- Action data type.
8470 , Text.intercalate "." ns -- Action namespace.
8571 )
8672 where
@@ -107,9 +93,10 @@ fname = pre (Text.cons '_' . renameField)
10793lname = pre renameField
10894pname = pre (flip Text.snoc '_' . Text.cons 'p' . upperHead . renameField)
10995
110−--dstr :: Global ->
96+dstr :: Global -> Exp
11197dstr = strE . Text.unpack . toPascal . global
11298
99+fstr :: Local -> Exp
113100fstr = strE . Text.unpack . local
114101
115102pre :: (Text -> Text) -> Prefix -> Local -> Name
@@ -156,3 +143,6 @@ global (Global g) = foldMap (upperAcronym . upperHead) g
156143
157144reference :: Global -> Local -> Global
158145reference (Global g) (Local l) = Global (g <> Text.split (== '.') l)
146+
147+localise :: Global -> Local
148+localise = Local . global
gen/src/Gen/Types/NS.hs+2−9
@@ -14,15 +14,11 @@ module Gen.Types.NS
1414 ) where
1515
1616import Data.Aeson
17−import Data.Aeson.Types
18−import Data.Char
19−import Data.Monoid
2017import Data.Semigroup
2118import Data.String
22−import Data.Text (Text)
23−import qualified Data.Text as Text
19+import Data.Text (Text)
20+import qualified Data.Text as Text
2421import Data.Text.Manipulate
25−import qualified Filesystem.Path.CurrentOS as Path
2622import Gen.Text
2723
2824newtype NS = NS { unNS :: [Text] }
@@ -31,9 +27,6 @@ newtype NS = NS { unNS :: [Text] }
3127mkNS :: Text -> NS
3228mkNS = NS . map (upperAcronym . upperHead) . Text.split (== '.')
3329
34−nsToPath :: NS -> Path.FilePath
35−nsToPath (NS xs) = Path.fromText (Text.intercalate "/" xs) Path.<.> "hs"
36−
3730instance IsString NS where
3831 fromString "" = mempty
3932 fromString s = mkNS (fromString s)
gen/src/Gen/Types/Schema.hs+38−30
@@ -25,45 +25,25 @@
2525module Gen.Types.Schema where
2626
2727import Control.Applicative
28−import Control.Lens hiding ((.=))
28+import Control.Lens hiding ((.=))
2929import Control.Monad
30−import Data.Aeson hiding (Array, Bool, Object,
31− String)
32−import qualified Data.Aeson as A
30+import Data.Aeson hiding (Array, Bool, Object, String)
31+import qualified Data.Aeson as A
3332import Data.Aeson.TH
34−import Data.Aeson.Types (Parser)
35−import Data.Char
36−import Data.Function (on)
37−import Data.Hashable
38−import qualified Data.HashMap.Strict as Map
39−import qualified Data.HashSet as Set
40−import Data.List (groupBy, sort, sortOn)
41−import Data.List.NonEmpty (NonEmpty (..))
42−import qualified Data.List.NonEmpty as NE
33+import Data.Aeson.Types (Parser)
34+import qualified Data.HashMap.Strict as Map
4335import Data.Maybe
44−import Data.Ord
45−import Data.Semigroup ((<>))
46−import Data.Text (Text)
47−import qualified Data.Text as Text
48−import qualified Data.Text.Lazy as LText
49−import qualified Data.Text.Lazy.Builder as Build
36+import Data.Semigroup ((<>))
37+import Data.Text (Text)
38+import qualified Data.Text as Text
5039import Data.Text.Manipulate
51−import qualified Data.Text.Read as Read
52−import qualified Filesystem.Path.CurrentOS as Path
53−import Formatting
54−import Gen.Orphans ()
40+import Gen.Orphans ()
5541import Gen.Text
5642import Gen.TH
5743import Gen.Types.Help
5844import Gen.Types.Id
5945import Gen.Types.Map
60−import Gen.Types.NS
61−import GHC.Generics
62−import GHC.TypeLits
63−import Language.Haskell.Exts (Name)
64−import Language.Haskell.Exts.Pretty (Pretty, prettyPrint)
65−import Prelude hiding (Enum)
66−import Text.EDE (Template)
46+import Prelude hiding (Enum)
6747
6848keyless :: Map Text a -> [a]
6949keyless = Map.elems
@@ -113,6 +93,25 @@ defaulted = isJust . view iDefault
11393required = view iRequired
11494parameter s = required s && not (defaulted s)
11595
96+emptyInfo :: Info
97+emptyInfo = Info
98+ { _iId = Nothing
99+ , _iDescription = Nothing
100+ , _iDefault = Nothing
101+ , _iRequired = False
102+ , _iPattern = Nothing
103+ , _iMinimum = Nothing
104+ , _iMaximum = Nothing
105+ , _iRepeated = False
106+ , _iAnnotations = mempty
107+ }
108+
109+requiredInfo :: Info
110+requiredInfo = emptyInfo & iRequired .~ True
111+
112+setRequired :: HasInfo a => a -> a
113+setRequired = iRequired .~ True
114+
116115data Schema a
117116 = SAny Info Any
118117 | SRef Info Ref
@@ -152,6 +151,9 @@ instance HasInfo (Schema a) where
152151 SArr _ x -> SArr i x
153152 SObj _ x -> SObj i x
154153
154+instance HasInfo (Fix Schema) where
155+ info = lens (\(Fix f) -> f ^. info) (\(Fix f) a -> Fix (f & info .~ a))
156+
155157checkType :: Text -> A.Object -> Parser ()
156158checkType x o = do
157159 y <- o .: "type"
@@ -172,6 +174,7 @@ instance FromJSON Ref where
172174 parseJSON = withObject "ref" (fmap Ref . (.: "$ref"))
173175
174176data Lit
177+ -- Literal types.
175178 = Text
176179 | Bool
177180 | Float
@@ -184,6 +187,11 @@ data Lit
184187 | Nat
185188 | Date
186189 | Time
190+ -- Core types.
191+ | Body
192+ | Alt
193+ | Key
194+ | OAuthToken
187195 deriving (Eq, Show)
188196
189197instance FromJSON Lit where
gen/src/Main.hs−2
@@ -19,7 +19,6 @@ import Control.Lens hiding ((<.>))
1919import Control.Monad.State
2020import Data.List (nub, sort)
2121import Data.String
22−import Data.Text (Text)
2322import qualified Data.Text as Text
2423import qualified Filesystem as FS
2524import Filesystem.Path.CurrentOS
@@ -184,4 +183,3 @@ main = do
184183 done
185184
186185 title ("Successfully processed " % int % " models.") i
187−
gen/static/LICENSE−6
@@ -365,9 +365,3 @@ file in a relevant directory) where a recipient would be likely to look
365365for such a notice.
366366
367367You may add additional accurate notices of copyright ownership.
368−
369−Exhibit B - "Incompatible With Secondary Licenses" Notice
370−---------------------------------------------------------
371−
372− This Source Code Form is "Incompatible With Secondary Licenses", as
373− defined by the Mozilla Public License, v. 2.0.