1
1
forked from extern/flakelight
flakelight/builtinModules/apps.nix
Archit Gupta e72626b0a9 Allow apps to be scripts
This enables setting the app to arbitrary bash scripts which will be
written to a store path and used for the app's program attr.
2024-02-24 21:31:24 -08:00

84 lines
2.4 KiB
Nix

# flakelight -- Framework for simplifying flake setup
# Copyright (C) 2023 Archit Gupta <archit@accelbread.com>
# SPDX-License-Identifier: MIT
{ config, lib, flakelight, genSystems, ... }:
let
inherit (builtins) match storeDir;
inherit (lib) defaultFunctor fix isFunction last mapAttrs mergeDefinitions
mkIf mkMerge mkOption mkOptionType;
inherit (lib.types) coercedTo enum lazyAttrsOf
optionDescriptionPhrase pathInStore submodule;
inherit (flakelight.types) nullable optFunctionTo stringLike;
isStorePath = s: match "${storeDir}/[^.][^ \n]*" s != null;
app = submodule {
options = {
type = mkOption { type = enum [ "app" ]; default = "app"; };
program = mkOption { type = pathInStore // { check = isStorePath; }; };
};
};
mkApp = name: pkgs: s:
let s' = "${s}"; in {
program =
if isStorePath s' then s'
else "${pkgs.writeShellScript "app-${name}" s'}";
};
parameterize = value: fn: fix fn value;
appType = parameterize app (self': app: (mkOptionType rec {
name = "appType";
description =
let
targetDesc = optionDescriptionPhrase
(class: class == "noun" || class == "composite")
(coercedTo stringLike (abort "") app);
in
"${targetDesc} or function that evaluates to it";
descriptionClass = "composite";
check = x: isFunction x || app.check x || stringLike.check x;
merge = loc: defs: pkgs:
let
targetType = coercedTo stringLike (mkApp (last loc) pkgs) app;
in
(mergeDefinitions loc targetType (map
(fn: {
inherit (fn) file;
value = if isFunction fn.value then fn.value pkgs else fn.value;
})
defs)).mergedValue;
inherit (app) getSubOptions getSubModules;
substSubModules = m: self' (app.substSubModules m);
functor = (defaultFunctor name) // { wrapped = app; };
nestedTypes.coercedType = stringLike;
nestedTypes.finalType = app;
}));
in
{
options = {
app = mkOption {
type = nullable appType;
default = null;
};
apps = mkOption {
type = nullable (optFunctionTo (lazyAttrsOf appType));
default = null;
};
};
config = mkMerge [
(mkIf (config.app != null) {
apps.default = config.app;
})
(mkIf (config.apps != null) {
outputs.apps = genSystems (pkgs:
mapAttrs (_: v: v pkgs) (config.apps pkgs));
})
];
}