102 lines
No EOL
3.3 KiB
Nix
102 lines
No EOL
3.3 KiB
Nix
let
|
|
lib = import <nixpkgs/lib>;
|
|
webConfig = import ../config/web.nix;
|
|
webValidation = import ../validation/web.nix;
|
|
|
|
stores = webValidation.getStores webConfig;
|
|
|
|
stripPrefix = prefix: value:
|
|
let
|
|
prefixLen = builtins.stringLength prefix;
|
|
valueLen = builtins.stringLength value;
|
|
in
|
|
if valueLen >= prefixLen && builtins.substring 0 prefixLen value == prefix then
|
|
builtins.substring prefixLen (valueLen - prefixLen) value
|
|
else
|
|
value;
|
|
|
|
trimLeadingSlash = value:
|
|
if builtins.stringLength value > 0 && builtins.substring 0 1 value == "/" then
|
|
builtins.substring 1 (builtins.stringLength value - 1) value
|
|
else
|
|
value;
|
|
|
|
findFiles = dir:
|
|
let
|
|
entries = builtins.readDir dir;
|
|
processEntry = name: type:
|
|
let
|
|
path = dir + "/${name}";
|
|
in
|
|
if type == "directory" then
|
|
findFiles path
|
|
else if type == "regular" then
|
|
[ path ]
|
|
else
|
|
[];
|
|
in
|
|
lib.concatLists (lib.mapAttrsToList processEntry entries);
|
|
|
|
detectContentType = relativePath:
|
|
if lib.hasSuffix ".html" relativePath then "text/html"
|
|
else if lib.hasSuffix ".css" relativePath then "text/css"
|
|
else if lib.hasSuffix ".js" relativePath then "application/javascript"
|
|
else if lib.hasSuffix ".json" relativePath then "application/json"
|
|
else if lib.hasSuffix ".svg" relativePath then "image/svg+xml"
|
|
else if lib.hasSuffix ".png" relativePath then "image/png"
|
|
else if lib.hasSuffix ".jpg" relativePath || lib.hasSuffix ".jpeg" relativePath then "image/jpeg"
|
|
else if lib.hasSuffix ".gif" relativePath then "image/gif"
|
|
else if lib.hasSuffix ".webp" relativePath then "image/webp"
|
|
else if lib.hasSuffix ".ico" relativePath then "image/x-icon"
|
|
else if lib.hasSuffix ".txt" relativePath then "text/plain"
|
|
else if lib.hasSuffix ".xml" relativePath then "application/xml"
|
|
else if lib.hasSuffix ".pdf" relativePath then "application/pdf"
|
|
else if lib.hasSuffix ".wasm" relativePath then "application/wasm"
|
|
else "application/octet-stream";
|
|
|
|
mkStorePath = storeName: rootPath:
|
|
builtins.path {
|
|
path = rootPath;
|
|
name = "web-store-${storeName}";
|
|
};
|
|
|
|
mkStoreFileEntries = storeName: store:
|
|
let
|
|
storeRoot = mkStorePath storeName store.root;
|
|
files = findFiles storeRoot;
|
|
|
|
mkFileEntry = filePath:
|
|
let
|
|
filePathString = toString filePath;
|
|
relative = trimLeadingSlash (stripPrefix (toString storeRoot) filePathString);
|
|
in
|
|
{
|
|
path = relative;
|
|
filePath = filePath;
|
|
contentType = detectContentType relative;
|
|
status = 200;
|
|
};
|
|
|
|
entries = map mkFileEntry files;
|
|
sortedEntries = builtins.sort (a: b: a.path < b.path) entries;
|
|
|
|
paths = map (entry: entry.path) sortedEntries;
|
|
uniquePaths = lib.unique paths;
|
|
_ =
|
|
if builtins.length paths == builtins.length uniquePaths then
|
|
null
|
|
else
|
|
throw "config/web.nix store '${storeName}' produces duplicate relative file paths in root '${toString store.root}'.";
|
|
in
|
|
sortedEntries;
|
|
|
|
storeFilesByName = lib.mapAttrs mkStoreFileEntries stores;
|
|
|
|
storePayloads = lib.mapAttrs (_: files: {
|
|
type = "store";
|
|
files = files;
|
|
}) storeFilesByName;
|
|
in
|
|
rec {
|
|
inherit stores storeFilesByName storePayloads;
|
|
} |