@@ -8,10 +8,11 @@ import Prelude hiding (userError)
88import Data.Maybe
99import Data.Char (isSpace)
1010import Data.String (fromString)
11−import Data.List (stripPrefix, isSuffixOf, (\\))
11+import Data.List (stripPrefix, isSuffixOf, (\\), nubBy)
1212import Data.List.Split (splitOn)
1313import Data.List.NonEmpty (NonEmpty(..))
1414import Data.Version
15+import Data.Function (on)
1516import Safe (headMay)
1617
1718import qualified Data.ByteString.Lazy.Char8 as BL
@@ -196,18 +197,35 @@ getResolvedDependencies :: [PackageName] -> PrepareM [(PackageName, Version)]
196197getResolvedDependencies declaredDeps = do
197198 depsBS <- fromString <$> readProcess' "bower" ["list", "--json", "--offline"] ""
198199
199− deps <- catchLeft (parse asBowerResolvedDependencies depsBS)
200− (internalError . JSONError FromBowerList)
200+ -- Check for undeclared dependencies
201+ toplevels <- catchJSON (parse asToplevelDependencies depsBS)
202+ warnUndeclared declaredDeps toplevels
201203
202− warnUndeclared declaredDeps (map fst deps)
204+ deps <- catchJSON (parse asResolvedDependencies depsBS)
203205 handleDeps deps
204206
205207 where
206− asBowerResolvedDependencies ::
207− Parse BowerError [(PackageName, DependencyStatus)]
208− asBowerResolvedDependencies =
209− key "dependencies"
210− (eachInObjectWithKey (parsePackageName . T.unpack) asDependencyStatus)
208+ catchJSON = flip catchLeft (internalError . JSONError FromBowerList)
209+
210+-- | Extracts all dependencies and their versions from
211+-- `bower list --json --offline`
212+asResolvedDependencies :: Parse BowerError [(PackageName, DependencyStatus)]
213+asResolvedDependencies = nubBy ((==) `on` fst) <$> go
214+ where
215+ go =
216+ fmap (fromMaybe []) $
217+ keyMay "dependencies" $
218+ (++) <$> eachInObjectWithKey (parsePackageName . T.unpack)
219+ asDependencyStatus
220+ <*> (concatMap snd <$> eachInObject asResolvedDependencies)
221+
222+-- | Extracts only the top level dependency names from the output of
223+-- `bower list --json --offline`
224+asToplevelDependencies :: Parse BowerError [PackageName]
225+asToplevelDependencies =
226+ fmap (map fst) $
227+ key "dependencies" $
228+ eachInObjectWithKey (parsePackageName . T.unpack) (return ())
211229
212230asDependencyStatus :: Parse e DependencyStatus
213231asDependencyStatus = do