on develop help sign in
Adding request/media bodies to method schema
6bf9becBrendan Hay
gen/LICENSE−6
@@ -365,9 +365,3 @@ file in a relevant directory) where a recipient would be likely to look
365for such a notice.
365for such a notice.
366
366
367You may add additional accurate notices of copyright ownership.
367You 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−
14-- Module : Gen.AST
1-- Module : Gen.AST
15-- Copyright : (c) 2015 Brendan Hay
2-- Copyright : (c) 2015 Brendan Hay
16-- License : Mozilla Public License, v. 2.0.
3-- License : Mozilla Public License, v. 2.0.
@@ -20,28 +7,13 @@
20
7
21module Gen.AST where
8module Gen.AST where
22
9
23−import Control.Applicative
24−import Control.Error
25−import Control.Lens hiding (lens)
26import Control.Monad.Except
10import Control.Monad.Except
27import Control.Monad.State.Strict
11import 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
35import Debug.Trace
12import Debug.Trace
36−import Gen.AST.Flatten (flatten)
13+import Gen.AST.Flatten (flatten)
37−import Gen.AST.Render (render)
14+import Gen.AST.Render (render)
38−import Gen.AST.Solve (solve)
15+import Gen.AST.Solve (solve)
39−import Gen.Formatting
40import Gen.Types
16import Gen.Types
41−import HIndent
42−import Language.Haskell.Exts.Build (name)
43−import Language.Haskell.Exts.Pretty
44−import Prelude hiding (sum)
45
17
46runAST :: Versions -> Service (Fix Schema) -> Either Error Library
18runAST :: Versions -> Service (Fix Schema) -> Either Error Library
47runAST v s = evalState (runExceptT go) (initial s)
19runAST v s = evalState (runExceptT go) (initial s)
@@ -50,133 +22,3 @@ runAST v s = evalState (runExceptT go) (initial s)
50 gs <- flatten s
22 gs <- flatten s
51 (api, ds) <- render =<< solve gs
23 (api, ds) <- render =<< solve gs
52 pure $! Library v gs api ds
24 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
24
24
25import Control.Applicative
25import Control.Applicative
26import Control.Error
26import Control.Error
27−import Control.Lens hiding (lens)
27+import Control.Lens hiding (lens)
28import Control.Monad.Except
28import 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
32import Data.Maybe
30import Data.Maybe
33−import Data.Semigroup ((<>))
31+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
39import Gen.Formatting
32import Gen.Formatting
40import Gen.Types
33import 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)
45
35
46flatten :: Service (Fix Schema) -> AST (Service Global)
36flatten :: Service (Fix Schema) -> AST (Service Global)
47flatten s = do
37flatten s = do
@@ -91,7 +81,15 @@ schema g ml (Fix f) = go f >>= insert this
91 Obj Nothing <$> Map.traverseWithKey (localSchema this) ps
81 Obj Nothing <$> Map.traverseWithKey (localSchema this) ps
92
82
93globalParam :: Local -> Param (Fix Schema) -> AST (Param Global)
83globalParam :: 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) }
95
93
96localParam :: Global -> Local -> Param (Fix Schema) -> AST (Param Global)
94localParam :: Global -> Local -> Param (Fix Schema) -> AST (Param Global)
97localParam g l p = do
95localParam g l p = do
@@ -118,27 +116,44 @@ method :: Map Local (Param Global)
118method qs suf m@Method {..} = do
116method qs suf m@Method {..} = do
119 ps <- Map.traverseWithKey (localParam _mId) _mParameters
117 ps <- Map.traverseWithKey (localParam _mId) _mParameters
120 cn <- use sCanonicalName
118 cn <- use sCanonicalName
119+
121 let (_, typ, _) = mname cn suf _mId
120 let (_, typ, _) = mname cn suf _mId
121+
122+ b <- body typ
123+
122− params = ps <> qs
124+ let params = ps <> qs
123− void $ insert typ (fresh params)
125+ fields = b (upload (Map.map _pParam params))
126+
127+ void $ insert typ (SObj schemaInfo (Obj Nothing fields))
124 pure $! m { _mParameters = params }
128 pure $! m { _mParameters = params }
125 where
129 where
126− fresh ps = SObj info' $ Obj Nothing (Map.map _pParam ps)
127−
128− info' = Info
129− { _iId = Nothing
130− , _iDescription = _mDescription
130+ schemaInfo = emptyInfo { _iDescription = _mDescription }
131+
132+ bodyInfo = requiredInfo { _iDescription = Just "Multipart request metadata." }
133+
134+ body p = case _mRequest of
131− , _iDefault = Nothing
135+ Nothing -> pure id
132− , _iRequired = False
136+ Just x -> do
133− , _iPattern = Nothing
137+ let f = localise (ref x)
134− , _iMinimum = Nothing
138+ g <- localSchema p f (Fix (SRef bodyInfo x))
135− , _iMaximum = Nothing
139+ pure (Map.insert f g)
136− , _iRepeated = False
140+
137− , _iAnnotations = mempty
141+ upload
138− }
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.
139
155
140−setRequired :: Fix Schema -> Fix Schema
156+ -- otherwise ensure servants 'ReqBody' is set.
141−setRequired (Fix e) = Fix (e & iRequired .~ True)
142
157
143insert :: Global -> Schema Global -> AST Global
158insert :: Global -> Schema Global -> AST Global
144insert g s = do
159insert g s = do
gen/src/Gen/AST/Render.hs+2−11
@@ -26,27 +26,17 @@ import Control.Applicative
26import Control.Error
26import Control.Error
27import Control.Lens hiding (enum, lens)
27import Control.Lens hiding (enum, lens)
28import Control.Monad.Except
28import Control.Monad.Except
29−import Data.CaseInsensitive (CI)
29+import Data.Char (isSpace)
30−import qualified Data.CaseInsensitive as CI
31−import Data.Char
32−import Data.Hashable
33import qualified Data.HashMap.Strict as Map
30import qualified Data.HashMap.Strict as Map
34−import qualified Data.HashSet as Set
35−import Data.List (intersect)
36import Data.Maybe
31import Data.Maybe
37import Data.Semigroup ((<>))
32import Data.Semigroup ((<>))
38−import Data.Text (Text)
39import qualified Data.Text as Text
33import qualified Data.Text as Text
40import qualified Data.Text.Lazy as LText
34import qualified Data.Text.Lazy as LText
41import qualified Data.Text.Lazy.Builder as Build
35import qualified Data.Text.Lazy.Builder as Build
42−import Data.Text.Manipulate
43−import Debug.Trace
44import Gen.AST.Solve (getSolved)
36import Gen.AST.Solve (getSolved)
45import Gen.Formatting
37import Gen.Formatting
46import Gen.Syntax
38import Gen.Syntax
47−import Gen.Text
48import Gen.Types
39import Gen.Types
49−import Gen.Types.Data
50import HIndent
40import HIndent
51import Language.Haskell.Exts.Build (name)
41import Language.Haskell.Exts.Build (name)
52import Language.Haskell.Exts.Pretty
42import Language.Haskell.Exts.Pretty
@@ -190,6 +180,7 @@ pp i x
190 , spacing = False
180 , spacing = False
191 }
181 }
192
182
183+
193-- FIXME: dirty hack to render smart ctor parameter comments.
184-- FIXME: dirty hack to render smart ctor parameter comments.
194comments :: Map Local Solved -> Rendered -> Rendered
185comments :: Map Local Solved -> Rendered -> Rendered
195comments (Map.toList -> rs) =
186comments (Map.toList -> rs) =
gen/src/Gen/AST/Solve.hs+7−5
@@ -38,7 +38,6 @@ import Data.Semigroup ((<>))
38import Data.Text (Text)
38import Data.Text (Text)
39import qualified Data.Text as Text
39import qualified Data.Text as Text
40import Data.Text.Manipulate
40import Data.Text.Manipulate
41−import Debug.Trace
42import Gen.Formatting
41import Gen.Formatting
43import Gen.Text
42import Gen.Text
44import Gen.Types
43import Gen.Types
@@ -83,7 +82,7 @@ getSchema g = do
83 Just x -> pure x
82 Just x -> pure x
84 Nothing -> throwError $
83 Nothing -> throwError $
85 format ("Missing Schema: " % gid % "\n" % shown)
84 format ("Missing Schema: " % gid % "\n" % shown)
86− g (map dname (Map.keys ss))
85+ g (map global (Map.keys ss))
87
86
88getType :: Global -> AST TType
87getType :: Global -> AST TType
89getType g = loc "getType" g $ memo typed g go
88getType g = loc "getType" g $ memo typed g go
@@ -118,6 +117,9 @@ getDerive g = loc "getDerive" g $ memo derived g go
118 Bool -> enum
117 Bool -> enum
119 Time -> base
118 Time -> base
120 Date -> base
119 Date -> base
120+ Body -> base
121+ Alt -> base
122+ Key -> base
121 -- FIXME: Add numeric cases
123 -- FIXME: Add numeric cases
122 _ -> [DNum, DIntegral, DReal] <> enum
124 _ -> [DNum, DIntegral, DReal] <> enum
123
125
@@ -215,9 +217,6 @@ acronymPrefixes (global -> g) = map CI.mk (xs ++ map suffix ys ++ zs)
215 -- SomeTestTType -> Som
217 -- SomeTestTType -> Som
216 r6 = Text.take limit <$> listToMaybe (splitWords a)
218 r6 = Text.take limit <$> listToMaybe (splitWords a)
217
219
218−loc :: String -> Global -> a -> a
219−loc n g = id -- trace (n ++ ": " ++ Text.unpack (fromKey g))
220−
221memo :: Lens' Memo (Map Global a)
220memo :: Lens' Memo (Map Global a)
222 -> Global
221 -> Global
223 -> (Schema Global -> AST a)
222 -> (Schema Global -> AST a)
@@ -230,3 +229,6 @@ memo l g f = do
230 x <- f =<< getSchema g
229 x <- f =<< getSchema g
231 l %= Map.insert g x
230 l %= Map.insert g x
232 pure x
231 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
13
13
14import Control.Error
14import Control.Error
15import Control.Monad.Except
15import Control.Monad.Except
16−import Control.Monad.State
17import Data.ByteString (ByteString)
16import Data.ByteString (ByteString)
18−import qualified Data.HashMap.Strict as Map
19−import Data.Text (Text)
20−import qualified Data.Text as Text
21import qualified Data.Text.Lazy as LText
17import qualified Data.Text.Lazy as LText
22import Data.Text.Lazy.Builder (toLazyText)
18import Data.Text.Lazy.Builder (toLazyText)
23import qualified Data.Text.Lazy.IO as LText
19import qualified Data.Text.Lazy.IO as LText
gen/src/Gen/Syntax.hs+11−1
@@ -29,7 +29,7 @@ import Gen.Text
29import Gen.Types
29import Gen.Types
30import Language.Haskell.Exts.Build
30import Language.Haskell.Exts.Build
31import Language.Haskell.Exts.SrcLoc
31import Language.Haskell.Exts.SrcLoc
32−import Language.Haskell.Exts.Syntax hiding (Int, Lit)
32+import Language.Haskell.Exts.Syntax hiding (Alt, Int, Lit)
33
33
34urlSig :: Name -> Decl
34urlSig :: Name -> Decl
35urlSig n = TypeSig noLoc [n] (TyCon "BaseUrl")
35urlSig n = TypeSig noLoc [n] (TyCon "BaseUrl")
@@ -331,6 +331,11 @@ externalLit = \case
331 Int32 -> TyCon "Int32"
331 Int32 -> TyCon "Int32"
332 Int64 -> TyCon "Int64"
332 Int64 -> TyCon "Int64"
333
333
334+ Alt -> TyCon "Alt"
335+ Key -> TyCon "Key"
336+ OAuthToken -> TyCon "OAuthToken"
337+ Body -> TyCon "Body"
338+
334internalLit :: Lit -> Type
339internalLit :: Lit -> Type
335internalLit = \case
340internalLit = \case
336 Text -> TyCon "Text"
341 Text -> TyCon "Text"
@@ -346,6 +351,11 @@ internalLit = \case
346 Int32 -> TyCon "Int32"
351 Int32 -> TyCon "Int32"
347 Int64 -> TyCon "Int64"
352 Int64 -> TyCon "Int64"
348
353
354+ Alt -> TyCon "Alt"
355+ Key -> TyCon "Key"
356+ OAuthToken -> TyCon "OAuthToken"
357+ Body -> TyCon "Body"
358+
349mapping :: TType -> Exp -> Exp
359mapping :: TType -> Exp -> Exp
350mapping t e = infixE e "." (go t)
360mapping t e = infixE e "." (go t)
351 where
361 where
gen/src/Gen/Text.hs+3−1
@@ -58,7 +58,7 @@ renameAbbrev = mconcat
58 . stripSuffix " API"
58 . stripSuffix " API"
59
59
60renameField :: Text -> Text
60renameField :: Text -> Text
61−renameField = lowerHead . toCamel
61+renameField = lowerHead . upperAcronym . toCamel
62
62
63renameBranch :: Text -> Text
63renameBranch :: Text -> Text
64renameBranch t
64renameBranch t
@@ -196,6 +196,8 @@ upperAcronym x = Fold.foldl' (flip (uncurry RE.replaceAll)) x xs
196 , ("Nat", "NAT")
196 , ("Nat", "NAT")
197 , ("Youtube", "YouTube")
197 , ("Youtube", "YouTube")
198 , ("Cnc", "CNC")
198 , ("Cnc", "CNC")
199+ , ("Oauth", "OAuth")
200+ , ("Ocr$", "OCR")
199 ]
201 ]
200
202
201acronyms :: [(String, String)]
203acronyms :: [(String, String)]
gen/src/Gen/Tree.hs−2
@@ -28,8 +28,6 @@ import Control.Monad.Except
28import Data.Aeson hiding (json)
28import Data.Aeson hiding (json)
29import Data.Bifunctor
29import Data.Bifunctor
30import Data.Foldable (foldr')
30import Data.Foldable (foldr')
31−import qualified Data.HashMap.Strict as Map
32−import qualified Data.List.NonEmpty as NE
33import Data.Monoid
31import Data.Monoid
34import Data.Text (Text)
32import Data.Text (Text)
35import qualified Data.Text as Text
33import qualified Data.Text as Text
gen/src/Gen/Types.hs+21−32
@@ -33,48 +33,33 @@ module Gen.Types
33 , module Gen.Types.Data
33 , module Gen.Types.Data
34 ) where
34 ) where
35
35
36−import Control.Applicative
36+import Control.Lens hiding ((.=))
37−import Control.Lens hiding ((.=))
38import Control.Monad.Except
37import Control.Monad.Except
39import Control.Monad.State.Strict
38import Control.Monad.State.Strict
40−import Data.Aeson hiding (Array, Bool, String)
39+import Data.Aeson hiding (Array, Bool, String)
41−import qualified Data.Aeson as A
42−import Data.Aeson.TH
43−import Data.CaseInsensitive (CI)
40+import Data.CaseInsensitive (CI)
44−import qualified Data.CaseInsensitive as CI
45−import Data.Char
46−import Data.Function (on)
41+import Data.Function (on)
47−import qualified Data.HashMap.Strict as Map
42+import qualified Data.HashMap.Strict as Map
48−import qualified Data.HashSet as Set
43+import qualified Data.HashSet as Set
49−import Data.List (groupBy, sort, sortOn)
44+import Data.List (sort)
50−import Data.List.NonEmpty (NonEmpty (..))
51−import qualified Data.List.NonEmpty as NE
52−import Data.Maybe
53import Data.Ord
45import Data.Ord
54−import Data.Semigroup ((<>))
46+import Data.Semigroup ((<>))
55−import Data.Text (Text)
47+import Data.Text (Text)
56−import qualified Data.Text as Text
48+import qualified Data.Text as Text
57−import qualified Data.Text.Lazy as LText
49+import qualified Data.Text.Lazy as LText
58−import qualified Data.Text.Lazy.Builder as Build
50+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
51+import qualified Filesystem.Path.CurrentOS as Path
62import Formatting
52import Formatting
63−import Gen.Orphans ()
53+import Gen.Orphans ()
64−import Gen.Text
65−import Gen.TH
66import Gen.Types.Data
54import Gen.Types.Data
67import Gen.Types.Help
55import Gen.Types.Help
68import Gen.Types.Id
56import Gen.Types.Id
69import Gen.Types.Map
57import Gen.Types.Map
70import Gen.Types.NS
58import Gen.Types.NS
71import Gen.Types.Schema
59import Gen.Types.Schema
72−import GHC.Generics
73import GHC.TypeLits
60import GHC.TypeLits
74−import Language.Haskell.Exts (Name)
75−import Language.Haskell.Exts.Pretty (Pretty, prettyPrint)
76−import Prelude hiding (Enum)
61+import Prelude hiding (Enum)
77−import Text.EDE (Template)
62+import Text.EDE (Template)
78
63
79type Set = Set.HashSet
64type Set = Set.HashSet
80type Error = LText.Text
65type Error = LText.Text
@@ -280,7 +265,11 @@ data Memo = Memo
280 }
265 }
281
266
282initial :: Service (Fix Schema) -> Memo
267initial :: 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+ ]
284
273
285-- reserve :: Flattened -> AST ()
274-- reserve :: Flattened -> AST ()
286-- reserve svc = do
275-- reserve svc = do
gen/src/Gen/Types/Data.hs+1−23
@@ -24,42 +24,20 @@
24
24
25module Gen.Types.Data where
25module Gen.Types.Data where
26
26
27−import Control.Applicative
28−import Control.Lens hiding ((.=))
29import Data.Aeson hiding (Array, Bool, String)
27import 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)
28+import Data.List (sortOn)
37−import Data.List.NonEmpty (NonEmpty (..))
38−import qualified Data.List.NonEmpty as NE
39import Data.Maybe
29import Data.Maybe
40−import Data.Ord
41−import Data.Semigroup ((<>))
42import Data.Text (Text)
30import Data.Text (Text)
43import qualified Data.Text as Text
31import qualified Data.Text as Text
44import qualified Data.Text.Lazy as LText
32import qualified Data.Text.Lazy as LText
45−import qualified Data.Text.Lazy.Builder as Build
46import Data.Text.Manipulate
33import Data.Text.Manipulate
47−import qualified Data.Text.Read as Read
48−import qualified Filesystem.Path.CurrentOS as Path
49−import Formatting
50import Gen.Orphans ()
34import Gen.Orphans ()
51−import Gen.Text
52−import Gen.TH
53import Gen.Types.Help
35import Gen.Types.Help
54import Gen.Types.Id
36import Gen.Types.Id
55−import Gen.Types.Map
56import Gen.Types.NS
37import Gen.Types.NS
57−import GHC.Generics
58−import GHC.TypeLits
59import Language.Haskell.Exts (Name)
38import Language.Haskell.Exts (Name)
60import Language.Haskell.Exts.Pretty (Pretty, prettyPrint)
39import Language.Haskell.Exts.Pretty (Pretty, prettyPrint)
61import Prelude hiding (Enum)
40import Prelude hiding (Enum)
62−import Text.EDE (Template)
63
41
64default (Text)
42default (Text)
65
43
gen/src/Gen/Types/Id.hs+8−18
@@ -23,6 +23,7 @@ module Gen.Types.Id
23
23
24 , global
24 , global
25 , local
25 , local
26+ , localise
26
27
27 , gid
28 , gid
28 , lid
29 , lid
@@ -42,27 +43,13 @@ module Gen.Types.Id
42 , pname
43 , pname
43 ) where
44 ) where
44
45
45−import Control.Applicative
46−import Control.Lens hiding (pre, (.=))
47import Data.Aeson hiding (Bool, String)
46import Data.Aeson hiding (Bool, String)
48−import Data.Aeson.TH
49−import qualified Data.Attoparsec.Text as A
50−import Data.Bifunctor
51import qualified Data.CaseInsensitive as CI
47import qualified Data.CaseInsensitive as CI
52−import Data.Char
53−import Data.Foldable (foldMap)
54−import Data.Function (on)
55import Data.Hashable
48import 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
61import Data.Semigroup hiding (Sum)
49import Data.Semigroup hiding (Sum)
62import Data.String
50import Data.String
63import Data.Text (Text)
51import Data.Text (Text)
64import qualified Data.Text as Text
52import qualified Data.Text as Text
65−import qualified Data.Text.Lazy as LText
66import qualified Data.Text.Lazy.Builder as Build
53import qualified Data.Text.Lazy.Builder as Build
67import Data.Text.Manipulate
54import Data.Text.Manipulate
68import Formatting
55import Formatting
@@ -71,8 +58,7 @@ import Gen.Text
71import Gen.Types.Map
58import Gen.Types.Map
72import GHC.Generics (Generic)
59import GHC.Generics (Generic)
73import Language.Haskell.Exts.Build
60import Language.Haskell.Exts.Build
74−import Language.Haskell.Exts.Pretty (prettyPrint)
61+import Language.Haskell.Exts.Syntax (Exp, Name)
75−import Language.Haskell.Exts.Syntax (Name)
76
62
77aname :: Text -> Name
63aname :: Text -> Name
78aname = name . Text.unpack . (<> "API") . upperHead . Text.replace "." ""
64aname = name . Text.unpack . (<> "API") . upperHead . Text.replace "." ""
@@ -80,7 +66,7 @@ aname = name . Text.unpack . (<> "API") . upperHead . Text.replace "." ""
80mname :: Text -> Suffix -> Global -> (Name, Global, Text)
66mname :: Text -> Suffix -> Global -> (Name, Global, Text)
81mname abrv (Suffix suf) (Global g) =
67mname abrv (Suffix suf) (Global g) =
82 ( name . Text.unpack $ mconcat n <> suf -- Action service type alias.
68 ( name . Text.unpack $ mconcat n <> suf -- Action service type alias.
83− , Global (n <> ["'"]) -- Action data type.
69+ , Global n -- (n <> ["'"]) -- Action data type.
84 , Text.intercalate "." ns -- Action namespace.
70 , Text.intercalate "." ns -- Action namespace.
85 )
71 )
86 where
72 where
@@ -107,9 +93,10 @@ fname = pre (Text.cons '_' . renameField)
107lname = pre renameField
93lname = pre renameField
108pname = pre (flip Text.snoc '_' . Text.cons 'p' . upperHead . renameField)
94pname = pre (flip Text.snoc '_' . Text.cons 'p' . upperHead . renameField)
109
95
110−--dstr :: Global ->
96+dstr :: Global -> Exp
111dstr = strE . Text.unpack . toPascal . global
97dstr = strE . Text.unpack . toPascal . global
112
98
99+fstr :: Local -> Exp
113fstr = strE . Text.unpack . local
100fstr = strE . Text.unpack . local
114
101
115pre :: (Text -> Text) -> Prefix -> Local -> Name
102pre :: (Text -> Text) -> Prefix -> Local -> Name
@@ -156,3 +143,6 @@ global (Global g) = foldMap (upperAcronym . upperHead) g
156
143
157reference :: Global -> Local -> Global
144reference :: Global -> Local -> Global
158reference (Global g) (Local l) = Global (g <> Text.split (== '.') l)
145reference (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
14 ) where
14 ) where
15
15
16import Data.Aeson
16import Data.Aeson
17−import Data.Aeson.Types
18−import Data.Char
19−import Data.Monoid
20import Data.Semigroup
17import Data.Semigroup
21import Data.String
18import Data.String
22−import Data.Text (Text)
19+import Data.Text (Text)
23−import qualified Data.Text as Text
20+import qualified Data.Text as Text
24import Data.Text.Manipulate
21import Data.Text.Manipulate
25−import qualified Filesystem.Path.CurrentOS as Path
26import Gen.Text
22import Gen.Text
27
23
28newtype NS = NS { unNS :: [Text] }
24newtype NS = NS { unNS :: [Text] }
@@ -31,9 +27,6 @@ newtype NS = NS { unNS :: [Text] }
31mkNS :: Text -> NS
27mkNS :: Text -> NS
32mkNS = NS . map (upperAcronym . upperHead) . Text.split (== '.')
28mkNS = NS . map (upperAcronym . upperHead) . Text.split (== '.')
33
29
34−nsToPath :: NS -> Path.FilePath
35−nsToPath (NS xs) = Path.fromText (Text.intercalate "/" xs) Path.<.> "hs"
36−
37instance IsString NS where
30instance IsString NS where
38 fromString "" = mempty
31 fromString "" = mempty
39 fromString s = mkNS (fromString s)
32 fromString s = mkNS (fromString s)
gen/src/Gen/Types/Schema.hs+38−30
@@ -25,45 +25,25 @@
25module Gen.Types.Schema where
25module Gen.Types.Schema where
26
26
27import Control.Applicative
27import Control.Applicative
28−import Control.Lens hiding ((.=))
28+import Control.Lens hiding ((.=))
29import Control.Monad
29import Control.Monad
30−import Data.Aeson hiding (Array, Bool, Object,
30+import Data.Aeson hiding (Array, Bool, Object, String)
31− String)
32−import qualified Data.Aeson as A
31+import qualified Data.Aeson as A
33import Data.Aeson.TH
32import Data.Aeson.TH
34−import Data.Aeson.Types (Parser)
33+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
34+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
43import Data.Maybe
35import Data.Maybe
44−import Data.Ord
36+import Data.Semigroup ((<>))
45−import Data.Semigroup ((<>))
46−import Data.Text (Text)
37+import Data.Text (Text)
47−import qualified Data.Text as Text
38+import qualified Data.Text as Text
48−import qualified Data.Text.Lazy as LText
49−import qualified Data.Text.Lazy.Builder as Build
50import Data.Text.Manipulate
39import 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 ()
55import Gen.Text
41import Gen.Text
56import Gen.TH
42import Gen.TH
57import Gen.Types.Help
43import Gen.Types.Help
58import Gen.Types.Id
44import Gen.Types.Id
59import Gen.Types.Map
45import 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)
46+import Prelude hiding (Enum)
66−import Text.EDE (Template)
67
47
68keyless :: Map Text a -> [a]
48keyless :: Map Text a -> [a]
69keyless = Map.elems
49keyless = Map.elems
@@ -113,6 +93,25 @@ defaulted = isJust . view iDefault
113required = view iRequired
93required = view iRequired
114parameter s = required s && not (defaulted s)
94parameter s = required s && not (defaulted s)
115
95
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+
116data Schema a
115data Schema a
117 = SAny Info Any
116 = SAny Info Any
118 | SRef Info Ref
117 | SRef Info Ref
@@ -152,6 +151,9 @@ instance HasInfo (Schema a) where
152 SArr _ x -> SArr i x
151 SArr _ x -> SArr i x
153 SObj _ x -> SObj i x
152 SObj _ x -> SObj i x
154
153
154+instance HasInfo (Fix Schema) where
155+ info = lens (\(Fix f) -> f ^. info) (\(Fix f) a -> Fix (f & info .~ a))
156+
155checkType :: Text -> A.Object -> Parser ()
157checkType :: Text -> A.Object -> Parser ()
156checkType x o = do
158checkType x o = do
157 y <- o .: "type"
159 y <- o .: "type"
@@ -172,6 +174,7 @@ instance FromJSON Ref where
172 parseJSON = withObject "ref" (fmap Ref . (.: "$ref"))
174 parseJSON = withObject "ref" (fmap Ref . (.: "$ref"))
173
175
174data Lit
176data Lit
177+ -- Literal types.
175 = Text
178 = Text
176 | Bool
179 | Bool
177 | Float
180 | Float
@@ -184,6 +187,11 @@ data Lit
184 | Nat
187 | Nat
185 | Date
188 | Date
186 | Time
189 | Time
190+ -- Core types.
191+ | Body
192+ | Alt
193+ | Key
194+ | OAuthToken
187 deriving (Eq, Show)
195 deriving (Eq, Show)
188
196
189instance FromJSON Lit where
197instance FromJSON Lit where
gen/src/Main.hs−2
@@ -19,7 +19,6 @@ import Control.Lens hiding ((<.>))
19import Control.Monad.State
19import Control.Monad.State
20import Data.List (nub, sort)
20import Data.List (nub, sort)
21import Data.String
21import Data.String
22−import Data.Text (Text)
23import qualified Data.Text as Text
22import qualified Data.Text as Text
24import qualified Filesystem as FS
23import qualified Filesystem as FS
25import Filesystem.Path.CurrentOS
24import Filesystem.Path.CurrentOS
@@ -184,4 +183,3 @@ main = do
184 done
183 done
185
184
186 title ("Successfully processed " % int % " models.") i
185 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
365for such a notice.
365for such a notice.
366
366
367You may add additional accurate notices of copyright ownership.
367You 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.