{-# LANGUAGE NoImplicitPrelude, OverloadedStrings, RecordWildCards #-}
{-|
Description: Generate nix expression for 'NP.Package'
-}
module Distribution.Nixpkgs.Nodejs.FromPackage
( genTemplate
) where

import Protolude

import Nix.Expr
import Nix.Expr.Additions

import Distribution.Nixpkgs.Nodejs.Utils (packageKeyToSymbol, attrSetMayStr, attrSetMay)
import qualified Distribution.Nodejs.Package as NP
import qualified Distribution.Nixpkgs.Nodejs.License as NL
import qualified Yarn.Lock.Types as YLT
import qualified Data.Aeson.KeyMap as KeyMap
import qualified Data.Aeson.Key as Key

depsToPkgKeys :: NP.Dependencies -> [YLT.PackageKey]
depsToPkgKeys :: Dependencies -> [PackageKey]
depsToPkgKeys Dependencies
deps =
  Dependencies
deps
  Dependencies -> (Dependencies -> [(Key, Text)]) -> [(Key, Text)]
forall a b. a -> (a -> b) -> b
& Dependencies -> [(Key, Text)]
forall v. KeyMap v -> [(Key, v)]
KeyMap.toList
  [(Key, Text)] -> ((Key, Text) -> (Text, Text)) -> [(Text, Text)]
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (Key -> Text) -> (Key, Text) -> (Text, Text)
forall (p :: * -> * -> *) a b c.
Bifunctor p =>
(a -> b) -> p a c -> p b c
first Key -> Text
Key.toText
  [(Text, Text)] -> ((Text, Text) -> PackageKey) -> [PackageKey]
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> (Text, Text) -> PackageKey
toPkgKey
  where
    toPkgKey :: (Text, Text) -> PackageKey
toPkgKey (Text
k, Text
v) =
      PackageKeyName -> Text -> PackageKey
YLT.PackageKey (Text -> PackageKeyName
NP.parsePackageKeyName Text
k) Text
v

-- | generate a nix expression that translates your package.nix
--
-- and can serve as template for manual adjustments
genTemplate :: Maybe NL.LicensesBySpdxId -> NP.Package -> NExpr
genTemplate :: Maybe LicensesBySpdxId -> Package -> NExpr
genTemplate Maybe LicensesBySpdxId
licSet NP.Package{Bool
Maybe Text
Text
Dependencies
Man
Bin
devDependencies :: Package -> Dependencies
dependencies :: Package -> Dependencies
license :: Package -> Maybe Text
man :: Package -> Man
bin :: Package -> Bin
scripts :: Package -> Dependencies
private :: Package -> Bool
homepage :: Package -> Maybe Text
description :: Package -> Maybe Text
version :: Package -> Text
name :: Package -> Text
devDependencies :: Dependencies
dependencies :: Dependencies
license :: Maybe Text
man :: Man
bin :: Bin
scripts :: Dependencies
private :: Bool
homepage :: Maybe Text
description :: Maybe Text
version :: Text
name :: Text
..} =
  -- reserved for possible future arguments (to prevent breakage)
  [Text] -> Params NExpr
simpleParamSet []
  Params NExpr -> NExpr -> NExpr
==> Text -> Params NExpr
forall r. Text -> Params r
Param Text
nodeDepsSym
  Params NExpr -> NExpr -> NExpr
==> ([Binding NExpr] -> NExpr
mkNonRecSet
        [ Text
"key" Text -> NExpr -> Binding NExpr
$= PackageKeyName -> NExpr
packageKeyToSet (Text -> PackageKeyName
NP.parsePackageKeyName Text
name)
        , Text
"version" Text -> NExpr -> Binding NExpr
$= Text -> NExpr
mkStr Text
version
        , Text
"nodeBuildInputs"  Text -> NExpr -> Binding NExpr
$= (Text -> NExpr -> NExpr -> NExpr
letE Text
"a" (Text -> NExpr
mkSym Text
nodeDepsSym)
                                  (NExpr -> NExpr) -> NExpr -> NExpr
forall a b. (a -> b) -> a -> b
$ [NExpr] -> NExpr
mkList ((PackageKey -> NExpr) -> [PackageKey] -> [NExpr]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
map (Text -> PackageKey -> NExpr
pkgDep Text
"a") [PackageKey]
depPkgKeys))
        , Text
"meta"      Text -> NExpr -> Binding NExpr
$= ([Binding NExpr] -> NExpr
mkNonRecSet
           ([Binding NExpr] -> NExpr) -> [Binding NExpr] -> NExpr
forall a b. (a -> b) -> a -> b
$ Text -> Maybe Text -> [Binding NExpr]
attrSetMayStr Text
"description" Maybe Text
description
          [Binding NExpr] -> [Binding NExpr] -> [Binding NExpr]
forall a. Semigroup a => a -> a -> a
<> Text -> Maybe NExpr -> [Binding NExpr]
attrSetMay    Text
"license" (Text -> LicensesBySpdxId -> NExpr
NL.nodeLicenseToNixpkgs (Text -> LicensesBySpdxId -> NExpr)
-> Maybe Text -> Maybe (LicensesBySpdxId -> NExpr)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Text
license Maybe (LicensesBySpdxId -> NExpr)
-> Maybe LicensesBySpdxId -> Maybe NExpr
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Maybe LicensesBySpdxId
licSet)
          [Binding NExpr] -> [Binding NExpr] -> [Binding NExpr]
forall a. Semigroup a => a -> a -> a
<> Text -> Maybe Text -> [Binding NExpr]
attrSetMayStr Text
"homepage" Maybe Text
homepage)
        ])
  where
    -- TODO: The devDependencies are only needed for the build
    -- and probably also only from packages not stemming from
    -- a npm registry (e.g. a git package). It would be cool
    -- if these dependencies were gone in the final output.
    -- See https://github.com/Profpatsch/yarn2nix/issues/5
    depPkgKeys :: [PackageKey]
depPkgKeys = Dependencies -> [PackageKey]
depsToPkgKeys (Dependencies
dependencies Dependencies -> Dependencies -> Dependencies
forall a. Semigroup a => a -> a -> a
<> Dependencies
devDependencies)
    pkgDep :: Text -> PackageKey -> NExpr
pkgDep Text
depsSym PackageKey
pk = Text -> NExpr
mkSym Text
depsSym NExpr -> Text -> NExpr
!!. PackageKey -> Text
packageKeyToSymbol PackageKey
pk
    nodeDepsSym :: Text
nodeDepsSym = Text
"allDeps"
    packageKeyToSet :: PackageKeyName -> NExpr
packageKeyToSet (YLT.SimplePackageKey Text
n) =
      PackageKeyName -> NExpr
packageKeyToSet (PackageKeyName -> NExpr) -> PackageKeyName -> NExpr
forall a b. (a -> b) -> a -> b
$ Text -> Text -> PackageKeyName
YLT.ScopedPackageKey Text
"" Text
n
    packageKeyToSet (YLT.ScopedPackageKey Text
s Text
n) = [Binding NExpr] -> NExpr
mkNonRecSet ([Binding NExpr] -> NExpr) -> [Binding NExpr] -> NExpr
forall a b. (a -> b) -> a -> b
$
      [ Text -> NExpr -> Binding NExpr
bindTo Text
"name"  (NExpr -> Binding NExpr) -> NExpr -> Binding NExpr
forall a b. (a -> b) -> a -> b
$ [StrQ] -> NExpr
mkStrQ [ Text -> StrQ
StrQ Text
n ]
      , Text -> NExpr -> Binding NExpr
bindTo Text
"scope" (NExpr -> Binding NExpr) -> NExpr -> Binding NExpr
forall a b. (a -> b) -> a -> b
$ [StrQ] -> NExpr
mkStrQ [ Text -> StrQ
StrQ Text
s ]
      ]