mirror of
https://github.com/Start9Labs/registry.git
synced 2026-03-26 02:11:53 +00:00
adds index/deindex endpoints
This commit is contained in:
7
cli/Main.hs
Normal file
7
cli/Main.hs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
module Main where
|
||||||
|
import Startlude ( IO
|
||||||
|
, pure
|
||||||
|
)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = pure ()
|
||||||
15
package.yaml
15
package.yaml
@@ -43,6 +43,7 @@ dependencies:
|
|||||||
- memory
|
- memory
|
||||||
- monad-logger
|
- monad-logger
|
||||||
- monad-logger-extras
|
- monad-logger-extras
|
||||||
|
- monad-loops
|
||||||
- parallel
|
- parallel
|
||||||
- persistent
|
- persistent
|
||||||
- persistent-postgresql
|
- persistent-postgresql
|
||||||
@@ -102,7 +103,19 @@ executables:
|
|||||||
when:
|
when:
|
||||||
- condition: flag(library-only)
|
- condition: flag(library-only)
|
||||||
buildable: false
|
buildable: false
|
||||||
|
embassy-publish:
|
||||||
|
source-dirs: cli
|
||||||
|
main: Main.hs
|
||||||
|
ghc-options:
|
||||||
|
- -threaded
|
||||||
|
- -rtsopts
|
||||||
|
- -with-rtsopts=-N
|
||||||
|
- -fdefer-typed-holes
|
||||||
|
dependencies:
|
||||||
|
- start9-registry
|
||||||
|
when:
|
||||||
|
- condition: flag(library-only)
|
||||||
|
buildable: false
|
||||||
tests:
|
tests:
|
||||||
start9-registry-test:
|
start9-registry-test:
|
||||||
source-dirs: test
|
source-dirs: test
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ import Conduit ( ConduitT
|
|||||||
, MonadResource
|
, MonadResource
|
||||||
, MonadUnliftIO
|
, MonadUnliftIO
|
||||||
, awaitForever
|
, awaitForever
|
||||||
|
, leftover
|
||||||
, yield
|
, yield
|
||||||
)
|
)
|
||||||
|
import Control.Monad.Loops ( unfoldM )
|
||||||
|
import Data.Conduit ( await )
|
||||||
import Database.Esqueleto.Experimental
|
import Database.Esqueleto.Experimental
|
||||||
( (%)
|
( (%)
|
||||||
, (&&.)
|
, (&&.)
|
||||||
@@ -90,10 +93,10 @@ searchServices (Just category) query = selectSource $ do
|
|||||||
orderBy [desc (services ^. VersionRecordUpdatedAt)]
|
orderBy [desc (services ^. VersionRecordUpdatedAt)]
|
||||||
pure services
|
pure services
|
||||||
|
|
||||||
getPkgData :: (MonadResource m, MonadIO m) => [PkgId] -> ConduitT () (Entity PkgRecord) (ReaderT SqlBackend m) ()
|
getPkgData :: (MonadResource m, MonadIO m) => [PkgId] -> ConduitT () (Entity VersionRecord) (ReaderT SqlBackend m) ()
|
||||||
getPkgData pkgs = selectSource $ do
|
getPkgData pkgs = selectSource $ do
|
||||||
pkgData <- from $ table @PkgRecord
|
pkgData <- from $ table @VersionRecord
|
||||||
where_ (pkgData ^. PkgRecordId `in_` valList (PkgRecordKey <$> pkgs))
|
where_ (pkgData ^. VersionRecordPkgId `in_` valList (PkgRecordKey <$> pkgs))
|
||||||
pure pkgData
|
pure pkgData
|
||||||
|
|
||||||
getPkgDependencyData :: MonadIO m
|
getPkgDependencyData :: MonadIO m
|
||||||
@@ -115,33 +118,34 @@ getPkgDependencyData pkgId pkgVersion = select $ do
|
|||||||
|
|
||||||
zipCategories :: MonadUnliftIO m
|
zipCategories :: MonadUnliftIO m
|
||||||
=> ConduitT
|
=> ConduitT
|
||||||
(Entity PkgRecord, [Entity VersionRecord])
|
(PkgId, [Entity VersionRecord])
|
||||||
(Entity PkgRecord, [Entity VersionRecord], [Entity Category])
|
(PkgId, [Entity VersionRecord], [Entity Category])
|
||||||
(ReaderT SqlBackend m)
|
(ReaderT SqlBackend m)
|
||||||
()
|
()
|
||||||
zipCategories = awaitForever $ \(pkg, vers) -> do
|
zipCategories = awaitForever $ \(pkg, vers) -> do
|
||||||
let pkgDbId = entityKey pkg
|
|
||||||
raw <- lift $ select $ do
|
raw <- lift $ select $ do
|
||||||
(sc :& cat) <-
|
(sc :& cat) <-
|
||||||
from
|
from
|
||||||
$ table @PkgCategory
|
$ table @PkgCategory
|
||||||
`innerJoin` table @Category
|
`innerJoin` table @Category
|
||||||
`on` (\(sc :& cat) -> sc ^. PkgCategoryCategoryId ==. cat ^. CategoryId)
|
`on` (\(sc :& cat) -> sc ^. PkgCategoryCategoryId ==. cat ^. CategoryId)
|
||||||
where_ (sc ^. PkgCategoryPkgId ==. val pkgDbId)
|
where_ (sc ^. PkgCategoryPkgId ==. val (PkgRecordKey pkg))
|
||||||
pure cat
|
pure cat
|
||||||
yield (pkg, vers, raw)
|
yield (pkg, vers, raw)
|
||||||
|
|
||||||
zipVersions :: MonadUnliftIO m
|
collateVersions :: MonadUnliftIO m
|
||||||
=> ConduitT (Entity PkgRecord) (Entity PkgRecord, [Entity VersionRecord]) (ReaderT SqlBackend m) ()
|
=> ConduitT (Entity VersionRecord) (PkgId, [Entity VersionRecord]) (ReaderT SqlBackend m) ()
|
||||||
zipVersions = awaitForever $ \pkg -> do
|
collateVersions = awaitForever $ \v0 -> do
|
||||||
let appDbId = entityKey pkg
|
let pkg = unPkgRecordKey . versionRecordPkgId $ entityVal v0
|
||||||
res <- lift $ select $ do
|
let pull = do
|
||||||
v <- from $ table @VersionRecord
|
mvn <- await
|
||||||
where_ $ v ^. VersionRecordPkgId ==. val appDbId
|
case mvn of
|
||||||
-- first value in list will be latest version
|
Nothing -> pure Nothing
|
||||||
orderBy [desc (v ^. VersionRecordNumber)]
|
Just vn -> do
|
||||||
pure v
|
let pkg' = unPkgRecordKey . versionRecordPkgId $ entityVal vn
|
||||||
yield (pkg, res)
|
if pkg == pkg' then pure (Just vn) else leftover vn $> Nothing
|
||||||
|
ls <- unfoldM pull
|
||||||
|
yield (pkg, v0 : ls)
|
||||||
|
|
||||||
zipDependencyVersions :: (Monad m, MonadIO m)
|
zipDependencyVersions :: (Monad m, MonadIO m)
|
||||||
=> (Entity PkgDependency, Entity PkgRecord)
|
=> (Entity PkgDependency, Entity PkgRecord)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
{-# LANGUAGE QuasiQuotes #-}
|
||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
|
||||||
module Handler.Admin where
|
module Handler.Admin where
|
||||||
|
|
||||||
import Conduit ( (.|)
|
import Conduit ( (.|)
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
{-# LANGUAGE TemplateHaskell #-}
|
{-# LANGUAGE TemplateHaskell #-}
|
||||||
{-# LANGUAGE TupleSections #-}
|
{-# LANGUAGE TupleSections #-}
|
||||||
{-# LANGUAGE TypeApplications #-}
|
{-# LANGUAGE TypeApplications #-}
|
||||||
|
{-# OPTIONS_GHC -Wno-unrecognised-pragmas #-}
|
||||||
|
{-# HLINT ignore "Redundant <$>" #-}
|
||||||
|
|
||||||
module Handler.Marketplace where
|
module Handler.Marketplace where
|
||||||
|
|
||||||
@@ -66,14 +68,14 @@ import Database.Esqueleto.Experimental
|
|||||||
, select
|
, select
|
||||||
, table
|
, table
|
||||||
)
|
)
|
||||||
import Database.Marketplace ( fetchAllAppVersions
|
import Database.Marketplace ( collateVersions
|
||||||
|
, fetchAllAppVersions
|
||||||
, fetchLatestApp
|
, fetchLatestApp
|
||||||
, getPkgData
|
, getPkgData
|
||||||
, getPkgDependencyData
|
, getPkgDependencyData
|
||||||
, searchServices
|
, searchServices
|
||||||
, zipCategories
|
, zipCategories
|
||||||
, zipDependencyVersions
|
, zipDependencyVersions
|
||||||
, zipVersions
|
|
||||||
)
|
)
|
||||||
import Database.Persist ( PersistUniqueRead(getBy)
|
import Database.Persist ( PersistUniqueRead(getBy)
|
||||||
, insertUnique
|
, insertUnique
|
||||||
@@ -98,7 +100,7 @@ import Lib.Types.Emver ( Version
|
|||||||
import Model ( Category(..)
|
import Model ( Category(..)
|
||||||
, EntityField(..)
|
, EntityField(..)
|
||||||
, EosHash(EosHash, eosHashHash)
|
, EosHash(EosHash, eosHashHash)
|
||||||
, Key(unPkgRecordKey)
|
, Key(PkgRecordKey, unPkgRecordKey)
|
||||||
, OsVersion(..)
|
, OsVersion(..)
|
||||||
, PkgRecord(..)
|
, PkgRecord(..)
|
||||||
, Unique(UniqueVersion)
|
, Unique(UniqueVersion)
|
||||||
@@ -194,7 +196,7 @@ getEosR = do
|
|||||||
spec <- getVersionSpecFromQuery
|
spec <- getVersionSpecFromQuery
|
||||||
root <- getsYesod $ (</> "eos") . resourcesDir . appSettings
|
root <- getsYesod $ (</> "eos") . resourcesDir . appSettings
|
||||||
subdirs <- listDirectory root
|
subdirs <- listDirectory root
|
||||||
let (failures, successes) = partitionEithers $ (Atto.parseOnly parseVersion . T.pack) <$> subdirs
|
let (failures, successes) = partitionEithers $ Atto.parseOnly parseVersion . T.pack <$> subdirs
|
||||||
for_ failures $ \f -> $logWarn [i|Emver Parse Failure for EOS: #{f}|]
|
for_ failures $ \f -> $logWarn [i|Emver Parse Failure for EOS: #{f}|]
|
||||||
let mVersion = headMay . sortOn Down . filter (`satisfies` spec) $ successes
|
let mVersion = headMay . sortOn Down . filter (`satisfies` spec) $ successes
|
||||||
case mVersion of
|
case mVersion of
|
||||||
@@ -254,7 +256,7 @@ getPackageListR = do
|
|||||||
runDB
|
runDB
|
||||||
$ runConduit
|
$ runConduit
|
||||||
$ searchServices category query
|
$ searchServices category query
|
||||||
.| zipVersions
|
.| collateVersions
|
||||||
.| zipCategories
|
.| zipCategories
|
||||||
-- empty list since there are no requested packages in this case
|
-- empty list since there are no requested packages in this case
|
||||||
.| filterLatestVersionFromSpec []
|
.| filterLatestVersionFromSpec []
|
||||||
@@ -269,7 +271,7 @@ getPackageListR = do
|
|||||||
-- TODO could probably be better with sequenceConduits
|
-- TODO could probably be better with sequenceConduits
|
||||||
. runConduit
|
. runConduit
|
||||||
$ getPkgData (packageReqId <$> packages')
|
$ getPkgData (packageReqId <$> packages')
|
||||||
.| zipVersions
|
.| collateVersions
|
||||||
.| zipCategories
|
.| zipCategories
|
||||||
.| filterLatestVersionFromSpec vMap
|
.| filterLatestVersionFromSpec vMap
|
||||||
.| filterPkgOsCompatible osPredicate
|
.| filterPkgOsCompatible osPredicate
|
||||||
@@ -343,16 +345,16 @@ getPackageListR = do
|
|||||||
, Version
|
, Version
|
||||||
, [(Key PkgRecord, Text, Version)]
|
, [(Key PkgRecord, Text, Version)]
|
||||||
)
|
)
|
||||||
getPackageDependencies osPredicate PackageMetadata { packageMetadataPkgRecord = pkg, packageMetadataPkgVersionRecords = pkgVersions, packageMetadataPkgCategories = pkgCategories, packageMetadataPkgVersion = pkgVersion }
|
getPackageDependencies osPredicate PackageMetadata { packageMetadataPkgId = pkg, packageMetadataPkgVersionRecords = pkgVersions, packageMetadataPkgCategories = pkgCategories, packageMetadataPkgVersion = pkgVersion }
|
||||||
= do
|
= do
|
||||||
let pkgId = entityKey pkg
|
let pkgId = PkgRecordKey pkg
|
||||||
let pkgVersions' = versionRecordNumber . entityVal <$> pkgVersions
|
let pkgVersions' = versionRecordNumber . entityVal <$> pkgVersions
|
||||||
let pkgCategories' = entityVal <$> pkgCategories
|
let pkgCategories' = entityVal <$> pkgCategories
|
||||||
pkgDepInfo <- getPkgDependencyData pkgId pkgVersion
|
pkgDepInfo <- getPkgDependencyData pkgId pkgVersion
|
||||||
pkgDepInfoWithVersions <- traverse zipDependencyVersions pkgDepInfo
|
pkgDepInfoWithVersions <- traverse zipDependencyVersions pkgDepInfo
|
||||||
let compatiblePkgDepInfo = fmap (filterDependencyOsCompatible osPredicate) pkgDepInfoWithVersions
|
let compatiblePkgDepInfo = fmap (filterDependencyOsCompatible osPredicate) pkgDepInfoWithVersions
|
||||||
res <- catMaybes <$> traverse filterDependencyBestVersion compatiblePkgDepInfo
|
res <- catMaybes <$> traverse filterDependencyBestVersion compatiblePkgDepInfo
|
||||||
pure $ (pkgId, pkgCategories', pkgVersions', pkgVersion, res)
|
pure (pkgId, pkgCategories', pkgVersions', pkgVersion, res)
|
||||||
constructPackageListApiRes :: (MonadResource m, MonadReader r m, Has AppSettings r, Has PkgRepo r)
|
constructPackageListApiRes :: (MonadResource m, MonadReader r m, Has AppSettings r, Has PkgRepo r)
|
||||||
=> ( Key PkgRecord
|
=> ( Key PkgRecord
|
||||||
, [Category]
|
, [Category]
|
||||||
@@ -392,4 +394,4 @@ getPackageListR = do
|
|||||||
runConduit $ src .| CL.foldMap id
|
runConduit $ src .| CL.foldMap id
|
||||||
|
|
||||||
basicRender :: RenderRoute a => Route a -> Text
|
basicRender :: RenderRoute a => Route a -> Text
|
||||||
basicRender = TL.toStrict . TB.toLazyText . fold . fmap (mappend (TB.singleton '/') . TB.fromText) . fst . renderRoute
|
basicRender = TL.toStrict . TB.toLazyText . foldMap (mappend (TB.singleton '/') . TB.fromText) . fst . renderRoute
|
||||||
|
|||||||
@@ -129,7 +129,7 @@ instance FromJSON PackageReq where
|
|||||||
packageReqVersion <- o .: "version"
|
packageReqVersion <- o .: "version"
|
||||||
pure PackageReq { .. }
|
pure PackageReq { .. }
|
||||||
data PackageMetadata = PackageMetadata
|
data PackageMetadata = PackageMetadata
|
||||||
{ packageMetadataPkgRecord :: Entity PkgRecord
|
{ packageMetadataPkgId :: PkgId
|
||||||
, packageMetadataPkgVersionRecords :: [Entity VersionRecord]
|
, packageMetadataPkgVersionRecords :: [Entity VersionRecord]
|
||||||
, packageMetadataPkgCategories :: [Entity Category]
|
, packageMetadataPkgCategories :: [Entity Category]
|
||||||
, packageMetadataPkgVersion :: Version
|
, packageMetadataPkgVersion :: Version
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import Data.String.Interpolate.IsString
|
|||||||
import Database.Esqueleto.Experimental
|
import Database.Esqueleto.Experimental
|
||||||
( Entity
|
( Entity
|
||||||
, Key
|
, Key
|
||||||
, entityKey
|
|
||||||
, entityVal
|
, entityVal
|
||||||
)
|
)
|
||||||
import Foundation
|
import Foundation
|
||||||
@@ -40,7 +39,6 @@ import Lib.PkgRepository ( PkgRepo
|
|||||||
import Lib.Types.AppIndex ( PkgId )
|
import Lib.Types.AppIndex ( PkgId )
|
||||||
import Lib.Types.Emver
|
import Lib.Types.Emver
|
||||||
import Model ( Category
|
import Model ( Category
|
||||||
, Key(unPkgRecordKey)
|
|
||||||
, PkgDependency(pkgDependencyDepId, pkgDependencyDepVersionRange)
|
, PkgDependency(pkgDependencyDepId, pkgDependencyDepVersionRange)
|
||||||
, PkgRecord
|
, PkgRecord
|
||||||
, VersionRecord(..)
|
, VersionRecord(..)
|
||||||
@@ -99,10 +97,10 @@ orThrow action other = action >>= \case
|
|||||||
filterPkgOsCompatible :: Monad m => (Version -> Bool) -> ConduitT PackageMetadata PackageMetadata m ()
|
filterPkgOsCompatible :: Monad m => (Version -> Bool) -> ConduitT PackageMetadata PackageMetadata m ()
|
||||||
filterPkgOsCompatible p =
|
filterPkgOsCompatible p =
|
||||||
awaitForever
|
awaitForever
|
||||||
$ \PackageMetadata { packageMetadataPkgRecord = pkg, packageMetadataPkgVersionRecords = versions, packageMetadataPkgCategories = cats, packageMetadataPkgVersion = requestedVersion } ->
|
$ \PackageMetadata { packageMetadataPkgId = pkg, packageMetadataPkgVersionRecords = versions, packageMetadataPkgCategories = cats, packageMetadataPkgVersion = requestedVersion } ->
|
||||||
do
|
do
|
||||||
let compatible = filter (p . versionRecordOsVersion . entityVal) versions
|
let compatible = filter (p . versionRecordOsVersion . entityVal) versions
|
||||||
unless (null compatible) $ yield PackageMetadata { packageMetadataPkgRecord = pkg
|
unless (null compatible) $ yield PackageMetadata { packageMetadataPkgId = pkg
|
||||||
, packageMetadataPkgVersionRecords = compatible
|
, packageMetadataPkgVersionRecords = compatible
|
||||||
, packageMetadataPkgCategories = cats
|
, packageMetadataPkgCategories = cats
|
||||||
, packageMetadataPkgVersion = requestedVersion
|
, packageMetadataPkgVersion = requestedVersion
|
||||||
@@ -119,18 +117,13 @@ filterDependencyOsCompatible p PackageDependencyMetadata { packageDependencyMeta
|
|||||||
|
|
||||||
filterLatestVersionFromSpec :: (Monad m, MonadLogger m)
|
filterLatestVersionFromSpec :: (Monad m, MonadLogger m)
|
||||||
=> [(PkgId, VersionRange)]
|
=> [(PkgId, VersionRange)]
|
||||||
-> ConduitT
|
-> ConduitT (PkgId, [Entity VersionRecord], [Entity Category]) PackageMetadata m ()
|
||||||
(Entity PkgRecord, [Entity VersionRecord], [Entity Category])
|
filterLatestVersionFromSpec versionMap = awaitForever $ \(pkgId, vs, cats) -> do
|
||||||
PackageMetadata
|
|
||||||
m
|
|
||||||
()
|
|
||||||
filterLatestVersionFromSpec versionMap = awaitForever $ \(a, vs, cats) -> do
|
|
||||||
let pkgId = entityKey a
|
|
||||||
-- if no packages are specified, the VersionRange is implicitly `*`
|
-- if no packages are specified, the VersionRange is implicitly `*`
|
||||||
let spec = fromMaybe Any $ lookup (unPkgRecordKey $ entityKey a) versionMap
|
let spec = fromMaybe Any $ lookup pkgId versionMap
|
||||||
case headMay . sortOn Down $ filter (`satisfies` spec) $ fmap (versionRecordNumber . entityVal) vs of
|
case headMay . sortOn Down $ filter (`satisfies` spec) $ fmap (versionRecordNumber . entityVal) vs of
|
||||||
Nothing -> $logInfo [i|No version for #{pkgId} satisfying #{spec}|]
|
Nothing -> $logInfo [i|No version for #{pkgId} satisfying #{spec}|]
|
||||||
Just v -> yield $ PackageMetadata { packageMetadataPkgRecord = a
|
Just v -> yield $ PackageMetadata { packageMetadataPkgId = pkgId
|
||||||
, packageMetadataPkgVersionRecords = vs
|
, packageMetadataPkgVersionRecords = vs
|
||||||
, packageMetadataPkgCategories = cats
|
, packageMetadataPkgCategories = cats
|
||||||
, packageMetadataPkgVersion = v
|
, packageMetadataPkgVersion = v
|
||||||
|
|||||||
Reference in New Issue
Block a user