1290e8ed9f
The prettier-svelte package was rebuilding whenever any file in the repository changed because dashboardStubSrc referenced inputs.self directly. Since inputs.self's store path hash is computed from the entire repository contents, any file modification invalidated the derivation. Added dashboardLockfileSrc using lib.cleanSourceWith to filter inputs.self to only include package.json and package-lock.json from the dashboard directory. Updated dashboardStubSrc to reference this filtered source instead of inputs.self directly. This ensures prettier-svelte only rebuilds when the lockfiles actually change, significantly improving build caching for unrelated changes. Test plan: - Built prettier-svelte with nix build .#prettier-svelte - Modified src/exo/main.py and rebuilt - same store path (no rebuild) - Modified dashboard/package.json and rebuilt - different store path (rebuild triggered) - Ran nix flake check successfully
110 lines
4.0 KiB
Nix
110 lines
4.0 KiB
Nix
{ inputs, ... }:
|
|
{
|
|
perSystem =
|
|
{ pkgs, lib, ... }:
|
|
let
|
|
# Filter source to ONLY include package.json and package-lock.json
|
|
# This ensures prettier-svelte only rebuilds when lockfiles change
|
|
dashboardLockfileSrc = lib.cleanSourceWith {
|
|
src = inputs.self;
|
|
filter =
|
|
path: type:
|
|
let
|
|
baseName = builtins.baseNameOf path;
|
|
isDashboardDir = baseName == "dashboard" && type == "directory";
|
|
isPackageFile =
|
|
(lib.hasInfix "/dashboard/" path || lib.hasSuffix "/dashboard" (builtins.dirOf path))
|
|
&& (baseName == "package.json" || baseName == "package-lock.json");
|
|
in
|
|
isDashboardDir || isPackageFile;
|
|
};
|
|
|
|
# Stub source with lockfiles and minimal files for build to succeed
|
|
# This allows prettier-svelte to avoid rebuilding when dashboard source changes
|
|
dashboardStubSrc = pkgs.runCommand "dashboard-stub-src" { } ''
|
|
mkdir -p $out
|
|
cp ${dashboardLockfileSrc}/dashboard/package.json $out/
|
|
cp ${dashboardLockfileSrc}/dashboard/package-lock.json $out/
|
|
# Minimal files so vite build succeeds (produces empty output)
|
|
echo '<!DOCTYPE html><html><head></head><body></body></html>' > $out/index.html
|
|
mkdir -p $out/src
|
|
touch $out/src/app.html
|
|
'';
|
|
|
|
# Deps-only build using stub source (for prettier-svelte)
|
|
# Only rebuilds when package.json or package-lock.json change
|
|
dashboardDeps = inputs.dream2nix.lib.evalModules {
|
|
packageSets.nixpkgs = pkgs;
|
|
modules = [
|
|
./dashboard.nix
|
|
{
|
|
paths.projectRoot = inputs.self;
|
|
paths.projectRootFile = "flake.nix";
|
|
paths.package = inputs.self + "/dashboard";
|
|
}
|
|
{
|
|
deps.dashboardSrc = lib.mkForce dashboardStubSrc;
|
|
}
|
|
# Override build phases to skip the actual build - just need node_modules
|
|
{
|
|
mkDerivation = {
|
|
buildPhase = lib.mkForce "true";
|
|
installPhase = lib.mkForce ''
|
|
runHook preInstall
|
|
runHook postInstall
|
|
'';
|
|
};
|
|
}
|
|
];
|
|
};
|
|
|
|
# Filter source to only include dashboard directory
|
|
dashboardSrc = lib.cleanSourceWith {
|
|
src = inputs.self;
|
|
filter =
|
|
path: type:
|
|
let
|
|
baseName = builtins.baseNameOf path;
|
|
inDashboardDir =
|
|
(lib.hasInfix "/dashboard/" path)
|
|
|| (lib.hasSuffix "/dashboard" (builtins.dirOf path))
|
|
|| (baseName == "dashboard" && type == "directory");
|
|
in
|
|
inDashboardDir;
|
|
};
|
|
|
|
# Build the dashboard with dream2nix (includes node_modules in output)
|
|
dashboardFull = inputs.dream2nix.lib.evalModules {
|
|
packageSets.nixpkgs = pkgs;
|
|
modules = [
|
|
./dashboard.nix
|
|
{
|
|
paths.projectRoot = inputs.self;
|
|
paths.projectRootFile = "flake.nix";
|
|
paths.package = inputs.self + "/dashboard";
|
|
}
|
|
# Inject the filtered source
|
|
{
|
|
deps.dashboardSrc = lib.mkForce "${dashboardSrc}/dashboard";
|
|
}
|
|
];
|
|
};
|
|
in
|
|
{
|
|
# Extract just the static site from the full build
|
|
packages.dashboard = pkgs.runCommand "exo-dashboard" { } ''
|
|
cp -r ${dashboardFull}/build $out
|
|
'';
|
|
|
|
# Prettier with svelte plugin for treefmt
|
|
# Uses dashboardDeps instead of dashboardFull to avoid rebuilding on source changes
|
|
packages.prettier-svelte = pkgs.writeShellScriptBin "prettier-svelte" ''
|
|
export NODE_PATH="${dashboardDeps}/lib/node_modules/exo-dashboard/node_modules"
|
|
exec ${pkgs.nodejs}/bin/node \
|
|
${dashboardDeps}/lib/node_modules/exo-dashboard/node_modules/prettier/bin/prettier.cjs \
|
|
--plugin "${dashboardDeps}/lib/node_modules/exo-dashboard/node_modules/prettier-plugin-svelte/plugin.js" \
|
|
"$@"
|
|
'';
|
|
};
|
|
}
|