diff --git a/.gitignore b/.gitignore index 39a52e97b..9fff5192f 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ tunnel.log /static /well-known /.well-known-cache +/.nix-well-known /**/tmp-* /testdata/bigAlloc_*.csv /sessions diff --git a/flake.lock b/flake.lock index f5c74561b..9d1b7a81e 100644 --- a/flake.lock +++ b/flake.lock @@ -1,5 +1,190 @@ { "nodes": { + "HTTP": { + "flake": false, + "locked": { + "lastModified": 1451647621, + "narHash": "sha256-oHIyw3x0iKBexEo49YeUDV1k74ZtyYKGR2gNJXXRxts=", + "owner": "phadej", + "repo": "HTTP", + "rev": "9bc0996d412fef1787449d841277ef663ad9a915", + "type": "github" + }, + "original": { + "owner": "phadej", + "repo": "HTTP", + "type": "github" + } + }, + "HaskellNet-SSL": { + "flake": false, + "locked": { + "lastModified": 1582382981, + "narHash": "sha256-fjw+bKaGrGw9uTUd6fWZCIz24uuSTA1VIeijZ+zSq/M=", + "ref": "uni2work", + "rev": "40393c938111ac78232dc2c7eec5edb4a22d03e8", + "revCount": 62, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/HaskellNet-SSL.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/HaskellNet-SSL.git" + } + }, + "cabal-32": { + "flake": false, + "locked": { + "lastModified": 1603716527, + "narHash": "sha256-sDbrmur9Zfp4mPKohCD8IDZfXJ0Tjxpmr2R+kg5PpSY=", + "owner": "haskell", + "repo": "cabal", + "rev": "94aaa8e4720081f9c75497e2735b90f6a819b08e", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.2", + "repo": "cabal", + "type": "github" + } + }, + "cabal-34": { + "flake": false, + "locked": { + "lastModified": 1622475795, + "narHash": "sha256-chwTL304Cav+7p38d9mcb+egABWmxo2Aq+xgVBgEb/U=", + "owner": "haskell", + "repo": "cabal", + "rev": "b086c1995cdd616fc8d91f46a21e905cc50a1049", + "type": "github" + }, + "original": { + "owner": "haskell", + "ref": "3.4", + "repo": "cabal", + "type": "github" + } + }, + "cardano-shell": { + "flake": false, + "locked": { + "lastModified": 1608537748, + "narHash": "sha256-PulY1GfiMgKVnBci3ex4ptk2UNYMXqGjJOxcPy2KYT4=", + "owner": "input-output-hk", + "repo": "cardano-shell", + "rev": "9392c75087cb9a3d453998f4230930dea3a95725", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "cardano-shell", + "type": "github" + } + }, + "colonnade": { + "flake": false, + "locked": { + "lastModified": 1592144408, + "narHash": "sha256-bQSOjbn56ZEjzqkC/oqZ331FdxF7tbhJndtXeRqWcq8=", + "ref": "uni2work", + "rev": "f8170266ab25b533576e96715bedffc5aa4f19fa", + "revCount": 153, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/colonnade.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/colonnade.git" + } + }, + "conduit-resumablesink": { + "flake": false, + "locked": { + "lastModified": 1533667275, + "narHash": "sha256-+TR0tYRk1WFQRrFs6oO80jdlfY7OTyB7th7Hi/tDQMw=", + "ref": "uni2work", + "rev": "cbea6159c2975d42f948525e03e12fc390da53c5", + "revCount": 10, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/conduit-resumablesink.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/conduit-resumablesink.git" + } + }, + "cryptoids": { + "flake": false, + "locked": { + "lastModified": 1602592869, + "narHash": "sha256-uhbIaVFXtdWmeDJl0ZDyJnE2Ul3bV324KkaK+ix6USA=", + "ref": "uni2work", + "rev": "130b0dcbf2b09ccdf387b50262f1efbbbf1819e3", + "revCount": 44, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/cryptoids.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/cryptoids.git" + } + }, + "cryptonite": { + "flake": false, + "locked": { + "lastModified": 1624444174, + "narHash": "sha256-sDMA4ej1NIModAt7PQvcgIknI3KwfzcAp9YQUSe4CWw=", + "ref": "uni2work", + "rev": "71a630edaf5f22c464e24fac8d9d310f4055ea1f", + "revCount": 1202, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/cryptonite.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/cryptonite.git" + } + }, + "encoding": { + "flake": false, + "locked": { + "lastModified": 1582400874, + "narHash": "sha256-ukQw4tvjtvqR8HEPgPTSmvtTc6WeXEs3IfCLLNy+YJc=", + "ref": "uni2work", + "rev": "22fc3bb14841d8d50997aa47f1be3852e666f787", + "revCount": 162, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/encoding.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/encoding.git" + } + }, + "esqueleto": { + "flake": false, + "locked": { + "lastModified": 1625584503, + "narHash": "sha256-kgNcNKODv4xkmS6+MKDAVDpbL/IQ5Imucst0uV4HzYU=", + "ref": "uni2work", + "rev": "b9987d94af9d7403eded8ca75ad761eb7fc06e4c", + "revCount": 697, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/esqueleto.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/esqueleto.git" + } + }, "flake-utils": { "locked": { "lastModified": 1623875721, @@ -11,31 +196,396 @@ }, "original": { "owner": "numtide", - "ref": "master", "repo": "flake-utils", "type": "github" } }, + "fontawesome-token": { + "flake": false, + "locked": { + "narHash": "sha256-XABvCxD/7zXRyyR01dr5IvK+8A0VoibiVUS5ZAU+f+o=", + "path": "/etc/fontawesome-token", + "type": "path" + }, + "original": { + "path": "/etc/fontawesome-token", + "type": "path" + } + }, + "ghc-8.6.5-iohk": { + "flake": false, + "locked": { + "lastModified": 1600920045, + "narHash": "sha256-DO6kxJz248djebZLpSzTGD6s8WRpNI9BTwUeOf5RwY8=", + "owner": "input-output-hk", + "repo": "ghc", + "rev": "95713a6ecce4551240da7c96b6176f980af75cae", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "ref": "release/8.6.5-iohk", + "repo": "ghc", + "type": "github" + } + }, + "hackage": { + "flake": false, + "locked": { + "lastModified": 1629940355, + "narHash": "sha256-o9/U8R/JtyHIcxhMLaWYP+D/52B6LH/ikCyNZ7+mymI=", + "owner": "input-output-hk", + "repo": "hackage.nix", + "rev": "429deb2a137084c011310bad92f4cecf244f2fc2", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "hackage.nix", + "type": "github" + } + }, + "haskell-nix": { + "inputs": { + "HTTP": "HTTP", + "cabal-32": "cabal-32", + "cabal-34": "cabal-34", + "cardano-shell": "cardano-shell", + "flake-utils": "flake-utils", + "ghc-8.6.5-iohk": "ghc-8.6.5-iohk", + "hackage": "hackage", + "hpc-coveralls": "hpc-coveralls", + "nix-tools": "nix-tools", + "nixpkgs": "nixpkgs", + "nixpkgs-2003": "nixpkgs-2003", + "nixpkgs-2009": "nixpkgs-2009", + "nixpkgs-2105": "nixpkgs-2105", + "nixpkgs-unstable": "nixpkgs-unstable", + "old-ghc-nix": "old-ghc-nix", + "stackage": "stackage" + }, + "locked": { + "lastModified": 1629940530, + "narHash": "sha256-cf/bshYWloj+rJSmOcFokN6Rs1lpFkiECKpykN3JBH8=", + "owner": "input-output-hk", + "repo": "haskell.nix", + "rev": "5fcd4faf98fc8ca8287e2c7bc1fff71dfd340f1f", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "haskell.nix", + "type": "github" + } + }, + "hpc-coveralls": { + "flake": false, + "locked": { + "lastModified": 1607498076, + "narHash": "sha256-8uqsEtivphgZWYeUo5RDUhp6bO9j2vaaProQxHBltQk=", + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "rev": "14df0f7d229f4cd2e79f8eabb1a740097fdfa430", + "type": "github" + }, + "original": { + "owner": "sevanspowell", + "repo": "hpc-coveralls", + "type": "github" + } + }, + "ldap-client": { + "flake": false, + "locked": { + "lastModified": 1582401733, + "narHash": "sha256-StLj8BnQqbl8fnE+xWlSOScVRGnl19cv8d1CBZ29O0k=", + "ref": "uni2work", + "rev": "01afaf599ba6f8a9d804c269e91d3190b249d3f0", + "revCount": 61, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/ldap-client.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/ldap-client.git" + } + }, + "memcached-binary": { + "flake": false, + "locked": { + "lastModified": 1582403725, + "narHash": "sha256-40BNhNNYC/B4u16dKwBrkk5hmhncq805YC4y1aGFRqs=", + "ref": "uni2work", + "rev": "b7071df50bad3a251a544b984e4bf98fa09b8fae", + "revCount": 28, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/memcached-binary.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/memcached-binary.git" + } + }, + "minio-hs": { + "flake": false, + "locked": { + "lastModified": 1597069863, + "narHash": "sha256-JmMajaLT4+zt+w2koDkaloFL8ugmrQBlcYKj+78qn9M=", + "ref": "uni2work", + "rev": "42103ab247057c04c8ce7a83d9d4c160713a3df1", + "revCount": 197, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/minio-hs.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/minio-hs.git" + } + }, + "nix-tools": { + "flake": false, + "locked": { + "lastModified": 1626997434, + "narHash": "sha256-1judQmP298ao6cGUNxcGhcAXHOnA9qSLvWk/ZtoUL7w=", + "owner": "input-output-hk", + "repo": "nix-tools", + "rev": "c8c5e6a6fbb12a73598d1a434984a36e880ce3cf", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "nix-tools", + "type": "github" + } + }, "nixpkgs": { "locked": { - "lastModified": 1624788075, - "narHash": "sha256-xzO2aL5gGejNvey2jKGnbnFXbo99pdytlY5FF/IhvAE=", + "lastModified": 1624291665, + "narHash": "sha256-kNkaoa3dai9WOi7fsPklCCWZ8hRAkXx0ZUhpYKShyUk=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "4ba70da807359ed01d662763a96c7b442762e5ef", + "rev": "3c6f3f84af60a8ed5b8a79cf3026b7630fcdefb8", "type": "github" }, "original": { "owner": "NixOS", - "ref": "master", + "ref": "nixpkgs-20.09-darwin", "repo": "nixpkgs", "type": "github" } }, + "nixpkgs-2003": { + "locked": { + "lastModified": 1620055814, + "narHash": "sha256-8LEHoYSJiL901bTMVatq+rf8y7QtWuZhwwpKE2fyaRY=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "1db42b7fe3878f3f5f7a4f2dc210772fd080e205", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.03-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2009": { + "locked": { + "lastModified": 1624271064, + "narHash": "sha256-qns/uRW7MR2EfVf6VEeLgCsCp7pIOjDeR44JzTF09MA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "46d1c3f28ca991601a53e9a14fdd53fcd3dd8416", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-20.09-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-2105": { + "locked": { + "lastModified": 1624291665, + "narHash": "sha256-kNkaoa3dai9WOi7fsPklCCWZ8hRAkXx0ZUhpYKShyUk=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "3c6f3f84af60a8ed5b8a79cf3026b7630fcdefb8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-21.05-darwin", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1628785280, + "narHash": "sha256-2B5eMrEr6O8ff2aQNeVxTB+9WrGE80OB4+oM6T7fOcc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6525bbc06a39f26750ad8ee0d40000ddfdc24acb", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "old-ghc-nix": { + "flake": false, + "locked": { + "lastModified": 1621819714, + "narHash": "sha256-EJCnYQSWk7FRLwS0lZgTWIiQ6pcvDX1VuD6LGD4Uwzs=", + "owner": "angerman", + "repo": "old-ghc-nix", + "rev": "f089a6f090cdb35fcf95f865fc6a31ba6b3ac4eb", + "type": "github" + }, + "original": { + "owner": "angerman", + "ref": "master2", + "repo": "old-ghc-nix", + "type": "github" + } + }, "root": { "inputs": { - "flake-utils": "flake-utils", - "nixpkgs": "nixpkgs" + "HaskellNet-SSL": "HaskellNet-SSL", + "colonnade": "colonnade", + "conduit-resumablesink": "conduit-resumablesink", + "cryptoids": "cryptoids", + "cryptonite": "cryptonite", + "encoding": "encoding", + "esqueleto": "esqueleto", + "flake-utils": [ + "haskell-nix", + "flake-utils" + ], + "fontawesome-token": "fontawesome-token", + "haskell-nix": "haskell-nix", + "ldap-client": "ldap-client", + "memcached-binary": "memcached-binary", + "minio-hs": "minio-hs", + "nixpkgs": [ + "haskell-nix", + "nixpkgs-unstable" + ], + "serversession": "serversession", + "tail-DateTime": "tail-DateTime", + "xss-sanitize": "xss-sanitize", + "yesod": "yesod", + "zip-stream": "zip-stream" + } + }, + "serversession": { + "flake": false, + "locked": { + "lastModified": 1624794082, + "narHash": "sha256-mixhAsgOq0iiAhOcZfFSyl8CwS7utaKeZBz/Lix16hk=", + "ref": "uni2work", + "rev": "b9d76def10da1260c7f6aa82bda32111f37a952b", + "revCount": 174, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/serversession.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/serversession.git" + } + }, + "stackage": { + "flake": false, + "locked": { + "lastModified": 1629940472, + "narHash": "sha256-LFrNC25OpNoS6dGG5om+UGP8YdYjp01Qm6cenbemaVg=", + "owner": "input-output-hk", + "repo": "stackage.nix", + "rev": "c50dd0527babf85818cc67a7099e532e453752db", + "type": "github" + }, + "original": { + "owner": "input-output-hk", + "repo": "stackage.nix", + "type": "github" + } + }, + "tail-DateTime": { + "flake": false, + "locked": { + "lastModified": 1576249828, + "narHash": "sha256-90okKfi5Nf5xw+IFsPXzdykdboLMbOYHmUVyNZS65Go=", + "ref": "uni2work", + "rev": "ef1237569ff22667acb64a9dfd64682ee55817eb", + "revCount": 132, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git" + } + }, + "xss-sanitize": { + "flake": false, + "locked": { + "lastModified": 1602593438, + "narHash": "sha256-2jAHm79x8f+ygGHq9gipF3h8+eMT7eCxVMOGMc/brKE=", + "ref": "uni2work", + "rev": "dc928c3a456074b8777603bea20e81937321777f", + "revCount": 114, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/xss-sanitize.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/xss-sanitize.git" + } + }, + "yesod": { + "flake": false, + "locked": { + "lastModified": 1625061191, + "narHash": "sha256-K0X2MwUStChml1DlJ7t4yBMDwrMe6j/780nJtSy9Hss=", + "ref": "uni2work", + "rev": "a59f63e0336ee61f7a90b8778e9147305d3127bb", + "revCount": 5053, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/yesod.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/yesod.git" + } + }, + "zip-stream": { + "flake": false, + "locked": { + "lastModified": 1599734754, + "narHash": "sha256-gqIlgj2dxVkqEMafuVL+dqZPoV+WLpOJwz1NhsKnH64=", + "ref": "uni2work", + "rev": "843683d024f767de236f74d24a3348f69181a720", + "revCount": 39, + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/zip-stream.git" + }, + "original": { + "ref": "uni2work", + "type": "git", + "url": "ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/zip-stream.git" } } }, diff --git a/flake.nix b/flake.nix index bd6be4594..a05be898a 100644 --- a/flake.nix +++ b/flake.nix @@ -1,32 +1,246 @@ { - inputs = { - nixpkgs = { - type = "github"; - owner = "NixOS"; - repo = "nixpkgs"; - ref = "master"; - }; - flake-utils = { - type = "github"; - owner = "numtide"; - repo = "flake-utils"; - ref = "master"; - }; + inputs.haskell-nix.url = "github:input-output-hk/haskell.nix"; + inputs.nixpkgs.follows = "haskell-nix/nixpkgs-unstable"; + inputs.flake-utils.follows = "haskell-nix/flake-utils"; + + inputs.encoding = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/encoding.git?ref=uni2work"; + flake = false; + }; + inputs.memcached-binary = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/memcached-binary.git?ref=uni2work"; + flake = false; + }; + inputs.conduit-resumablesink = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/conduit-resumablesink.git?ref=uni2work"; + flake = false; + }; + inputs.HaskellNet-SSL = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/HaskellNet-SSL.git?ref=uni2work"; + flake = false; + }; + inputs.ldap-client = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/ldap-client.git?ref=uni2work"; + flake = false; + }; + inputs.serversession = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/serversession.git?ref=uni2work"; + flake = false; + }; + inputs.xss-sanitize = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/xss-sanitize.git?ref=uni2work"; + flake = false; + }; + inputs.colonnade = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/colonnade.git?ref=uni2work"; + flake = false; + }; + inputs.minio-hs = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/minio-hs.git?ref=uni2work"; + flake = false; + }; + inputs.cryptoids = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/cryptoids.git?ref=uni2work"; + flake = false; + }; + inputs.zip-stream = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/zip-stream.git?ref=uni2work"; + flake = false; + }; + inputs.yesod = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/yesod.git?ref=uni2work"; + flake = false; + }; + inputs.cryptonite = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/cryptonite.git?ref=uni2work"; + flake = false; + }; + inputs.esqueleto = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/esqueleto.git?ref=uni2work"; + flake = false; }; - outputs = { self, nixpkgs, flake-utils, ... }: flake-utils.lib.eachDefaultSystem + inputs.tail-DateTime = { + url = "git+ssh://git@gitlab2.rz.ifi.lmu.de/uni2work/tail.DateTime.git?ref=uni2work"; + flake = false; + }; + inputs.fontawesome-token = { + url = "path:/etc/fontawesome-token"; + flake = false; + }; + + outputs = inputs@{ self, nixpkgs, flake-utils, haskell-nix, ... }: flake-utils.lib.eachSystem ["x86_64-linux"] (system: let pkgs = import nixpkgs { - inherit system; + inherit system overlays; config.allowUnfree = true; }; - overlay = import ./nix/maildev; + overlays = + let + frontendSource = pkgs.lib.sourceByRegex ./. [ + "^(assets|frontend)(/.*)?$" + "^config(/(favicon\.json|robots\.txt))?$" + "^(webpack|postcss)\.config\.js$" + "^(package|jsconfig)\.json$" + "^\.babelrc$" + ]; + backendSource = pkgs.lib.sourceByRegex ./. [ + "^(package|stack-flake)\.yaml$" + "^stack\.yaml\.lock$" + "^(assets|app|hlint|load|messages|models|src|templates|test|testdata|wflint)(/.*)?$" + "^config(/(archive-types|mimetypes|personalised-sheet-files-collate|settings\.yml|submission-blacklist|test-settings\.yml|video-types|wordlist\.txt))?$" + "^routes$" + ]; + in [ + (import ./nix/maildev) + haskell-nix.overlay + (final: prev: { + uniworx-node-dependencies = (prev.callPackage ./nix/frontend {}).nodeDependencies.override (oldArgs: { + dependencies = + let + srcOverrides = { + "tail.datetime" = inputs.tail-DateTime; + "@fortawesome/fontawesome-pro" = prev.fetchurl { + url = "https://npm.fontawesome.com/@fortawesome/fontawesome-pro/-/5.14.0/fontawesome-pro-5.14.0.tgz"; + curlOpts = "-H @${prev.writeText "headers.txt" "Authorization: Bearer ${builtins.readFile inputs.fontawesome-token}"}"; + hash = "sha256-jGvPrTKKL0rCWRZUEnJEmrOdHyQYs3M5709B1hjmFw4="; + }; + }; + in map (dep: dep // { src = srcOverrides."${dep.packageName}" or dep.src; }) oldArgs.dependencies; + }); + }) + (final: prev: { + uniworx-well-known = prev.stdenv.mkDerivation { + name = "uniworx-well-known"; + src = frontendSource; - inherit (pkgs.lib) recursiveUpdate; + phases = ["unpackPhase" "buildPhase" "installPhase" "fixupPhase"]; + + buildPhase = '' + ln -s ${prev.uniworx-node-dependencies}/lib/node_modules ./node_modules + export PATH="${prev.uniworx-node-dependencies}/bin:${prev.exiftool}/bin:$PATH" + webpack --progress + ''; + + installPhase = '' + mkdir -p $out + cp -r --reflink=auto well-known $out/.nix-well-known + ''; + + outputHashMode = "recursive"; + outputHashAlgo = "sha256"; + outputHash = "tDaffdAT5EGPKdDJ2ovo9XSGdV48W3Efqe+iBmakh6g="; + }; + }) + (final: prev: { + uniworx-frontend = prev.stdenv.mkDerivation { + name = "uniworx-frontend"; + srcs = [frontendSource prev.uniworx-well-known]; + sourceRoot = "source"; + + phases = ["unpackPhase" "buildPhase" "installPhase"]; + + postUnpack = '' + cp -pr --reflink=auto uniworx-well-known/. $sourceRoot + ''; + + buildPhase = '' + ln -s ${prev.uniworx-node-dependencies}/lib/node_modules ./node_modules + export PATH="${prev.uniworx-node-dependencies}/bin:$PATH" + webpack --progress + ''; + + installPhase = '' + mkdir -p $out $out/config + cp -r --reflink=auto well-known static $out + cp -r --reflink=auto config/webpack.yml $out/config + ''; + }; + }) + (final: prev: { + uniworx = final.haskell-nix.stackProject { + src = prev.stdenv.mkDerivation { + name = "uniworx-src"; + src = backendSource; + + phases = ["unpackPhase" "patchPhase" "installPhase"]; + + patchPhase = '' + substitute stack-flake.yaml stack.yaml \ + ${prev.lib.concatMapStringsSep " \\\n" (pkgName: "--replace @${pkgName}@ ${inputs."${pkgName}"}") haskellInputs} + ''; + + installPhase = '' + mkdir -p $out + cp -pr --reflink=auto ./. $out + ''; + }; + compiler-nix-name = "ghc8104"; + # stack-sha256 = "1n7z294ldv2rjkfj1vs3kqmnbp34m2scrmyrp5kwmga9vp86fd9z"; + modules = [ + { + packages = { + encoding.src = inputs.encoding; + memcached-binary.src = inputs.memcached-binary; + conduit-resumablesink.src = inputs.conduit-resumablesink; + HaskellNet-SSL.src = inputs.HaskellNet-SSL; + ldap-client.src = inputs.ldap-client; + serversession.src = "${inputs.serversession}/serversession"; + serversession-backend-acid-state.src = "${inputs.serversession}/serversession-backend-acid-state"; + xss-sanitize.src = inputs.xss-sanitize; + colonnade.src = "${inputs.colonnade}/colonnade"; + minio-hs.src = inputs.minio-hs; + cryptoids-class.src = "${inputs.cryptoids}/cryptoids-class"; + cryptoids-types.src = "${inputs.cryptoids}/cryptoids-types"; + cryptoids.src = "${inputs.cryptoids}/cryptoids"; + filepath-crypto.src = "${inputs.cryptoids}/filepath-crypto"; + uuid-crypto.src = "${inputs.cryptoids}/uuid-crypto"; + zip-stream.src = inputs.zip-stream; + yesod.src = "${inputs.yesod}/yesod"; + yesod-core.src = "${inputs.yesod}/yesod-core"; + yesod-static.src = "${inputs.yesod}/yesod-static"; + yesod-persistent.src = "${inputs.yesod}/yesod-persistent"; + yesod-form.src = "${inputs.yesod}/yesod-form"; + yesod-auth.src = "${inputs.yesod}/yesod-auth"; + yesod-test.src = "${inputs.yesod}/yesod-test"; + cryptonite.src = inputs.cryptonite; + esqueleto.src = inputs.esqueleto; + }; + } + { + packages.uniworx = { + postUnpack = '' + cp -pr --reflink=auto ${prev.uniworx-frontend}/. $sourceRoot + chmod a+w -R $sourceRoot + ''; + preBuild = '' + export TZDIR=${final.tzdata}/share/zoneinfo + ''; + components.library.build-tools = with final.pkgs; [ llvm_9 ]; + components.exes.uniworx.build-tools = with final.pkgs; [ llvm_9 ]; + components.exes.uniworxdb.build-tools = with final.pkgs; [ llvm_9 ]; + components.exes.uniworxload.build-tools = with final.pkgs; [ llvm_9 ]; + components.exes.uniworx-wflint.build-tools = with final.pkgs; [ llvm_9 ]; + components.tests.yesod.build-tools = with final.pkgs; [ llvm_9 ]; + components.tests.hlint.build-tools = with final.pkgs; [ llvm_9 ]; + }; + } + ]; + }; + }) + ]; + haskellInputs = ["encoding" "memcached-binary" "conduit-resumablesink" "HaskellNet-SSL" "ldap-client" "serversession" "xss-sanitize" "colonnade" "minio-hs" "cryptoids" "zip-stream" "yesod" "cryptonite" "esqueleto"]; + + haskellFlake = pkgs.uniworx.flake {}; in { - devShell = import ./shell.nix { pkgs = self.legacyPackages.${system}; }; + packages = haskellFlake.packages // { inherit (pkgs) uniworx-node-dependencies uniworx-well-known uniworx-frontend; inherit (pkgs.uniworx.stack-nix.passthru) calculateMaterializedSha; }; + inherit (haskellFlake) checks apps; + + devShell = import ./shell.nix { inherit pkgs; }; - legacyPackages = recursiveUpdate (overlay self.legacyPackages.${system} pkgs) pkgs; + legacyPackages = pkgs; + + defaultPackage = haskellFlake.packages."uniworx:exe:uniworx"; } ); } diff --git a/nix/frontend/default.nix b/nix/frontend/default.nix new file mode 100644 index 000000000..f929727d5 --- /dev/null +++ b/nix/frontend/default.nix @@ -0,0 +1,17 @@ +# This file has been generated by node2nix 1.9.0. Do not edit! + +{pkgs ? import { + inherit system; + }, system ? builtins.currentSystem, nodejs ? pkgs."nodejs-14_x"}: + +let + nodeEnv = import ./node-env.nix { + inherit (pkgs) stdenv lib python2 runCommand writeTextFile; + inherit pkgs nodejs; + libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null; + }; +in +import ./node-packages.nix { + inherit (pkgs) fetchurl nix-gitignore stdenv lib fetchgit; + inherit nodeEnv; +} diff --git a/nix/frontend/node-env.nix b/nix/frontend/node-env.nix new file mode 100644 index 000000000..c2b723195 --- /dev/null +++ b/nix/frontend/node-env.nix @@ -0,0 +1,567 @@ +# This file originates from node2nix + +{lib, stdenv, nodejs, python2, pkgs, libtool, runCommand, writeTextFile}: + +let + # Workaround to cope with utillinux in Nixpkgs 20.09 and util-linux in Nixpkgs master + utillinux = if pkgs ? utillinux then pkgs.utillinux else pkgs.util-linux; + + python = if nodejs ? python then nodejs.python else python2; + + # Create a tar wrapper that filters all the 'Ignoring unknown extended header keyword' noise + tarWrapper = runCommand "tarWrapper" {} '' + mkdir -p $out/bin + + cat > $out/bin/tar <> $out/nix-support/hydra-build-products + ''; + }; + + includeDependencies = {dependencies}: + lib.optionalString (dependencies != []) + (lib.concatMapStrings (dependency: + '' + # Bundle the dependencies of the package + mkdir -p node_modules + cd node_modules + + # Only include dependencies if they don't exist. They may also be bundled in the package. + if [ ! -e "${dependency.name}" ] + then + ${composePackage dependency} + fi + + cd .. + '' + ) dependencies); + + # Recursively composes the dependencies of a package + composePackage = { name, packageName, src, dependencies ? [], ... }@args: + builtins.addErrorContext "while evaluating node package '${packageName}'" '' + DIR=$(pwd) + cd $TMPDIR + + unpackFile ${src} + + # Make the base dir in which the target dependency resides first + mkdir -p "$(dirname "$DIR/${packageName}")" + + if [ -f "${src}" ] + then + # Figure out what directory has been unpacked + packageDir="$(find . -maxdepth 1 -type d | tail -1)" + + # Restore write permissions to make building work + find "$packageDir" -type d -exec chmod u+x {} \; + chmod -R u+w "$packageDir" + + # Move the extracted tarball into the output folder + mv "$packageDir" "$DIR/${packageName}" + elif [ -d "${src}" ] + then + # Get a stripped name (without hash) of the source directory. + # On old nixpkgs it's already set internally. + if [ -z "$strippedName" ] + then + strippedName="$(stripHash ${src})" + fi + + # Restore write permissions to make building work + chmod -R u+w "$strippedName" + + # Move the extracted directory into the output folder + mv "$strippedName" "$DIR/${packageName}" + fi + + # Unset the stripped name to not confuse the next unpack step + unset strippedName + + # Include the dependencies of the package + cd "$DIR/${packageName}" + ${includeDependencies { inherit dependencies; }} + cd .. + ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} + ''; + + pinpointDependencies = {dependencies, production}: + let + pinpointDependenciesFromPackageJSON = writeTextFile { + name = "pinpointDependencies.js"; + text = '' + var fs = require('fs'); + var path = require('path'); + + function resolveDependencyVersion(location, name) { + if(location == process.env['NIX_STORE']) { + return null; + } else { + var dependencyPackageJSON = path.join(location, "node_modules", name, "package.json"); + + if(fs.existsSync(dependencyPackageJSON)) { + var dependencyPackageObj = JSON.parse(fs.readFileSync(dependencyPackageJSON)); + + if(dependencyPackageObj.name == name) { + return dependencyPackageObj.version; + } + } else { + return resolveDependencyVersion(path.resolve(location, ".."), name); + } + } + } + + function replaceDependencies(dependencies) { + if(typeof dependencies == "object" && dependencies !== null) { + for(var dependency in dependencies) { + var resolvedVersion = resolveDependencyVersion(process.cwd(), dependency); + + if(resolvedVersion === null) { + process.stderr.write("WARNING: cannot pinpoint dependency: "+dependency+", context: "+process.cwd()+"\n"); + } else { + dependencies[dependency] = resolvedVersion; + } + } + } + } + + /* Read the package.json configuration */ + var packageObj = JSON.parse(fs.readFileSync('./package.json')); + + /* Pinpoint all dependencies */ + replaceDependencies(packageObj.dependencies); + if(process.argv[2] == "development") { + replaceDependencies(packageObj.devDependencies); + } + replaceDependencies(packageObj.optionalDependencies); + + /* Write the fixed package.json file */ + fs.writeFileSync("package.json", JSON.stringify(packageObj, null, 2)); + ''; + }; + in + '' + node ${pinpointDependenciesFromPackageJSON} ${if production then "production" else "development"} + + ${lib.optionalString (dependencies != []) + '' + if [ -d node_modules ] + then + cd node_modules + ${lib.concatMapStrings (dependency: pinpointDependenciesOfPackage dependency) dependencies} + cd .. + fi + ''} + ''; + + # Recursively traverses all dependencies of a package and pinpoints all + # dependencies in the package.json file to the versions that are actually + # being used. + + pinpointDependenciesOfPackage = { packageName, dependencies ? [], production ? true, ... }@args: + '' + if [ -d "${packageName}" ] + then + cd "${packageName}" + ${pinpointDependencies { inherit dependencies production; }} + cd .. + ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} + fi + ''; + + # Extract the Node.js source code which is used to compile packages with + # native bindings + nodeSources = runCommand "node-sources" {} '' + tar --no-same-owner --no-same-permissions -xf ${nodejs.src} + mv node-* $out + ''; + + # Script that adds _integrity fields to all package.json files to prevent NPM from consulting the cache (that is empty) + addIntegrityFieldsScript = writeTextFile { + name = "addintegrityfields.js"; + text = '' + var fs = require('fs'); + var path = require('path'); + + function augmentDependencies(baseDir, dependencies) { + for(var dependencyName in dependencies) { + var dependency = dependencies[dependencyName]; + + // Open package.json and augment metadata fields + var packageJSONDir = path.join(baseDir, "node_modules", dependencyName); + var packageJSONPath = path.join(packageJSONDir, "package.json"); + + if(fs.existsSync(packageJSONPath)) { // Only augment packages that exist. Sometimes we may have production installs in which development dependencies can be ignored + console.log("Adding metadata fields to: "+packageJSONPath); + var packageObj = JSON.parse(fs.readFileSync(packageJSONPath)); + + if(dependency.integrity) { + packageObj["_integrity"] = dependency.integrity; + } else { + packageObj["_integrity"] = "sha1-000000000000000000000000000="; // When no _integrity string has been provided (e.g. by Git dependencies), add a dummy one. It does not seem to harm and it bypasses downloads. + } + + if(dependency.resolved) { + packageObj["_resolved"] = dependency.resolved; // Adopt the resolved property if one has been provided + } else { + packageObj["_resolved"] = dependency.version; // Set the resolved version to the version identifier. This prevents NPM from cloning Git repositories. + } + + if(dependency.from !== undefined) { // Adopt from property if one has been provided + packageObj["_from"] = dependency.from; + } + + fs.writeFileSync(packageJSONPath, JSON.stringify(packageObj, null, 2)); + } + + // Augment transitive dependencies + if(dependency.dependencies !== undefined) { + augmentDependencies(packageJSONDir, dependency.dependencies); + } + } + } + + if(fs.existsSync("./package-lock.json")) { + var packageLock = JSON.parse(fs.readFileSync("./package-lock.json")); + + if(![1, 2].includes(packageLock.lockfileVersion)) { + process.stderr.write("Sorry, I only understand lock file versions 1 and 2!\n"); + process.exit(1); + } + + if(packageLock.dependencies !== undefined) { + augmentDependencies(".", packageLock.dependencies); + } + } + ''; + }; + + # Reconstructs a package-lock file from the node_modules/ folder structure and package.json files with dummy sha1 hashes + reconstructPackageLock = writeTextFile { + name = "addintegrityfields.js"; + text = '' + var fs = require('fs'); + var path = require('path'); + + var packageObj = JSON.parse(fs.readFileSync("package.json")); + + var lockObj = { + name: packageObj.name, + version: packageObj.version, + lockfileVersion: 1, + requires: true, + dependencies: {} + }; + + function augmentPackageJSON(filePath, dependencies) { + var packageJSON = path.join(filePath, "package.json"); + if(fs.existsSync(packageJSON)) { + var packageObj = JSON.parse(fs.readFileSync(packageJSON)); + dependencies[packageObj.name] = { + version: packageObj.version, + integrity: "sha1-000000000000000000000000000=", + dependencies: {} + }; + processDependencies(path.join(filePath, "node_modules"), dependencies[packageObj.name].dependencies); + } + } + + function processDependencies(dir, dependencies) { + if(fs.existsSync(dir)) { + var files = fs.readdirSync(dir); + + files.forEach(function(entry) { + var filePath = path.join(dir, entry); + var stats = fs.statSync(filePath); + + if(stats.isDirectory()) { + if(entry.substr(0, 1) == "@") { + // When we encounter a namespace folder, augment all packages belonging to the scope + var pkgFiles = fs.readdirSync(filePath); + + pkgFiles.forEach(function(entry) { + if(stats.isDirectory()) { + var pkgFilePath = path.join(filePath, entry); + augmentPackageJSON(pkgFilePath, dependencies); + } + }); + } else { + augmentPackageJSON(filePath, dependencies); + } + } + }); + } + } + + processDependencies("node_modules", lockObj.dependencies); + + fs.writeFileSync("package-lock.json", JSON.stringify(lockObj, null, 2)); + ''; + }; + + prepareAndInvokeNPM = {packageName, bypassCache, reconstructLock, npmFlags, production}: + let + forceOfflineFlag = if bypassCache then "--offline" else "--registry http://www.example.com"; + in + '' + # Pinpoint the versions of all dependencies to the ones that are actually being used + echo "pinpointing versions of dependencies..." + source $pinpointDependenciesScriptPath + + # Patch the shebangs of the bundled modules to prevent them from + # calling executables outside the Nix store as much as possible + patchShebangs . + + # Deploy the Node.js package by running npm install. Since the + # dependencies have been provided already by ourselves, it should not + # attempt to install them again, which is good, because we want to make + # it Nix's responsibility. If it needs to install any dependencies + # anyway (e.g. because the dependency parameters are + # incomplete/incorrect), it fails. + # + # The other responsibilities of NPM are kept -- version checks, build + # steps, postprocessing etc. + + export HOME=$TMPDIR + cd "${packageName}" + runHook preRebuild + + ${lib.optionalString bypassCache '' + ${lib.optionalString reconstructLock '' + if [ -f package-lock.json ] + then + echo "WARNING: Reconstruct lock option enabled, but a lock file already exists!" + echo "This will most likely result in version mismatches! We will remove the lock file and regenerate it!" + rm package-lock.json + else + echo "No package-lock.json file found, reconstructing..." + fi + + node ${reconstructPackageLock} + ''} + + node ${addIntegrityFieldsScript} + ''} + + npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} rebuild + + if [ "''${dontNpmInstall-}" != "1" ] + then + # NPM tries to download packages even when they already exist if npm-shrinkwrap is used. + rm -f npm-shrinkwrap.json + + npm ${forceOfflineFlag} --nodedir=${nodeSources} ${npmFlags} ${lib.optionalString production "--production"} install + fi + ''; + + # Builds and composes an NPM package including all its dependencies + buildNodePackage = + { name + , packageName + , version + , dependencies ? [] + , buildInputs ? [] + , production ? true + , npmFlags ? "" + , dontNpmInstall ? false + , bypassCache ? false + , reconstructLock ? false + , preRebuild ? "" + , dontStrip ? true + , unpackPhase ? "true" + , buildPhase ? "true" + , ... }@args: + + let + extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "preRebuild" "unpackPhase" "buildPhase" ]; + in + stdenv.mkDerivation ({ + name = "node_${name}-${version}"; + buildInputs = [ tarWrapper python nodejs ] + ++ lib.optional (stdenv.isLinux) utillinux + ++ lib.optional (stdenv.isDarwin) libtool + ++ buildInputs; + + inherit nodejs; + + inherit dontStrip; # Stripping may fail a build for some package deployments + inherit dontNpmInstall preRebuild unpackPhase buildPhase; + + compositionScript = composePackage args; + pinpointDependenciesScript = pinpointDependenciesOfPackage args; + + passAsFile = [ "compositionScript" "pinpointDependenciesScript" ]; + + installPhase = '' + # Create and enter a root node_modules/ folder + mkdir -p $out/lib/node_modules + cd $out/lib/node_modules + + # Compose the package and all its dependencies + source $compositionScriptPath + + ${prepareAndInvokeNPM { inherit packageName bypassCache reconstructLock npmFlags production; }} + + # Create symlink to the deployed executable folder, if applicable + if [ -d "$out/lib/node_modules/.bin" ] + then + ln -s $out/lib/node_modules/.bin $out/bin + fi + + # Create symlinks to the deployed manual page folders, if applicable + if [ -d "$out/lib/node_modules/${packageName}/man" ] + then + mkdir -p $out/share + for dir in "$out/lib/node_modules/${packageName}/man/"* + do + mkdir -p $out/share/man/$(basename "$dir") + for page in "$dir"/* + do + ln -s $page $out/share/man/$(basename "$dir") + done + done + fi + + # Run post install hook, if provided + runHook postInstall + ''; + } // extraArgs); + + # Builds a node environment (a node_modules folder and a set of binaries) + buildNodeDependencies = + { name + , packageName + , version + , src + , dependencies ? [] + , buildInputs ? [] + , production ? true + , npmFlags ? "" + , dontNpmInstall ? false + , bypassCache ? false + , reconstructLock ? false + , dontStrip ? true + , unpackPhase ? "true" + , buildPhase ? "true" + , ... }@args: + + let + extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" ]; + in + stdenv.mkDerivation ({ + name = "node-dependencies-${name}-${version}"; + + buildInputs = [ tarWrapper python nodejs ] + ++ lib.optional (stdenv.isLinux) utillinux + ++ lib.optional (stdenv.isDarwin) libtool + ++ buildInputs; + + inherit dontStrip; # Stripping may fail a build for some package deployments + inherit dontNpmInstall unpackPhase buildPhase; + + includeScript = includeDependencies { inherit dependencies; }; + pinpointDependenciesScript = pinpointDependenciesOfPackage args; + + passAsFile = [ "includeScript" "pinpointDependenciesScript" ]; + + installPhase = '' + mkdir -p $out/${packageName} + cd $out/${packageName} + + source $includeScriptPath + + # Create fake package.json to make the npm commands work properly + cp ${src}/package.json . + chmod 644 package.json + ${lib.optionalString bypassCache '' + if [ -f ${src}/package-lock.json ] + then + cp ${src}/package-lock.json . + fi + ''} + + # Go to the parent folder to make sure that all packages are pinpointed + cd .. + ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} + + ${prepareAndInvokeNPM { inherit packageName bypassCache reconstructLock npmFlags production; }} + + # Expose the executables that were installed + cd .. + ${lib.optionalString (builtins.substring 0 1 packageName == "@") "cd .."} + + mv ${packageName} lib + ln -s $out/lib/node_modules/.bin $out/bin + ''; + } // extraArgs); + + # Builds a development shell + buildNodeShell = + { name + , packageName + , version + , src + , dependencies ? [] + , buildInputs ? [] + , production ? true + , npmFlags ? "" + , dontNpmInstall ? false + , bypassCache ? false + , reconstructLock ? false + , dontStrip ? true + , unpackPhase ? "true" + , buildPhase ? "true" + , ... }@args: + + let + nodeDependencies = buildNodeDependencies args; + in + stdenv.mkDerivation { + name = "node-shell-${name}-${version}"; + + buildInputs = [ python nodejs ] ++ lib.optional (stdenv.isLinux) utillinux ++ buildInputs; + buildCommand = '' + mkdir -p $out/bin + cat > $out/bin/shell < vObj.relevance.automated_update).slice(-1)[0].version; - } catch(e) { - console.error(e); + if (!fs.existsSync(faviconNixDirectory)) { + try { + const faviconApiChangelog = await request({ + method: 'GET', + uri: 'https://realfavicongenerator.net/api/versions', + headers: { + 'Accept': '*/*' + }, + json: true + }); + faviconApiVersion = faviconApiChangelog.filter(vObj => vObj.relevance.automated_update).slice(-1)[0].version; + } catch(e) { + console.error(e); + } } return { @@ -224,7 +227,16 @@ async function webpackConfig() { const cacheDirectory = path.resolve(__dirname, '.well-known-cache', `${cacheDigest}-${lang}`); - if (fs.existsSync(cacheDirectory) && (!faviconApiVersion || faviconApiVersion === cachedVersion)) { + if (fs.existsSync(faviconNixDirectory)) { + console.log("Using favicons generated by nix"); + return [ + new CopyPlugin({ + patterns: [ + { from: path.resolve(faviconNixDirectory, lang), to: path.resolve(__dirname, 'well-known', lang) } + ] + }) + ]; + } else if (fs.existsSync(cacheDirectory) && (!faviconApiVersion || faviconApiVersion === cachedVersion)) { console.log(`Using cached well-known from ${cacheDirectory} for ${lang}`); return [ new CopyPlugin({