Compare commits
25 Commits
3ef84a6b8c
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
f0f3f19c21
|
|||
|
f05330dd60
|
|||
|
1f4adea38e
|
|||
|
8fe36cfddc
|
|||
|
66fe96f8ce
|
|||
|
ac27bd0bec
|
|||
|
6df2a1a659
|
|||
|
5a6dd50718
|
|||
|
67d062e9b0
|
|||
|
de4bb6a60e
|
|||
|
101ab28b9b
|
|||
| d2e3803d2d | |||
|
|
cff7f6163f | ||
|
242f3e0052
|
|||
|
c340ee3659
|
|||
|
2940e7c5fb
|
|||
|
a984858a7f
|
|||
| 504b715b42 | |||
|
|
5d757c2fcf | ||
|
|
8ccdad907f | ||
|
47b05d81c1
|
|||
|
d5421d87db
|
|||
|
|
d2eec57ac2 | ||
|
cf0dcee23f
|
|||
|
706e911539
|
@@ -15,7 +15,7 @@ jobs:
|
|||||||
- uses: cachix/install-nix-action@v23
|
- uses: cachix/install-nix-action@v23
|
||||||
with:
|
with:
|
||||||
extra_nix_config: |
|
extra_nix_config: |
|
||||||
access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}
|
access-tokens = github.com=${{ secrets.INPUT_GITHUB_ACCESS_TOKEN }}
|
||||||
- name: "flake: update inputs"
|
- name: "flake: update inputs"
|
||||||
uses: DeterminateSystems/update-flake-lock@v20
|
uses: DeterminateSystems/update-flake-lock@v20
|
||||||
with:
|
with:
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
|
|
||||||
**My personal [NUR](https://github.com/nix-community/NUR) repository**
|
**My personal [NUR](https://github.com/nix-community/NUR) repository**
|
||||||
|
|
||||||
[CI](https://git.xeals.me/xeals/nur-packages/actions) [](https://xeals.cachix.org)
|
[](https://git.xeals.me/xeals/nur-packages/actions)
|
||||||
|
[](https://xeals.cachix.org)
|
||||||
|
|
||||||
|
|
||||||
## Using
|
## Using
|
||||||
|
|
||||||
|
|||||||
12
flake.lock
generated
12
flake.lock
generated
@@ -5,11 +5,11 @@
|
|||||||
"systems": "systems"
|
"systems": "systems"
|
||||||
},
|
},
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1710146030,
|
"lastModified": 1731533236,
|
||||||
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
|
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||||
"owner": "numtide",
|
"owner": "numtide",
|
||||||
"repo": "flake-utils",
|
"repo": "flake-utils",
|
||||||
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
|
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
@@ -20,11 +20,11 @@
|
|||||||
},
|
},
|
||||||
"nixpkgs": {
|
"nixpkgs": {
|
||||||
"locked": {
|
"locked": {
|
||||||
"lastModified": 1719931832,
|
"lastModified": 1756536218,
|
||||||
"narHash": "sha256-0LD+KePCKKEb4CcPsTBOwf019wDtZJanjoKm1S8q3Do=",
|
"narHash": "sha256-ynQxPVN2FIPheUgTFhv01gYLbaiSOS7NgWJPm9LF9D0=",
|
||||||
"owner": "NixOS",
|
"owner": "NixOS",
|
||||||
"repo": "nixpkgs",
|
"repo": "nixpkgs",
|
||||||
"rev": "0aeab749216e4c073cece5d34bc01b79e717c3e0",
|
"rev": "a918bb3594dd243c2f8534b3be01b3cb4ed35fd1",
|
||||||
"type": "github"
|
"type": "github"
|
||||||
},
|
},
|
||||||
"original": {
|
"original": {
|
||||||
|
|||||||
@@ -6,15 +6,11 @@ let
|
|||||||
|
|
||||||
cfg = config.services.betanin;
|
cfg = config.services.betanin;
|
||||||
|
|
||||||
defaultUser = "betanin";
|
|
||||||
defaultGroup = "betanin";
|
|
||||||
|
|
||||||
settingsFormat = pkgs.formats.toml { };
|
settingsFormat = pkgs.formats.toml { };
|
||||||
beetsFormat = pkgs.formats.yaml { };
|
beetsFormat = pkgs.formats.yaml { };
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options.services.betanin = {
|
||||||
services.betanin = {
|
|
||||||
enable = lib.mkEnableOption "betanin";
|
enable = lib.mkEnableOption "betanin";
|
||||||
|
|
||||||
package = mkOption {
|
package = mkOption {
|
||||||
@@ -38,13 +34,13 @@ in
|
|||||||
user = mkOption {
|
user = mkOption {
|
||||||
description = "User that the betanin program should run under.";
|
description = "User that the betanin program should run under.";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = defaultUser;
|
default = "betanin";
|
||||||
};
|
};
|
||||||
|
|
||||||
group = mkOption {
|
group = mkOption {
|
||||||
description = "Group that the betanin program should run under.";
|
description = "Group that the betanin program should run under.";
|
||||||
type = types.str;
|
type = types.str;
|
||||||
default = defaultGroup;
|
default = "betanin";
|
||||||
};
|
};
|
||||||
|
|
||||||
dataDir = mkOption {
|
dataDir = mkOption {
|
||||||
@@ -60,7 +56,7 @@ in
|
|||||||
{
|
{
|
||||||
frontend = {
|
frontend = {
|
||||||
username = "foo";
|
username = "foo";
|
||||||
password { _secret = "/run/secrets/betaninPasswordFile"; };
|
password = { _secret = "/run/secrets/betaninPasswordFile"; };
|
||||||
};
|
};
|
||||||
clients = {
|
clients = {
|
||||||
api_key = { _secret = "/run/secrets/betaninApiKeyFile"; };
|
api_key = { _secret = "/run/secrets/betaninApiKeyFile"; };
|
||||||
@@ -70,7 +66,7 @@ in
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
'';
|
'';
|
||||||
description = lib.mdDoc ''
|
description = ''
|
||||||
Configuration for betanin.
|
Configuration for betanin.
|
||||||
|
|
||||||
Options containing secret data should be set to an attribute set
|
Options containing secret data should be set to an attribute set
|
||||||
@@ -82,8 +78,7 @@ in
|
|||||||
beets.settings = mkOption {
|
beets.settings = mkOption {
|
||||||
type = beetsFormat.type;
|
type = beetsFormat.type;
|
||||||
default = { };
|
default = { };
|
||||||
description = lib.mdDoc "Configuration for beets used by betanin.";
|
description = "Configuration for beets used by betanin.";
|
||||||
};
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -123,17 +118,14 @@ in
|
|||||||
{
|
{
|
||||||
description = "Betanin service";
|
description = "Betanin service";
|
||||||
wantedBy = [ "multi-user.target" ];
|
wantedBy = [ "multi-user.target" ];
|
||||||
after = [ "networking.target" ];
|
after = [ "network.target" ];
|
||||||
|
path = [ pkgs.replace-secret ];
|
||||||
|
|
||||||
environment = {
|
environment = {
|
||||||
HOME = cfg.dataDir;
|
HOME = cfg.dataDir;
|
||||||
};
|
};
|
||||||
path = [ pkgs.replace-secret ];
|
|
||||||
|
|
||||||
script = ''
|
script = ''
|
||||||
mkdir -p ${cfg.dataDir}/.config/betanin \
|
|
||||||
${cfg.dataDir}/.local/share/betanin \
|
|
||||||
${cfg.dataDir}/.config/beets
|
|
||||||
|
|
||||||
ln -sf ${beetsFile} ${cfg.dataDir}/.config/beets/config.yaml
|
ln -sf ${beetsFile} ${cfg.dataDir}/.config/beets/config.yaml
|
||||||
cat ${settingsFile} > ${cfg.dataDir}/.config/betanin/config.toml
|
cat ${settingsFile} > ${cfg.dataDir}/.config/betanin/config.toml
|
||||||
${secretReplacements}
|
${secretReplacements}
|
||||||
@@ -141,28 +133,34 @@ in
|
|||||||
${cfg.package}/bin/betanin --port ${toString cfg.port}
|
${cfg.package}/bin/betanin --port ${toString cfg.port}
|
||||||
'';
|
'';
|
||||||
|
|
||||||
serviceConfig = lib.mkMerge [
|
serviceConfig = {
|
||||||
{
|
|
||||||
User = cfg.user;
|
User = cfg.user;
|
||||||
Group = cfg.group;
|
Group = cfg.group;
|
||||||
PrivateTmp = true;
|
PrivateTmp = true;
|
||||||
Restart = "always";
|
Restart = "always";
|
||||||
WorkingDirectory = cfg.dataDir;
|
WorkingDirectory = cfg.dataDir;
|
||||||
}
|
StateDirectory = mkIf (cfg.dataDir == "/var/lib/betanin") "betanin";
|
||||||
(mkIf (cfg.dataDir == "/var/lib/betanin") {
|
};
|
||||||
StateDirectory = "betanin";
|
|
||||||
})
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
users.users = optionalAttrs (cfg.user == defaultUser) {
|
systemd.tmpfiles.rules = [
|
||||||
|
"d ${cfg.dataDir} 0710 ${cfg.user} ${cfg.group} - -"
|
||||||
|
"d ${cfg.dataDir}/.config 0750 ${cfg.user} ${cfg.group} - -"
|
||||||
|
"d ${cfg.dataDir}/.config/betanin 0750 ${cfg.user} ${cfg.group} - -"
|
||||||
|
"d ${cfg.dataDir}/.config/beets 0750 ${cfg.user} ${cfg.group} - -"
|
||||||
|
"d ${cfg.dataDir}/.local 0750 ${cfg.user} ${cfg.group} - -"
|
||||||
|
"d ${cfg.dataDir}/.local/share 0750 ${cfg.user} ${cfg.group} - -"
|
||||||
|
"d ${cfg.dataDir}/.local/share/betanin 0750 ${cfg.user} ${cfg.group} - -"
|
||||||
|
];
|
||||||
|
|
||||||
|
users.users = optionalAttrs (cfg.user == "betanin") {
|
||||||
${cfg.user} = {
|
${cfg.user} = {
|
||||||
isSystemUser = true;
|
isSystemUser = true;
|
||||||
group = cfg.group;
|
group = cfg.group;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
users.groups = optionalAttrs (cfg.group == defaultGroup) {
|
users.groups = optionalAttrs (cfg.group == "betanin") {
|
||||||
${cfg.group} = { };
|
${cfg.group} = { };
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,6 +18,8 @@ python3Packages.buildPythonApplication rec {
|
|||||||
|
|
||||||
propagatedBuildInputs = [ mopidy python3Packages.py-sonic ];
|
propagatedBuildInputs = [ mopidy python3Packages.py-sonic ];
|
||||||
|
|
||||||
|
format = "setuptools";
|
||||||
|
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
|
|||||||
@@ -20,6 +20,8 @@ python3Packages.buildPythonApplication rec {
|
|||||||
pyyaml
|
pyyaml
|
||||||
];
|
];
|
||||||
|
|
||||||
|
format = "setuptools";
|
||||||
|
|
||||||
patchPhase = ''
|
patchPhase = ''
|
||||||
substituteInPlace setup.py \
|
substituteInPlace setup.py \
|
||||||
--replace PROJECTVERSION "${version}"
|
--replace PROJECTVERSION "${version}"
|
||||||
|
|||||||
@@ -1,17 +0,0 @@
|
|||||||
# This file has been generated by node2nix 1.11.1. Do not edit!
|
|
||||||
|
|
||||||
{pkgs ? import <nixpkgs> {
|
|
||||||
inherit system;
|
|
||||||
}, system ? builtins.currentSystem, nodejs ? pkgs."nodejs_18"}:
|
|
||||||
|
|
||||||
let
|
|
||||||
nodeEnv = import ./node-env.nix {
|
|
||||||
inherit (pkgs) stdenv lib python2 runCommand writeTextFile writeShellScript;
|
|
||||||
inherit pkgs nodejs;
|
|
||||||
libtool = if pkgs.stdenv.isDarwin then pkgs.darwin.cctools else null;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
import ./packages.nix {
|
|
||||||
inherit (pkgs) fetchurl nix-gitignore stdenv lib fetchgit;
|
|
||||||
inherit nodeEnv;
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
{ pkgs
|
|
||||||
, stdenv
|
|
||||||
, src
|
|
||||||
, version
|
|
||||||
}:
|
|
||||||
|
|
||||||
let
|
|
||||||
nodeComposition = import ./composition.nix {
|
|
||||||
inherit pkgs;
|
|
||||||
inherit (stdenv.hostPlatform) system;
|
|
||||||
};
|
|
||||||
in
|
|
||||||
nodeComposition.package.override {
|
|
||||||
pname = "betanin";
|
|
||||||
inherit version;
|
|
||||||
src = "${src}/betanin_client";
|
|
||||||
|
|
||||||
postInstall = ''
|
|
||||||
PRODUCTION=true npm run-script build
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/env bash
|
|
||||||
|
|
||||||
# Requires node2nix and jq
|
|
||||||
|
|
||||||
cd "$(dirname "$0")" || exit 1
|
|
||||||
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
nix build ..#betanin.src 2>/dev/null
|
|
||||||
|
|
||||||
tempDir=$(mktemp -d)
|
|
||||||
cp result/betanin_client/package.json "$tempDir/"
|
|
||||||
cp result/betanin_client/package-lock.json "$tempDir/"
|
|
||||||
pushd "$tempDir"
|
|
||||||
|
|
||||||
node2nix \
|
|
||||||
--input package.json \
|
|
||||||
--lock package-lock.json \
|
|
||||||
--output packages.nix \
|
|
||||||
--composition composition.nix \
|
|
||||||
--strip-optional-dependencies \
|
|
||||||
--development \
|
|
||||||
--nodejs-18
|
|
||||||
|
|
||||||
popd
|
|
||||||
cp "$tempDir"/*.nix .
|
|
||||||
|
|
||||||
rm result
|
|
||||||
rm -rf "$tempDir"
|
|
||||||
@@ -1,689 +0,0 @@
|
|||||||
# This file originates from node2nix
|
|
||||||
|
|
||||||
{lib, stdenv, nodejs, python2, pkgs, libtool, runCommand, writeTextFile, writeShellScript}:
|
|
||||||
|
|
||||||
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 <<EOF
|
|
||||||
#! ${stdenv.shell} -e
|
|
||||||
$(type -p tar) "\$@" --warning=no-unknown-keyword --delay-directory-restore
|
|
||||||
EOF
|
|
||||||
|
|
||||||
chmod +x $out/bin/tar
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Function that generates a TGZ file from a NPM project
|
|
||||||
buildNodeSourceDist =
|
|
||||||
{ name, version, src, ... }:
|
|
||||||
|
|
||||||
stdenv.mkDerivation {
|
|
||||||
name = "node-tarball-${name}-${version}";
|
|
||||||
inherit src;
|
|
||||||
buildInputs = [ nodejs ];
|
|
||||||
buildPhase = ''
|
|
||||||
export HOME=$TMPDIR
|
|
||||||
tgzFile=$(npm pack | tail -n 1) # Hooks to the pack command will add output (https://docs.npmjs.com/misc/scripts)
|
|
||||||
'';
|
|
||||||
installPhase = ''
|
|
||||||
mkdir -p $out/tarballs
|
|
||||||
mv $tgzFile $out/tarballs
|
|
||||||
mkdir -p $out/nix-support
|
|
||||||
echo "file source-dist $out/tarballs/$tgzFile" >> $out/nix-support/hydra-build-products
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Common shell logic
|
|
||||||
installPackage = writeShellScript "install-package" ''
|
|
||||||
installPackage() {
|
|
||||||
local packageName=$1 src=$2
|
|
||||||
|
|
||||||
local strippedName
|
|
||||||
|
|
||||||
local 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
|
|
||||||
|
|
||||||
# Change to the package directory to install dependencies
|
|
||||||
cd "$DIR/$packageName"
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Bundle the dependencies of the package
|
|
||||||
#
|
|
||||||
# Only include dependencies if they don't exist. They may also be bundled in the package.
|
|
||||||
includeDependencies = {dependencies}:
|
|
||||||
lib.optionalString (dependencies != []) (
|
|
||||||
''
|
|
||||||
mkdir -p node_modules
|
|
||||||
cd node_modules
|
|
||||||
''
|
|
||||||
+ (lib.concatMapStrings (dependency:
|
|
||||||
''
|
|
||||||
if [ ! -e "${dependency.packageName}" ]; then
|
|
||||||
${composePackage dependency}
|
|
||||||
fi
|
|
||||||
''
|
|
||||||
) dependencies)
|
|
||||||
+ ''
|
|
||||||
cd ..
|
|
||||||
''
|
|
||||||
);
|
|
||||||
|
|
||||||
# Recursively composes the dependencies of a package
|
|
||||||
composePackage = { name, packageName, src, dependencies ? [], ... }@args:
|
|
||||||
builtins.addErrorContext "while evaluating node package '${packageName}'" ''
|
|
||||||
installPackage "${packageName}" "${src}"
|
|
||||||
${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);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
packageObj.devDependencies = {};
|
|
||||||
}
|
|
||||||
replaceDependencies(packageObj.optionalDependencies);
|
|
||||||
replaceDependencies(packageObj.peerDependencies);
|
|
||||||
|
|
||||||
/* 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 = "reconstructpackagelock.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: 2,
|
|
||||||
requires: true,
|
|
||||||
packages: {
|
|
||||||
"": {
|
|
||||||
name: packageObj.name,
|
|
||||||
version: packageObj.version,
|
|
||||||
license: packageObj.license,
|
|
||||||
bin: packageObj.bin,
|
|
||||||
dependencies: packageObj.dependencies,
|
|
||||||
engines: packageObj.engines,
|
|
||||||
optionalDependencies: packageObj.optionalDependencies
|
|
||||||
}
|
|
||||||
},
|
|
||||||
dependencies: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
function augmentPackageJSON(filePath, packages, dependencies) {
|
|
||||||
var packageJSON = path.join(filePath, "package.json");
|
|
||||||
if(fs.existsSync(packageJSON)) {
|
|
||||||
var packageObj = JSON.parse(fs.readFileSync(packageJSON));
|
|
||||||
packages[filePath] = {
|
|
||||||
version: packageObj.version,
|
|
||||||
integrity: "sha1-000000000000000000000000000=",
|
|
||||||
dependencies: packageObj.dependencies,
|
|
||||||
engines: packageObj.engines,
|
|
||||||
optionalDependencies: packageObj.optionalDependencies
|
|
||||||
};
|
|
||||||
dependencies[packageObj.name] = {
|
|
||||||
version: packageObj.version,
|
|
||||||
integrity: "sha1-000000000000000000000000000=",
|
|
||||||
dependencies: {}
|
|
||||||
};
|
|
||||||
processDependencies(path.join(filePath, "node_modules"), packages, dependencies[packageObj.name].dependencies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function processDependencies(dir, packages, 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, packages, dependencies);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
augmentPackageJSON(filePath, packages, dependencies);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processDependencies("node_modules", lockObj.packages, lockObj.dependencies);
|
|
||||||
|
|
||||||
fs.writeFileSync("package-lock.json", JSON.stringify(lockObj, null, 2));
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
# Script that links bins defined in package.json to the node_modules bin directory
|
|
||||||
# NPM does not do this for top-level packages itself anymore as of v7
|
|
||||||
linkBinsScript = writeTextFile {
|
|
||||||
name = "linkbins.js";
|
|
||||||
text = ''
|
|
||||||
var fs = require('fs');
|
|
||||||
var path = require('path');
|
|
||||||
|
|
||||||
var packageObj = JSON.parse(fs.readFileSync("package.json"));
|
|
||||||
|
|
||||||
var nodeModules = Array(packageObj.name.split("/").length).fill("..").join(path.sep);
|
|
||||||
|
|
||||||
if(packageObj.bin !== undefined) {
|
|
||||||
fs.mkdirSync(path.join(nodeModules, ".bin"))
|
|
||||||
|
|
||||||
if(typeof packageObj.bin == "object") {
|
|
||||||
Object.keys(packageObj.bin).forEach(function(exe) {
|
|
||||||
if(fs.existsSync(packageObj.bin[exe])) {
|
|
||||||
console.log("linking bin '" + exe + "'");
|
|
||||||
fs.symlinkSync(
|
|
||||||
path.join("..", packageObj.name, packageObj.bin[exe]),
|
|
||||||
path.join(nodeModules, ".bin", exe)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log("skipping non-existent bin '" + exe + "'");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if(fs.existsSync(packageObj.bin)) {
|
|
||||||
console.log("linking bin '" + packageObj.bin + "'");
|
|
||||||
fs.symlinkSync(
|
|
||||||
path.join("..", packageObj.name, packageObj.bin),
|
|
||||||
path.join(nodeModules, ".bin", packageObj.name.split("/").pop())
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log("skipping non-existent bin '" + packageObj.bin + "'");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(packageObj.directories !== undefined && packageObj.directories.bin !== undefined) {
|
|
||||||
fs.mkdirSync(path.join(nodeModules, ".bin"))
|
|
||||||
|
|
||||||
fs.readdirSync(packageObj.directories.bin).forEach(function(exe) {
|
|
||||||
if(fs.existsSync(path.join(packageObj.directories.bin, exe))) {
|
|
||||||
console.log("linking bin '" + exe + "'");
|
|
||||||
fs.symlinkSync(
|
|
||||||
path.join("..", packageObj.name, packageObj.directories.bin, exe),
|
|
||||||
path.join(nodeModules, ".bin", exe)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log("skipping non-existent bin '" + exe + "'");
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
runHook postRebuild
|
|
||||||
|
|
||||||
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} --no-bin-links --ignore-scripts ${npmFlags} ${lib.optionalString production "--production"} install
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Link executables defined in package.json
|
|
||||||
node ${linkBinsScript}
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Builds and composes an NPM package including all its dependencies
|
|
||||||
buildNodePackage =
|
|
||||||
{ name
|
|
||||||
, packageName
|
|
||||||
, version ? null
|
|
||||||
, dependencies ? []
|
|
||||||
, buildInputs ? []
|
|
||||||
, production ? true
|
|
||||||
, npmFlags ? ""
|
|
||||||
, dontNpmInstall ? false
|
|
||||||
, bypassCache ? false
|
|
||||||
, reconstructLock ? false
|
|
||||||
, preRebuild ? ""
|
|
||||||
, dontStrip ? true
|
|
||||||
, unpackPhase ? "true"
|
|
||||||
, buildPhase ? "true"
|
|
||||||
, meta ? {}
|
|
||||||
, ... }@args:
|
|
||||||
|
|
||||||
let
|
|
||||||
extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "preRebuild" "unpackPhase" "buildPhase" "meta" ];
|
|
||||||
in
|
|
||||||
stdenv.mkDerivation ({
|
|
||||||
name = "${name}${if version == null then "" else "-${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 = ''
|
|
||||||
source ${installPackage}
|
|
||||||
|
|
||||||
# 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
|
|
||||||
|
|
||||||
# Fixup all executables
|
|
||||||
ls $out/bin/* | while read i
|
|
||||||
do
|
|
||||||
file="$(readlink -f "$i")"
|
|
||||||
chmod u+rwx "$file"
|
|
||||||
if isScript "$file"
|
|
||||||
then
|
|
||||||
sed -i 's/\r$//' "$file" # convert crlf to lf
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
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
|
|
||||||
'';
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
# default to Node.js' platforms
|
|
||||||
platforms = nodejs.meta.platforms;
|
|
||||||
} // meta;
|
|
||||||
} // extraArgs);
|
|
||||||
|
|
||||||
# Builds a node environment (a node_modules folder and a set of binaries)
|
|
||||||
buildNodeDependencies =
|
|
||||||
{ name
|
|
||||||
, packageName
|
|
||||||
, version ? null
|
|
||||||
, 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}${if version == null then "" else "-${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 = ''
|
|
||||||
source ${installPackage}
|
|
||||||
|
|
||||||
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 .
|
|
||||||
chmod 644 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 ? null
|
|
||||||
, src
|
|
||||||
, dependencies ? []
|
|
||||||
, buildInputs ? []
|
|
||||||
, production ? true
|
|
||||||
, npmFlags ? ""
|
|
||||||
, dontNpmInstall ? false
|
|
||||||
, bypassCache ? false
|
|
||||||
, reconstructLock ? false
|
|
||||||
, dontStrip ? true
|
|
||||||
, unpackPhase ? "true"
|
|
||||||
, buildPhase ? "true"
|
|
||||||
, ... }@args:
|
|
||||||
|
|
||||||
let
|
|
||||||
nodeDependencies = buildNodeDependencies args;
|
|
||||||
extraArgs = removeAttrs args [ "name" "dependencies" "buildInputs" "dontStrip" "dontNpmInstall" "unpackPhase" "buildPhase" ];
|
|
||||||
in
|
|
||||||
stdenv.mkDerivation ({
|
|
||||||
name = "node-shell-${name}${if version == null then "" else "-${version}"}";
|
|
||||||
|
|
||||||
buildInputs = [ python nodejs ] ++ lib.optional (stdenv.isLinux) utillinux ++ buildInputs;
|
|
||||||
buildCommand = ''
|
|
||||||
mkdir -p $out/bin
|
|
||||||
cat > $out/bin/shell <<EOF
|
|
||||||
#! ${stdenv.shell} -e
|
|
||||||
$shellHook
|
|
||||||
exec ${stdenv.shell}
|
|
||||||
EOF
|
|
||||||
chmod +x $out/bin/shell
|
|
||||||
'';
|
|
||||||
|
|
||||||
# Provide the dependencies in a development shell through the NODE_PATH environment variable
|
|
||||||
inherit nodeDependencies;
|
|
||||||
shellHook = lib.optionalString (dependencies != []) ''
|
|
||||||
export NODE_PATH=${nodeDependencies}/lib/node_modules
|
|
||||||
export PATH="${nodeDependencies}/bin:$PATH"
|
|
||||||
'';
|
|
||||||
} // extraArgs);
|
|
||||||
in
|
|
||||||
{
|
|
||||||
buildNodeSourceDist = lib.makeOverridable buildNodeSourceDist;
|
|
||||||
buildNodePackage = lib.makeOverridable buildNodePackage;
|
|
||||||
buildNodeDependencies = lib.makeOverridable buildNodeDependencies;
|
|
||||||
buildNodeShell = lib.makeOverridable buildNodeShell;
|
|
||||||
}
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -3,6 +3,7 @@
|
|||||||
, fetchFromGitHub
|
, fetchFromGitHub
|
||||||
, python3
|
, python3
|
||||||
, beets
|
, beets
|
||||||
|
, wrapGAppsHook
|
||||||
}:
|
}:
|
||||||
|
|
||||||
let
|
let
|
||||||
@@ -22,7 +23,13 @@ let
|
|||||||
sourceRoot = "${src.name}/betanin_client";
|
sourceRoot = "${src.name}/betanin_client";
|
||||||
|
|
||||||
npmDepsHash = "sha256-VkCQKpkDCTDejv8eRAN2Zfbq8TlWLdtqVJU3fo9hQrI=";
|
npmDepsHash = "sha256-VkCQKpkDCTDejv8eRAN2Zfbq8TlWLdtqVJU3fo9hQrI=";
|
||||||
|
NODE_ENV = "production";
|
||||||
NODE_OPTIONS = "--openssl-legacy-provider";
|
NODE_OPTIONS = "--openssl-legacy-provider";
|
||||||
|
|
||||||
|
npmInstallFlags = [ "--include=dev" ];
|
||||||
|
installPhase = ''
|
||||||
|
cp -r dist $out
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
in
|
in
|
||||||
python3.pkgs.buildPythonApplication {
|
python3.pkgs.buildPythonApplication {
|
||||||
@@ -32,14 +39,20 @@ python3.pkgs.buildPythonApplication {
|
|||||||
|
|
||||||
patches = [ ./paths.patch ];
|
patches = [ ./paths.patch ];
|
||||||
postPatch = ''
|
postPatch = ''
|
||||||
export clientDistDir="${client}/lib/node_modules/betanin/dist/"
|
export clientDistDir="${client}"
|
||||||
export libPrefix="${python3.libPrefix}"
|
export libPrefix="${python3.libPrefix}"
|
||||||
substituteAllInPlace betanin/paths.py
|
substituteAllInPlace betanin/paths.py
|
||||||
|
|
||||||
|
# pythonRelaxDepsHook doesn't work
|
||||||
|
sed -i 's/Flask <3.0.0/Flask/' pyproject.toml
|
||||||
'';
|
'';
|
||||||
|
|
||||||
buildInputs = with python3.pkgs; [ setuptools ];
|
# required for apprise
|
||||||
|
nativeBuildInputs = [ wrapGAppsHook ];
|
||||||
|
|
||||||
propagatedBuildInputs = (with python3.pkgs; [
|
build-system = with python3.pkgs; [ setuptools ];
|
||||||
|
|
||||||
|
dependencies = (with python3.pkgs; [
|
||||||
apprise
|
apprise
|
||||||
alembic
|
alembic
|
||||||
click
|
click
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ let
|
|||||||
fi
|
fi
|
||||||
args+=("$a")
|
args+=("$a")
|
||||||
done
|
done
|
||||||
exec "${cura5}/bin/${name}" "''${args[@]}"
|
QT_QPA_PLATFORM=xcb exec "${cura5}/bin/cura5" "''${args[@]}"
|
||||||
'';
|
'';
|
||||||
in
|
in
|
||||||
stdenv.mkDerivation rec {
|
stdenv.mkDerivation rec {
|
||||||
|
|||||||
@@ -1,35 +0,0 @@
|
|||||||
{ lib
|
|
||||||
, python3
|
|
||||||
, fetchPypi
|
|
||||||
}:
|
|
||||||
|
|
||||||
python3.pkgs.buildPythonApplication rec {
|
|
||||||
pname = "gersemi";
|
|
||||||
version = "0.11.0";
|
|
||||||
format = "setuptools";
|
|
||||||
|
|
||||||
src = fetchPypi {
|
|
||||||
inherit pname version;
|
|
||||||
hash = "sha256-K8ZbVVYiEazdjbuAUa8r9lJyjOPt2jsKbUAovTx9XeY=";
|
|
||||||
};
|
|
||||||
|
|
||||||
# Remove dataclasses backport requirement since it doesn't work on newer
|
|
||||||
# Python.
|
|
||||||
patchPhase = ''
|
|
||||||
sed -i '/dataclasses/d' setup.py
|
|
||||||
'';
|
|
||||||
|
|
||||||
propagatedBuildInputs = with python3.pkgs; [
|
|
||||||
appdirs
|
|
||||||
colorama
|
|
||||||
lark
|
|
||||||
pyyaml
|
|
||||||
];
|
|
||||||
|
|
||||||
meta = {
|
|
||||||
description = "A formatter to make your CMake code the real treasure";
|
|
||||||
homepage = "https://github.com/BlankSpruce/gersemi";
|
|
||||||
license = lib.licenses.mpl20;
|
|
||||||
platforms = python3.meta.platforms;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -9,7 +9,7 @@ from dataclasses import dataclass, fields as datafields
|
|||||||
from enum import Enum, unique
|
from enum import Enum, unique
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
|
|
||||||
APIBASE = "https://porkbun.com/api/json/v3/dns"
|
APIBASE = "https://api.porkbun.com/api/json/v3/dns"
|
||||||
|
|
||||||
|
|
||||||
def dataclass_from_dict(klass: object, d: dict):
|
def dataclass_from_dict(klass: object, d: dict):
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
, rustPlatform
|
, rustPlatform
|
||||||
|
|
||||||
, pkg-config
|
, pkg-config
|
||||||
, alsaLib
|
, alsa-lib
|
||||||
, dbus
|
, dbus
|
||||||
, openssl
|
, openssl
|
||||||
|
|
||||||
@@ -23,6 +23,7 @@ assert withGui -> gtk3.meta.available;
|
|||||||
rustPlatform.buildRustPackage rec {
|
rustPlatform.buildRustPackage rec {
|
||||||
pname = "psst";
|
pname = "psst";
|
||||||
version = "20221012.d70ed81";
|
version = "20221012.d70ed81";
|
||||||
|
|
||||||
src = fetchFromGitHub {
|
src = fetchFromGitHub {
|
||||||
owner = "jpochyla";
|
owner = "jpochyla";
|
||||||
repo = "psst";
|
repo = "psst";
|
||||||
@@ -30,12 +31,12 @@ rustPlatform.buildRustPackage rec {
|
|||||||
hash = "sha256-ZKhHN0ruLb6ZVKkrKv/YawRsVop6SP1QF/nrtkmA8P8=";
|
hash = "sha256-ZKhHN0ruLb6ZVKkrKv/YawRsVop6SP1QF/nrtkmA8P8=";
|
||||||
fetchSubmodules = true;
|
fetchSubmodules = true;
|
||||||
};
|
};
|
||||||
cargoSha256 = "sha256-zH6+EV78FDVOYEFXk0f54pH2Su0QpK1I0bHqzIiMdBo=";
|
cargoHash = "sha256-my15AXG9LLmdqZLqXdeZ81VLv+GbSMgNtuFAlYTEUvQ=";
|
||||||
|
|
||||||
nativeBuildInputs = [ pkg-config ]
|
nativeBuildInputs = [ pkg-config ]
|
||||||
++ optional withGui copyDesktopItems;
|
++ optional withGui copyDesktopItems;
|
||||||
|
|
||||||
buildInputs = [ alsaLib dbus openssl ]
|
buildInputs = [ alsa-lib dbus openssl ]
|
||||||
++ optional withGui gtk3;
|
++ optional withGui gtk3;
|
||||||
|
|
||||||
cargoBuildFlags = optionals (!withGui) [
|
cargoBuildFlags = optionals (!withGui) [
|
||||||
|
|||||||
@@ -55,6 +55,8 @@ python3Packages.buildPythonApplication rec {
|
|||||||
(if opusSupport then opusTools else null)
|
(if opusSupport then opusTools else null)
|
||||||
];
|
];
|
||||||
|
|
||||||
|
format = "setuptools";
|
||||||
|
|
||||||
# Remove impure executables.
|
# Remove impure executables.
|
||||||
patches = [ ./fix-setup.patch ];
|
patches = [ ./fix-setup.patch ];
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,9 @@ buildDotnetModule rec {
|
|||||||
mv $out/bin/TheAirBlow.Thor.Shell $out/bin/thor
|
mv $out/bin/TheAirBlow.Thor.Shell $out/bin/thor
|
||||||
'';
|
'';
|
||||||
|
|
||||||
|
# dotnet7 is unsupported but it still runs fine; just don't build it in CI.
|
||||||
|
# https://github.com/Samsung-Loki/Thor/issues/23
|
||||||
|
preferLocalBuild = true;
|
||||||
meta = {
|
meta = {
|
||||||
homepage = "https://github.com/Samsung-Loki/Thor";
|
homepage = "https://github.com/Samsung-Loki/Thor";
|
||||||
description = "An alternative to Heimdall";
|
description = "An alternative to Heimdall";
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ buildPythonPackage rec {
|
|||||||
sha256 = "0wh2phg8h02a6vlpqd0widd6g8ng142vzmk8hpyx0bnwn2i45sjc";
|
sha256 = "0wh2phg8h02a6vlpqd0widd6g8ng142vzmk8hpyx0bnwn2i45sjc";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
format = "setuptools";
|
||||||
|
|
||||||
doCheck = false;
|
doCheck = false;
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
|
|||||||
Reference in New Issue
Block a user