{ pkgs }: let inherit (pkgs) lib; in { mkWrapper = { config, name, enableTui ? false, modules ? [ ], }: let merged_config = lib.foldl' (acc: elem: acc // elem.config) config modules; checks = lib.concatStringsSep "\n" ( lib.concatMap ( attrs: lib.mapAttrsToList (k: v: '' echo "Running ${k}" ${v} echo "Passed ${k}" '') attrs.checks ) modules ); removeNullAndEmptyAttrs = attrs: let f = lib.filterAttrsRecursive (key: value: value != null && value != { }); in # filterAttrsRecursive doesn't delete the *resulting* empty attrs, so we must # evaluate it again and to get rid of it. lib.pipe attrs [ f f ]; toPCJson = name: attrs: pkgs.writeTextFile { name = "process-compose-${name}.json"; text = builtins.toJSON attrs; }; configFile = toPCJson name ( removeNullAndEmptyAttrs ( merged_config // { is_tui_disabled = !enableTui; } ) ); in pkgs.writeShellApplication { inherit name; text = '' ${checks} PC_CONFIG_FILES=${configFile} ${pkgs.process-compose}/bin/process-compose "$@" ''; }; mkPostgres = { name, default_config ? true, config ? { }, extra_config ? '''', package ? pkgs.postgresql, ... }: let merged_config = ( if default_config then { listen_addresses = "localhost"; port = 5432; shared_buffers = "128MB"; worker_mem = "4M"; logging_collector = "off"; } else { } ) // config; toStr = value: if true == value then "yes" else if false == value then "no" else if lib.isString value then "'${lib.replaceStrings [ "'" ] [ "''" value ]}'" else builtins.toString value; configFile = pkgs.writeTextDir "postgresql.conf" ( lib.concatStringSep "\n" ( lib.mapAttrsToList (n: v: "${n} = ${toStr v}") (lib.filterAttrs ( lib.const (x: x != null) )) merged_config ) ); configFileCheck = pkgs.writeShellScript { name = "postgresql-config-check-${name}"; text = '' ${package}/bin/postgres -D${configFile} -C config_file touch $out ''; }; in { config.processes."${name}" = { }; checks."postgresql${name}" = configFileCheck; }; }