on develop help sign in
Updating parameter typing/solving to ensure sharing
commit8263baf2af43990d65b21ffe9fe4ce0c4a6fc01c authorBrendan Hay <brendan.g.hay@gmail.com> dateSun 27 Sep 2015, 20:21 (11 years ago) parent3908f1b
7 files changed+212−170
gen/Makefile+1−1 gen/src/Gen/AST.hs+71−54 gen/src/Gen/Solve.hs+4−42 gen/src/Gen/Syntax.hs+27−26 gen/src/Gen/Tree.hs+7−1 gen/src/Gen/Types.hs+91−46 gen/template/action.ede+11
gen/Makefile+1−1
@@ -14,7 +14,7 @@ CLIENT_VERSION = $(call version,$(TOP)/gen/gogol-gen.cabal)
1414
1515MODELS ?= $(shell find $(MODEL_DIR) -type f -name '*.json' | sort)
1616
17−.PHONY: gen format
17+.PHONY: gen format $(BIN)/gogol-gen
1818
1919release: gen format
2020
gen/src/Gen/AST.hs+71−54
@@ -28,50 +28,46 @@ import Control.Monad.Except
2828import Control.Monad.State.Strict
2929import Data.Char
3030import qualified Data.HashMap.Strict as Map
31+import Data.Maybe
3132import Data.Semigroup ((<>))
3233import qualified Data.Text as Text
3334import qualified Data.Text.Lazy as LText
3435import qualified Data.Text.Lazy.Builder as Build
35−import Data.Traversable (for)
36+import Debug.Trace
3637import Gen.Formatting
3738import Gen.Solve
3839import Gen.Syntax
3940import Gen.Types
4041import HIndent
41−import Language.Haskell.Exts (Name)
4242import Language.Haskell.Exts.Build (name)
4343import Language.Haskell.Exts.Pretty
4444import Prelude hiding (sum)
4545
46−runAST :: Service (Fix Schema) Resource -> Either Error (Service Data API)
47−runAST svc = evalState (runExceptT (render ss)) (initial (_svcSchemas ss))
46+runAST :: Parsed -> Either Error Printed
47+runAST svc = evalState (runExceptT (go svc)) initial
4848 where
49− ss = flatten svc
49+ go = flatten >=> solveAll >=> render
5050
51−render :: Service (Schema Id) Resource -> AST (Service Data API)
51+render :: Typed -> AST Printed
5252render svc = do
53− x <- kvTraverseMaybe typ (_svcSchemas svc)
53+ x <- traverse typ (_svcSchemas svc)
5454 y <- api (_svcApi svc)
55− return $! svc { _svcSchemas = x, _svcApi = y }
55+ return $! svc { _svcSchemas = catMaybes x, _svcParameters = (), _svcApi = y }
5656 where
57− typ :: Id -> Schema Id -> AST (Maybe Data)
58− typ k = \case
57+ typ :: Solved -> AST (Maybe Data)
58+ typ Solved{..} = case _schema of
5959 Arr {} -> pure Nothing
6060 Ref {} -> pure Nothing
6161 Any {} -> pure Nothing
6262 Lit {} -> pure Nothing
63− Enum i vs ds -> Just . sum' <$> prefix k
63+ Enum i vs ds -> pure . Just $
64+ Sum (dname _ident) (i ^. description) (zipWith branch vs (ds ++ repeat ""))
6465 where
65− sum' p = Sum (dname k) (i ^. description) $
66− zipWith (branch p) vs (ds ++ repeat "")
66+ branch v = Branch (bname _prefix v) v
6767
68− branch p v = Branch (bname p v) v
69−
70− Obj i rs -> do
71− p <- prefix k
72− ds <- derive k
73− dd <- Map.traverseWithKey (const . solve . mkProp k) rs
74− Just <$> prod k p i ds dd
68+ Obj i rs -> fmap Just $
69+ prod _ident _prefix i _deriving
70+ =<< traverse solve rs
7571
7672 prod :: Id -> Pre -> Info -> [Derive] -> Map Local Solved -> AST Data
7773 prod k p i ds ts = Prod (dname k) (i ^. description)
@@ -93,7 +89,7 @@ render svc = do
9389 "' with the minimum fields required to make a request.\n")
9490 k
9591
96− api :: Resource -> AST API
92+ api :: Resource Solved -> AST API
9793 api x = do
9894 as <- Map.fromList <$> top x
9995 API n <$> pp Print (apiAlias n (Map.keys as))
@@ -112,20 +108,33 @@ render svc = do
112108 verb p l m = do
113109 let (k, i) = vname p l
114110 s <- solve i
115− Just d <- typ i (_schema s)
111+ Just d <- typ s
116112 fmap (k,) $
117113 Action k (actionNS svc p l) (_mDescription m)
118114 <$> pp Print (verbAlias svc k m)
119− <*> pure d
120−
121−flatten :: Service (Fix Schema) Resource -> Service (Schema Id) Resource
122−flatten svc = svc { _svcSchemas = execState run mempty }
115+ <*> pure (reset d)
116+
117+ reset = \case
118+ Prod n' h r c ls _ -> Prod n' h r c ls []
119+ d -> d
120+
121+solveAll :: Flattened -> AST Typed
122+solveAll svc = do
123+ ss <- traverse solve (_svcSchemas svc)
124+ ps <- traverse (traverse solve) (_svcParameters svc)
125+ a <- traverse solve (_svcApi svc)
126+ pure $! svc { _svcSchemas = ss, _svcParameters = ps, _svcApi = a }
127+
128+flatten :: Parsed -> AST Flattened
129+flatten svc = do
130+ _ <- Map.traverseWithKey typ (_svcSchemas svc)
131+ ps <- Map.traverseWithKey (prm "") (_svcParameters svc)
132+ a <- api ps (_svcApi svc)
133+ ss <- uses schemas Map.keys
134+ pure $! svc { _svcSchemas = ss, _svcParameters = Map.elems ps, _svcApi = a }
123135 where
124− run = mapM_ (uncurry sch) (Map.toList (_svcSchemas svc))
125− >> api (_svcApi svc)
126−
127− sch :: Id -> Fix Schema -> State (Map Id (Schema Id)) Id
128− sch n (Fix f) = go f >>= ins n
136+ typ :: Id -> Fix Schema -> AST Id
137+ typ n (Fix f) = go f >>= ins n
129138 where
130139 go = \case
131140 Obj i ps -> Obj i <$> Map.traverseWithKey (prop n) ps
@@ -136,43 +145,51 @@ flatten svc = svc { _svcSchemas = execState run mempty }
136145 Ref i r -> pure (Ref i r)
137146 Any i -> pure (Any i)
138147
139− prop :: Id -> Local -> Fix Schema -> State (Map Id (Schema Id)) Id
140− prop n l (Fix f) = go f >>= ins this
148+ prop :: Id -> Local -> Fix Schema -> AST Id
149+ prop p l (Fix f) = go f >>= ins this
141150 where
142151 go = \case
143152 Obj i ps -> Obj i <$> Map.traverseWithKey (prop this) ps
144153 Arr i (Fix e) -> Arr i <$> prop this "item" (Fix (e & required .~ True))
145154
146− Enum i vs ds -> pure (Enum i vs ds)
147− Lit i x -> pure (Lit i x)
148− Ref i r -> pure (Ref i r)
149− Any i -> pure (Any i)
155+ Enum i vs ds -> pure (Enum i vs ds)
156+ Lit i x -> pure (Lit i x)
157+ Ref i r -> pure (Ref i r)
158+ Any i -> pure (Any i)
159+
160+ this = mkProp p l
150161
151− this = mkProp n l
162+ prm :: Id -> Local -> Param (Fix Schema) -> AST (Param Id)
163+ prm p l x = do
164+ n <- prop p l (_prmSchema x)
165+ pure $! x { _prmSchema = n }
152166
153− api :: Resource -> State (Map Id (Schema Id)) ()
154− api = \case
155− Top rs -> mapM_ (uncurry sub) (Map.toList rs)
156− Sub ms -> mapM_ (uncurry (verb "")) (Map.toList ms)
167+ api :: Map Local (Param Id) -> Resource (Fix Schema) -> AST (Resource Id)
168+ api qs = \case
169+ Top rs -> Top <$> Map.traverseWithKey sub rs
170+ Sub ms -> Sub <$> Map.traverseWithKey (verb "") ms
157171 where
158172 sub l = \case
159− Top rs -> mapM_ (uncurry sub) (Map.toList rs)
160− Sub ms -> mapM_ (uncurry (verb l)) (Map.toList ms)
173+ Top rs -> Top <$> Map.traverseWithKey sub rs
174+ Sub ms -> Sub <$> Map.traverseWithKey (verb l) ms
161175
162− -- FIXME: Global parameters
163176 verb p l m = do
164177 let (_, i) = vname p l
165− rs <- Map.traverseWithKey (\k v -> prop i k (paramSchema v)) (_mParameters m)
166− void . ins i $
167− Obj (Info (_mDescription m) Nothing False Nothing) rs
178+ rs <- Map.traverseWithKey (prm i) (_mParameters m)
179+ _ <- ins i $
180+ Obj (Info (_mDescription m) Nothing False Nothing) (Map.map _prmSchema (rs <> qs))
181+ pure $! m { _mParameters = rs <> qs }
168182
169− ins :: Id -> Schema Id -> State (Map Id (Schema Id)) Id
183+ ins :: Id -> Schema Id -> AST Id
170184 ins n x = do
171− s <- gets (Map.lookup n)
172− case s of
173− Nothing -> modify (Map.insert n x) >> pure n
174− -- FIXME:
175− Just e -> error $ "Already exists: " ++ show (n, e, x)
185+ ms <- uses schemas (Map.lookup n)
186+ case ms of
187+ Just y | x /= y -> throwError $
188+ format ("Schema exists: " % shown % "\nTried inserting: " % shown)
189+ y x
190+ _ -> schemas %= Map.insert n x
191+
192+ return n
176193
177194data PP
178195 = Indent
gen/src/Gen/Solve.hs+4−42
@@ -42,44 +42,6 @@ import Gen.Text
4242import Gen.Types
4343import Prelude hiding (sum)
4444
45−data TType
46− = TType Id
47− | TLit Lit
48− | TMaybe TType
49− | TEither TType TType
50− | TList TType
51−
52−data Derive
53− = DEq
54− | DOrd
55− | DRead
56− | DShow
57− | DEnum
58− | DNum
59− | DIntegral
60− | DReal
61− | DMonoid
62− | DIsString
63− | DData
64− | DTypeable
65− | DGeneric
66− deriving (Eq, Show)
67−
68−data Solved = Solved
69− { _prefix :: Pre
70− , _schema :: Schema Id
71− , _type :: TType
72− , _deriving :: [Derive]
73− }
74−
75−instance HasInfo Solved where
76− info = f . info
77− where
78− f = lens _schema (\s a -> s { _schema = a })
79−
80−monoid :: Solved -> Bool
81−monoid = elem DMonoid . _deriving
82−
8345type Seen = Map (CI Text) (Set (CI Text))
8446
8547data Memo = Memo
@@ -91,8 +53,8 @@ data Memo = Memo
9153 , _schemas :: Map Id (Schema Id)
9254 }
9355
94−initial :: Map Id (Schema Id) -> Memo
95−initial = Memo mempty mempty mempty mempty mempty
56+initial :: Memo
57+initial = Memo mempty mempty mempty mempty mempty mempty
9658
9759makeLenses ''Memo
9860
@@ -116,7 +78,7 @@ memo l k f = do
11678 return x
11779
11880solve :: Id -> AST Solved
119−solve k = Solved <$> prefix k <*> schema k <*> typeOf k <*> derive k
81+solve k = loc "solve" k $ Solved k <$> prefix k <*> schema k <*> typeOf k <*> derive k
12082
12183typeOf :: Id -> AST TType
12284typeOf k = loc "typeof" k $ memo typed k go
@@ -246,4 +208,4 @@ acronymPrefixes (idToText -> n) = map CI.mk (xs ++ map suffix ys ++ zs)
246208 r6 = Text.take limit <$> listToMaybe (splitWords a)
247209
248210loc :: String -> Id -> a -> a
249−loc n r = id -- trace (n ++ ": " ++ Text.unpack (idToText r))
211+loc n r = id --trace (n ++ ": " ++ Text.unpack (idToText r))
gen/src/Gen/Syntax.hs+27−26
@@ -40,40 +40,40 @@ apiAlias n ls = TypeDecl noLoc n [] alias
4040 x:xs -> foldl' (\l r -> TyInfix l (UnQual (sym ":<|>")) r) x xs
4141
4242-- type Method = :> ...
43−verbAlias :: Service s r -> Name -> Method -> Decl
43+verbAlias :: Typed -> Name -> Method Solved -> Decl
4444verbAlias s n m = TypeDecl noLoc n [] alias
4545 where
4646 alias = foldr' (\l r -> TyInfix l (UnQual (sym ":>")) r) verb (path ++ qry)
4747
4848 path :: [Type]
49− path = map match
50− . filter (not . Text.null)
51− $ Text.split (== '/') (_svcServicePath s)
52− <> Text.split (== '/') (_mPath m)
53− where
54− match x
55− | Just (c, t) <- Text.uncons x
56− , c == '{'
57− , Just k <- Map.lookup (Local (Text.init t)) params
58− , _prmLocation k == Path
59− = TyApp (TyApp (tycon "Capture")
60− (sing (Text.init t)))
61− (literal (_prmLiteral k))
62− | otherwise = sing x
49+ path = [] -- map match
50+ -- . filter (not . Text.null)
51+ -- $ Text.split (== '/') (_svcServicePath s)
52+ -- <> Text.split (== '/') (_mPath m)
53+ -- where
54+ -- match x
55+ -- | Just (c, t) <- Text.uncons x
56+ -- , c == '{'
57+ -- , Just k <- Map.lookup (Local (Text.init t)) params
58+ -- , _prmLocation k == Path
59+ -- = TyApp (TyApp (tycon "Capture")
60+ -- (sing (Text.init t)))
61+ -- (literal (_prmLiteral k))
62+ -- | otherwise = sing x
6363
6464 -- FIXME: order by _mParameterOrder
6565 qry :: [Type]
66− qry = mapMaybe f (Map.toList params)
67− where
68− f (k, p) =
69− -- FIXME: types, many/repeated
70− let t = literal (_prmLiteral p)
71− n = sing (local k)
72− in case _prmLocation p of
73− Query -> Just $ TyApp (TyApp (tycon "QueryParam") n) t
74− Path -> Nothing
75−
76− params = _svcParameters s <> _mParameters m
66+ qry = [] -- mapMaybe f (Map.toList params)
67+ -- where
68+ -- f (k, p) =
69+ -- -- FIXME: types, many/repeated
70+ -- let t = literal (_prmLiteral p)
71+ -- n = sing (local k)
72+ -- in case _prmLocation p of
73+ -- Query -> Just $ TyApp (TyApp (tycon "QueryParam") n) t
74+ -- Path -> Nothing
75+
76+-- params = _svcParameters s <> _mParameters m
7777
7878 verb :: Type
7979 verb = TyApp (TyApp meth typ) res
@@ -231,6 +231,7 @@ def s
231231 Lit _ Bool -> lit (upperHead x)
232232 Lit _ Text -> str x
233233 Lit {} -> lit x
234+ e -> error $ "Unsupported default value: " ++ show e
234235
235236 lit = var . name . Text.unpack
236237
gen/src/Gen/Tree.hs+7−1
@@ -87,7 +87,13 @@ populate d Templates{..} l = (encodeString d :/) . dir lib <$> layout
8787 , mod' (sumNS s) (sumImports s) sumTemplate (pure svc)
8888 ] ++ map action (svcActions s)
8989 where
90− action n = mod' n (actionImports s) actionTemplate (pure svc)
90+ action a =
91+ mod' (_actNS a) (actionImports s) actionTemplate
92+ . pure . Object $
93+ act <> svc'
94+ where
95+ Object act = object [ "action" .= a ]
96+ Object svc' = svc
9197
9298 svc = toJSON s
9399
gen/src/Gen/Types.hs+91−46
@@ -266,28 +266,65 @@ instance HasInfo (Schema a) where
266266 Ref _ r -> Ref i r
267267 Any {} -> Any i
268268
269−data Param = Param
269+data Param a = Param
270270 { _prmLocation :: !Location
271271 , _prmRepeated :: !Bool
272272 , _prmInfo :: Info
273− , _prmLiteral :: !Lit
274− }
273+ , _prmSchema :: a
274+ } deriving (Show, Functor, Foldable, Traversable)
275275
276−paramSchema :: Param -> Fix Schema
277−paramSchema p
278− | _prmRepeated p = Fix $ Arr (_prmInfo p) lit
279− | otherwise = lit
280− where
281− lit = Fix $ Lit (_prmInfo p) (_prmLiteral p)
276+-- paramSchema :: Param -> Fix Schema
277+-- paramSchema p
278+-- | _prmRepeated p = Fix $ Arr (_prmInfo p) lit
279+-- | otherwise = lit
280+-- where
281+-- lit = Fix $ Lit (_prmInfo p) (_prmLiteral p)
282282
283−instance FromJSON Param where
283+instance FromJSON a => FromJSON (Param a) where
284284 parseJSON = withObject "parameter" $ \o -> Param
285285 <$> o .: "location"
286286 <*> o .:? "repeated" .!= False
287287 <*> parseJSON (Object o)
288288 <*> parseJSON (Object o)
289289
290−deriveToJSON (js "") ''Param
290+data TType
291+ = TType Id
292+ | TLit Lit
293+ | TMaybe TType
294+ | TEither TType TType
295+ | TList TType
296+
297+data Derive
298+ = DEq
299+ | DOrd
300+ | DRead
301+ | DShow
302+ | DEnum
303+ | DNum
304+ | DIntegral
305+ | DReal
306+ | DMonoid
307+ | DIsString
308+ | DData
309+ | DTypeable
310+ | DGeneric
311+ deriving (Eq, Show)
312+
313+data Solved = Solved
314+ { _ident :: Id
315+ , _prefix :: Pre
316+ , _schema :: Schema Id
317+ , _type :: TType
318+ , _deriving :: [Derive]
319+ }
320+
321+instance HasInfo Solved where
322+ info = f . info
323+ where
324+ f = lens _schema (\s a -> s { _schema = a })
325+
326+monoid :: Solved -> Bool
327+monoid = elem DMonoid . _deriving
291328
292329data Syn a = Syn { syntax :: a }
293330
@@ -345,11 +382,12 @@ data Action = Action
345382 }
346383
347384instance ToJSON Action where
348− toJSON (Action n _ h a d) = object
349− [ "name" .= Syn n
350− , "help" .= h
351− , "alias" .= a
352− , "data" .= d
385+ toJSON Action {..} = object
386+ [ "name" .= Syn _actName
387+ , "ns" .= _actNS
388+ , "help" .= _actHelp
389+ , "alias" .= _actAlias
390+ , "type" .= _actData
353391 ]
354392
355393data API = API
@@ -359,25 +397,25 @@ data API = API
359397 }
360398
361399instance ToJSON API where
362− toJSON (API n d as) = object
363− [ "name" .= Syn n
364− , "decl" .= d
365− , "actions" .= Map.elems as
400+ toJSON API {..} = object
401+ [ "name" .= Syn _apiName
402+ , "decl" .= _apiDecl
403+ , "actions" .= Map.elems _apiActions
366404 ]
367405
368−data Method = Method
406+data Method a = Method
369407 { _mId :: Text
370408 , _mPath :: Text
371409 , _mMethod :: Text
372410 , _mDescription :: Maybe Help
373− , _mParameters :: Map Local Param
411+ , _mParameters :: Map Local (Param a)
374412 , _mParameterOrder :: [Local]
375413 , _mScopes :: [Text]
376414 , _mRequest :: Maybe Global
377415 , _mResponse :: Maybe Global
378− } deriving (Generic)
416+ } deriving (Generic, Functor, Foldable, Traversable)
379417
380−instance FromJSON Method where
418+instance FromJSON a => FromJSON (Method a) where
381419 parseJSON = withObject "method" $ \o -> Method
382420 <$> o .: "id"
383421 <*> o .: "path"
@@ -392,18 +430,17 @@ instance FromJSON Method where
392430 ref o k = Just <$> (o .: k >>= (.: "$ref"))
393431 <|> pure Nothing
394432
395−deriveToJSON (js "_m") ''Method
433+data Resource a
434+ = Top (Map Local (Resource a))
435+ | Sub (Map Local (Method a))
436+ deriving (Functor, Foldable, Traversable)
396437
397−data Resource
398− = Top (Map Local Resource)
399− | Sub (Map Local Method)
400−
401−instance FromJSON Resource where
438+instance FromJSON a => FromJSON (Resource a) where
402439 parseJSON = withObject "resource" $ \o ->
403440 Top <$> o .: "resources"
404441 <|> Sub <$> o .: "methods"
405442
406−data Service s r = Service
443+data Service s p r = Service
407444 { _svcLibrary :: Text
408445 , _svcTitle :: Text
409446 , _svcName :: Text
@@ -421,12 +458,12 @@ data Service s r = Service
421458 , _svcServicePath :: Text
422459 , _svcBatchPath :: Text
423460 , _svcAuth :: Maybe Object
424− , _svcParameters :: Map Local Param
425− , _svcSchemas :: Map Id s
461+ , _svcParameters :: p
462+ , _svcSchemas :: s
426463 , _svcApi :: r
427464 } deriving (Generic)
428465
429−instance FromJSON s => FromJSON (Service s Resource) where
466+instance (FromJSON s, FromJSON p, FromJSON r) => FromJSON (Service s p r) where
430467 parseJSON = withObject "service" $ \o -> Service
431468 <$> o .: "library"
432469 <*> o .: "title"
@@ -449,7 +486,7 @@ instance FromJSON s => FromJSON (Service s Resource) where
449486 <*> o .: "schemas"
450487 <*> parseJSON (Object o)
451488
452−instance ToJSON (Service Data API) where
489+instance (ToJSON s, ToJSON p) => ToJSON (Service s p API) where
453490 toJSON s = Object (x <> y)
454491 where
455492 Object x = genericToJSON (js "_svc") s
@@ -457,38 +494,46 @@ instance ToJSON (Service Data API) where
457494 [ "exposedModules" .= exposedModules s
458495 ]
459496
460−svcAbbrev :: Service s r -> Text
497+type Parsed = Service (Map Id (Fix Schema))
498+ (Map Local (Param (Fix Schema)))
499+ (Resource (Fix Schema))
500+
501+type Flattened = Service [Id] [Param Id] (Resource Id)
502+type Typed = Service [Solved] [Param Solved] (Resource Solved)
503+type Printed = Service [Data] () API
504+
505+svcAbbrev :: Service s p r -> Text
461506svcAbbrev = upperHead . renameAbbrev . _svcCanonicalName
462507
463−svcActions :: Service s API -> [NS]
464−svcActions = map _actNS . Map.elems . _apiActions . _svcApi
508+svcActions :: Service s p API -> [Action]
509+svcActions = Map.elems . _apiActions . _svcApi
465510
466−typeImports, prodImports, sumImports, actionImports :: Service s r -> [NS]
511+typeImports, prodImports, sumImports, actionImports :: Service s p r -> [NS]
467512typeImports s = sort ["Network.Google.Prelude", prodNS s, sumNS s]
468513prodImports s = sort ["Network.Google.Prelude", sumNS s]
469514sumImports _ = sort ["Network.Google.Prelude"]
470515actionImports = typeImports
471516
472−tocNS, typesNS, prodNS, sumNS :: Service s r -> NS
517+tocNS, typesNS, prodNS, sumNS :: Service s p r -> NS
473518tocNS s = NS $ "Network" : "Google" : Text.split (== '.') (_svcCanonicalName s)
474519typesNS = (<> "Types") . tocNS
475520prodNS = (<> "Product") . typesNS
476521sumNS = (<> "Sum") . typesNS
477522
478−actionNS :: Service s r -> Local -> Local -> NS
523+actionNS :: Service s p r -> Local -> Local -> NS
479524actionNS s x y = tocNS s <> NS [upperHead (local x), upperHead (local y)]
480525
481−exposedModules :: Service s API -> [NS]
482−exposedModules s = sort (tocNS s : typesNS s : svcActions s)
526+exposedModules :: Service s p API -> [NS]
527+exposedModules s = sort (tocNS s : typesNS s : map _actNS (svcActions s))
483528
484−otherModules :: Service s r -> [NS]
529+otherModules :: Service s p r -> [NS]
485530otherModules s = sort [prodNS s, sumNS s]
486531
487532data Library = Library
488533 { _libName :: Text
489534 , _libTitle :: Text
490535 , _libVersions :: Versions
491− , _libServices :: NonEmpty (Service Data API)
536+ , _libServices :: NonEmpty Printed
492537 }
493538
494539instance ToJSON Library where
@@ -503,7 +548,7 @@ instance ToJSON Library where
503548 , "otherModules" .= concatMap otherModules (NE.toList _libServices)
504549 ]
505550
506−merge :: Versions -> [Service Data API] -> [Library]
551+merge :: Versions -> [Printed] -> [Library]
507552merge v = map go . groupBy (on (==) _svcLibrary)
508553 where
509554 go [x] = mk x
gen/template/action.ede+11
@@ -5,3 +5,14 @@
55{-# OPTIONS_GHC -fno-warn-duplicate-exports #-}
66
77{% include "_include/license.ede" %}
8+--
9+module {{ action.ns }}
10+ (
11+ -- * Resource
12+ {{ action.name }}
13+
14+ ) where
15+
16+{{ action.alias }}
17+
18+{% include "_include/prod.ede" with type = action.type %}