2023-08-27 07:48:57 +02:00
|
|
|
# flakelight -- Framework for simplifying flake setup
|
2023-08-25 06:14:55 +02:00
|
|
|
# Copyright (C) 2023 Archit Gupta <archit@accelbread.com>
|
|
|
|
# SPDX-License-Identifier: MIT
|
|
|
|
|
2024-01-10 10:16:24 +01:00
|
|
|
{ config, lib, flakelight, genSystems, ... }:
|
2023-08-25 06:14:55 +02:00
|
|
|
let
|
2024-02-22 03:43:05 +01:00
|
|
|
inherit (builtins) match storeDir;
|
|
|
|
inherit (lib) defaultFunctor fix isFunction last mapAttrs mergeDefinitions
|
|
|
|
mkIf mkMerge mkOption mkOptionType;
|
|
|
|
inherit (lib.types) coercedTo enum lazyAttrsOf
|
2024-03-21 12:10:38 +01:00
|
|
|
optionDescriptionPhrase pathInStore submoduleWith;
|
2024-02-22 03:43:05 +01:00
|
|
|
inherit (flakelight.types) nullable optFunctionTo stringLike;
|
|
|
|
|
|
|
|
isStorePath = s: match "${storeDir}/[^.][^ \n]*" s != null;
|
2024-02-20 10:25:27 +01:00
|
|
|
|
2024-03-21 12:10:38 +01:00
|
|
|
app = submoduleWith {
|
|
|
|
modules = [{
|
|
|
|
options = {
|
|
|
|
type = mkOption { type = enum [ "app" ]; default = "app"; };
|
|
|
|
program = mkOption { type = pathInStore // { check = isStorePath; }; };
|
|
|
|
};
|
|
|
|
}];
|
2024-02-20 10:25:27 +01:00
|
|
|
};
|
|
|
|
|
2024-02-22 03:43:05 +01:00
|
|
|
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;
|
2023-08-25 06:14:55 +02:00
|
|
|
|
2024-02-22 03:43:05 +01:00
|
|
|
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;
|
|
|
|
}));
|
2023-08-25 06:14:55 +02:00
|
|
|
in
|
|
|
|
{
|
|
|
|
options = {
|
|
|
|
app = mkOption {
|
2024-02-20 10:25:27 +01:00
|
|
|
type = nullable appType;
|
2023-08-25 06:14:55 +02:00
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
|
|
|
|
apps = mkOption {
|
2024-02-20 10:25:27 +01:00
|
|
|
type = nullable (optFunctionTo (lazyAttrsOf appType));
|
2023-08-25 06:14:55 +02:00
|
|
|
default = null;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
config = mkMerge [
|
|
|
|
(mkIf (config.app != null) {
|
|
|
|
apps.default = config.app;
|
|
|
|
})
|
|
|
|
|
|
|
|
(mkIf (config.apps != null) {
|
2024-01-10 10:16:24 +01:00
|
|
|
outputs.apps = genSystems (pkgs:
|
2024-02-20 10:25:27 +01:00
|
|
|
mapAttrs (_: v: v pkgs) (config.apps pkgs));
|
2023-08-25 06:14:55 +02:00
|
|
|
})
|
|
|
|
];
|
|
|
|
}
|