Initial commit
germanium cutoff
This commit is contained in:
@@ -0,0 +1,497 @@
|
||||
let
|
||||
mkSchemaSupport =
|
||||
{
|
||||
pkgs,
|
||||
inputs,
|
||||
system,
|
||||
self ? null,
|
||||
flakeRoot,
|
||||
schemaDir,
|
||||
schemaPrefix ? "packageSchema_",
|
||||
schemaBuildCommand ? "yarn build",
|
||||
schemaTypecheckCommand ? "yarn typecheck",
|
||||
nodejs ? pkgs.nodejs_24,
|
||||
git ? pkgs.git,
|
||||
}:
|
||||
let
|
||||
schemaPackageJson = builtins.fromJSON (builtins.readFile "${schemaDir}/package.json");
|
||||
schemaMainPath = schemaPackageJson.main or "dist/qx-package-schema.js";
|
||||
schemaMainPathDefault = "dist/qx-package-schema.js";
|
||||
schemaPackageName = schemaPackageJson.name or "schema";
|
||||
selfSchemaName =
|
||||
if pkgs.lib.hasInfix "/" schemaPackageName
|
||||
then pkgs.lib.last (pkgs.lib.splitString "/" schemaPackageName)
|
||||
else schemaPackageName;
|
||||
|
||||
flakeText =
|
||||
builtins.replaceStrings
|
||||
[ "\n" "\r" "\t" ]
|
||||
[ " " " " " " ]
|
||||
(builtins.readFile "${flakeRoot}/flake.nix");
|
||||
|
||||
getInputUrl = inputName:
|
||||
let
|
||||
pattern1 = ".*" + inputName + "[[:space:]]*\\.url[[:space:]]*=[[:space:]]*\"([^\"]+)\".*";
|
||||
pattern2 = ".*" + inputName + "[[:space:]]*=[[:space:]]*\\{[^}]*url[[:space:]]*=[[:space:]]*\"([^\"]+)\".*";
|
||||
match1 = builtins.match pattern1 flakeText;
|
||||
match2 = if match1 != null then match1 else builtins.match pattern2 flakeText;
|
||||
in if match2 == null then null else builtins.elemAt match2 0;
|
||||
|
||||
schemaBase =
|
||||
(pkgs.callPackage "${schemaDir}/yarn-project.nix" {
|
||||
inherit nodejs git;
|
||||
})
|
||||
{
|
||||
# avoid pulling .git, etc.
|
||||
src = pkgs.lib.cleanSource schemaDir;
|
||||
};
|
||||
|
||||
schema = schemaBase.overrideAttrs (old: {
|
||||
buildPhase = (old.buildPhase or "") + ''
|
||||
runHook preBuild
|
||||
${schemaBuildCommand}
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
});
|
||||
|
||||
schemaCheck = schema.overrideAttrs (old: {
|
||||
doCheck = true;
|
||||
|
||||
checkPhase = (old.checkPhase or "") + ''
|
||||
runHook preCheck
|
||||
${schemaTypecheckCommand}
|
||||
runHook postCheck
|
||||
'';
|
||||
});
|
||||
|
||||
schemaInputs =
|
||||
pkgs.lib.filterAttrs (name: _: pkgs.lib.hasPrefix schemaPrefix name) inputs;
|
||||
|
||||
decodeSchemaInputName = encodedName:
|
||||
builtins.replaceStrings [ "__" ] [ "." ] encodedName;
|
||||
|
||||
schemaPackagesFromInputs =
|
||||
pkgs.lib.mapAttrs'
|
||||
(name: flake:
|
||||
let
|
||||
schemaName =
|
||||
decodeSchemaInputName (pkgs.lib.removePrefix schemaPrefix name);
|
||||
in
|
||||
{
|
||||
name = schemaName;
|
||||
value = flake.packages.${system}.schema;
|
||||
})
|
||||
schemaInputs;
|
||||
|
||||
schemaPackages = schemaPackagesFromInputs // { "${selfSchemaName}" = schema; };
|
||||
|
||||
schemaMetaByName =
|
||||
pkgs.lib.mapAttrs'
|
||||
(name: flake:
|
||||
let
|
||||
schemaName =
|
||||
decodeSchemaInputName (pkgs.lib.removePrefix schemaPrefix name);
|
||||
sourceInfo = if flake ? sourceInfo then flake.sourceInfo else { };
|
||||
sourceRev = sourceInfo.rev or null;
|
||||
inputUrl = getInputUrl name;
|
||||
urlBase =
|
||||
if inputUrl == null
|
||||
then null
|
||||
else builtins.head (pkgs.lib.splitString "?" inputUrl);
|
||||
isDisallowed =
|
||||
inputUrl == null
|
||||
|| pkgs.lib.hasPrefix "path:" inputUrl
|
||||
|| pkgs.lib.hasPrefix "file:" inputUrl
|
||||
|| pkgs.lib.hasPrefix "git+file:" inputUrl;
|
||||
flakeRef =
|
||||
if isDisallowed || sourceRev == null || urlBase == null
|
||||
then null
|
||||
else urlBase + "?rev=" + sourceRev;
|
||||
meta =
|
||||
{
|
||||
name = "@qx-package-schemas/${schemaName}";
|
||||
type = sourceInfo.type or null;
|
||||
url = inputUrl;
|
||||
rev = sourceRev;
|
||||
flakeRef = flakeRef;
|
||||
};
|
||||
in
|
||||
if flakeRef == null
|
||||
then throw "Schema input ${schemaName} must be a git flake with url+rev"
|
||||
else {
|
||||
name = schemaName;
|
||||
value = meta;
|
||||
})
|
||||
schemaInputs;
|
||||
|
||||
schemaMetaJsonByName =
|
||||
pkgs.lib.mapAttrs (_: meta: builtins.toJSON meta) schemaMetaByName;
|
||||
|
||||
schemaExtensionsBlock = pkgs.lib.concatStringsSep "\n" (
|
||||
[
|
||||
"packageExtensions:"
|
||||
" \"qx-package@*\":"
|
||||
" dependencies:"
|
||||
]
|
||||
++ pkgs.lib.mapAttrsToList (
|
||||
name: _: " \"@qx-package-schemas/${name}\": \"portal:./qx-package-schemas/${name}\""
|
||||
) schemaPackages
|
||||
);
|
||||
|
||||
schemaExtensionsBlockEscaped = pkgs.lib.escapeShellArg schemaExtensionsBlock;
|
||||
|
||||
schemaLinkCommands = pkgs.lib.concatStringsSep "\n" (
|
||||
pkgs.lib.mapAttrsToList (name: drv: ''
|
||||
schema_pkg="$(ls -d ${drv}/libexec/* 2>/dev/null | head -n1 || true)"
|
||||
if [ -n "$schema_pkg" ]; then
|
||||
ln -sfn "$schema_pkg" qx-package-schemas/${name}
|
||||
fi
|
||||
'') schemaPackages
|
||||
);
|
||||
|
||||
schemaInstallCommands = pkgs.lib.concatStringsSep "\n" (
|
||||
pkgs.lib.mapAttrsToList (name: drv:
|
||||
let
|
||||
metaJson =
|
||||
if pkgs.lib.hasAttr name schemaMetaJsonByName
|
||||
then schemaMetaJsonByName.${name}
|
||||
else null;
|
||||
in
|
||||
''
|
||||
schema_pkg="$(ls -d ${drv}/libexec/* | head -n1)"
|
||||
dest="qx-package-schemas/${name}"
|
||||
rm -rf "$dest"
|
||||
cp -R --no-preserve=mode,ownership "$schema_pkg" "$dest"
|
||||
chmod -R u+w "$dest"
|
||||
''
|
||||
+ (
|
||||
if metaJson != null
|
||||
then ''
|
||||
schema_main="${schemaMainPathDefault}"
|
||||
if [ -f "$dest/$schema_main" ]; then
|
||||
block_tmp="$(mktemp -p "$dest")"
|
||||
tmp_out="$(mktemp -p "$dest")"
|
||||
cat > "$block_tmp" <<'EOF'
|
||||
packageSchema.__qx = ${metaJson};
|
||||
EOF
|
||||
chmod u+w "$dest/$schema_main"
|
||||
if grep -q '^export default ' "$dest/$schema_main"; then
|
||||
awk -v blockFile="$block_tmp" '
|
||||
BEGIN {
|
||||
while ((getline line < blockFile) > 0) {
|
||||
block = block line "\n"
|
||||
}
|
||||
}
|
||||
!inserted && /^export default / { printf "%s", block; inserted=1 }
|
||||
{ print }
|
||||
' "$dest/$schema_main" > "$tmp_out"
|
||||
cat "$tmp_out" > "$dest/$schema_main"
|
||||
elif grep -q '^//# sourceMappingURL=' "$dest/$schema_main"; then
|
||||
awk -v blockFile="$block_tmp" '
|
||||
BEGIN {
|
||||
while ((getline line < blockFile) > 0) {
|
||||
block = block line "\n"
|
||||
}
|
||||
}
|
||||
/^\/\/# sourceMappingURL=/ { printf "%s", block; print; next }
|
||||
{ print }
|
||||
' "$dest/$schema_main" > "$tmp_out"
|
||||
cat "$tmp_out" > "$dest/$schema_main"
|
||||
else
|
||||
printf '\n' >> "$dest/$schema_main"
|
||||
cat "$block_tmp" >> "$dest/$schema_main"
|
||||
fi
|
||||
rm -f "$block_tmp" "$tmp_out"
|
||||
fi
|
||||
''
|
||||
else ""
|
||||
)
|
||||
) schemaPackages
|
||||
);
|
||||
|
||||
updateYarnrcScript = ''
|
||||
qx_package_schemas_update_yarnrc() {
|
||||
local yarnrc=".yarnrc.yml"
|
||||
local tmp="$(mktemp)"
|
||||
local block_tmp="$(mktemp)"
|
||||
printf '%s\n' ${schemaExtensionsBlockEscaped} > "$block_tmp"
|
||||
awk -v blockFile="$block_tmp" '
|
||||
BEGIN {
|
||||
while ((getline line < blockFile) > 0) {
|
||||
block = block line "\n"
|
||||
}
|
||||
}
|
||||
/^# BEGIN packageExtensions/ {print; printf "%s", block; skip=1; next}
|
||||
/^# END packageExtensions/ {skip=0; print; next}
|
||||
!skip {print}
|
||||
' "$yarnrc" > "$tmp"
|
||||
mv "$tmp" "$yarnrc"
|
||||
rm -f "$block_tmp"
|
||||
}
|
||||
'';
|
||||
in
|
||||
{
|
||||
inherit
|
||||
schema
|
||||
schemaCheck
|
||||
schemaPackages
|
||||
schemaLinkCommands
|
||||
schemaInstallCommands
|
||||
updateYarnrcScript
|
||||
schemaExtensionsBlockEscaped
|
||||
selfSchemaName;
|
||||
};
|
||||
|
||||
mkTsPackageServer =
|
||||
{
|
||||
srcDir,
|
||||
serverBin ? "server",
|
||||
nodejs ? null,
|
||||
git ? null,
|
||||
templatePreparePackages ? null,
|
||||
buildCommand ? null,
|
||||
typecheckCommand ? "yarn typecheck",
|
||||
serverOverrides ? (old: { }),
|
||||
}:
|
||||
{
|
||||
pkgs,
|
||||
schemaSupport,
|
||||
extraBuildInputs ? [ ],
|
||||
extraNativeBuildInputs ? [ ],
|
||||
extraRuntimePackages ? [ ],
|
||||
}:
|
||||
let
|
||||
nodejs' = if nodejs != null then nodejs else pkgs.nodejs_24;
|
||||
git' = if git != null then git else pkgs.git;
|
||||
templatePreparePackages' =
|
||||
if templatePreparePackages != null
|
||||
then templatePreparePackages
|
||||
else [
|
||||
pkgs.findutils
|
||||
git'
|
||||
pkgs.gnused
|
||||
nodejs'
|
||||
pkgs.yarn-berry_4
|
||||
];
|
||||
|
||||
packageJson = builtins.fromJSON (builtins.readFile "${srcDir}/package.json");
|
||||
packageName = packageJson.name or "qx-package";
|
||||
|
||||
base =
|
||||
(pkgs.callPackage "${srcDir}/yarn-project.nix" {
|
||||
nodejs = nodejs';
|
||||
git = git';
|
||||
})
|
||||
{
|
||||
# avoid pulling .git, etc.
|
||||
src = pkgs.lib.cleanSource srcDir;
|
||||
};
|
||||
|
||||
runtimeBinPath = pkgs.lib.makeBinPath extraRuntimePackages;
|
||||
runtimeLibPath = pkgs.lib.makeLibraryPath extraRuntimePackages;
|
||||
runtimeWrap =
|
||||
if extraRuntimePackages == [ ]
|
||||
then ""
|
||||
else ''
|
||||
wrapProgram "$out/bin/${serverBin}" \
|
||||
--prefix PATH : ${runtimeBinPath} \
|
||||
--prefix LD_LIBRARY_PATH : ${runtimeLibPath}
|
||||
'';
|
||||
|
||||
server = base.overrideAttrs (old:
|
||||
let
|
||||
extraAttrs = serverOverrides old;
|
||||
in
|
||||
{
|
||||
buildInputs = (old.buildInputs or [ ]) ++ extraBuildInputs;
|
||||
|
||||
nativeBuildInputs = (old.nativeBuildInputs or [ ]) ++ [
|
||||
pkgs.python3
|
||||
pkgs.gnumake
|
||||
pkgs.gcc
|
||||
pkgs.pkg-config
|
||||
pkgs.makeWrapper
|
||||
] ++ extraNativeBuildInputs;
|
||||
|
||||
# node-gyp will look at these
|
||||
PYTHON = "${pkgs.python3}/bin/python3";
|
||||
npm_config_python = "${pkgs.python3}/bin/python3";
|
||||
|
||||
preConfigure = (old.preConfigure or "") + ''
|
||||
mkdir -p qx-package-schemas
|
||||
${schemaSupport.schemaLinkCommands}
|
||||
'';
|
||||
|
||||
buildPhase =
|
||||
(old.buildPhase or "")
|
||||
+ (
|
||||
if buildCommand != null
|
||||
then ''
|
||||
runHook preBuildQx
|
||||
${buildCommand}
|
||||
runHook postBuildQx
|
||||
''
|
||||
else ""
|
||||
);
|
||||
|
||||
postFixup = (old.postFixup or "") + runtimeWrap;
|
||||
|
||||
postInstall = (old.postInstall or "") + ''
|
||||
pkg_root="$out/libexec/${old.name}"
|
||||
mkdir -p "$pkg_root/qx-package-schemas"
|
||||
(cd "$pkg_root" && ${schemaSupport.schemaInstallCommands})
|
||||
'';
|
||||
} // extraAttrs
|
||||
);
|
||||
|
||||
check = server.overrideAttrs (old: {
|
||||
doCheck = true;
|
||||
|
||||
checkPhase = (old.checkPhase or "") + ''
|
||||
runHook preCheck
|
||||
${typecheckCommand}
|
||||
runHook postCheck
|
||||
'';
|
||||
});
|
||||
|
||||
prepareShell = pkgs.mkShell {
|
||||
packages = templatePreparePackages';
|
||||
};
|
||||
in
|
||||
{
|
||||
inherit server check packageName serverBin;
|
||||
|
||||
devShells = {
|
||||
"qx-prepare" = prepareShell;
|
||||
};
|
||||
};
|
||||
|
||||
mkQxPackageFlake =
|
||||
{
|
||||
self ? null,
|
||||
inputs,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
flakeRoot,
|
||||
schemaDir,
|
||||
schemaPrefix ? "packageSchema_",
|
||||
serverBuilder,
|
||||
packageName ? null,
|
||||
extraBuildInputs ? (pkgs: [ ]),
|
||||
extraNativeBuildInputs ? (pkgs: [ ]),
|
||||
extraRuntimePackages ? (pkgs: [ ]),
|
||||
extraDevShellPackages ? (pkgs: [ ]),
|
||||
enableYarnrcHook ? true,
|
||||
extraDevShellHook ? "",
|
||||
appProgram ? null,
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (
|
||||
system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
|
||||
schemaSupport = mkSchemaSupport {
|
||||
inherit pkgs inputs system schemaDir schemaPrefix self flakeRoot;
|
||||
};
|
||||
|
||||
normalizeList = value:
|
||||
if builtins.isFunction value
|
||||
then value pkgs
|
||||
else value;
|
||||
|
||||
serverResult = serverBuilder {
|
||||
inherit pkgs schemaSupport;
|
||||
extraBuildInputs = normalizeList extraBuildInputs;
|
||||
extraNativeBuildInputs = normalizeList extraNativeBuildInputs;
|
||||
extraRuntimePackages = normalizeList extraRuntimePackages;
|
||||
};
|
||||
|
||||
combinedName = pkgs.lib.strings.sanitizeDerivationName (
|
||||
if packageName != null
|
||||
then packageName
|
||||
else if serverResult ? packageName
|
||||
then serverResult.packageName
|
||||
else "qx-package"
|
||||
);
|
||||
|
||||
packageServer = serverResult.server;
|
||||
packageServerCheck = if serverResult ? check then serverResult.check else null;
|
||||
|
||||
appProgramFinal =
|
||||
if appProgram != null
|
||||
then appProgram
|
||||
else if serverResult ? appProgram
|
||||
then serverResult.appProgram
|
||||
else "${packageServer}/bin/${serverResult.serverBin or "server"}";
|
||||
|
||||
devShellHookBase =
|
||||
if enableYarnrcHook
|
||||
then ''
|
||||
find_schema_root() {
|
||||
dir="$PWD"
|
||||
while [ "$dir" != "/" ]; do
|
||||
if [ -f "$dir/src/.yarnrc.yml" ] && [ -d "$dir/schema" ]; then
|
||||
printf "%s\n" "$dir"
|
||||
return 0
|
||||
fi
|
||||
dir="$(dirname "$dir")"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
${schemaSupport.updateYarnrcScript}
|
||||
|
||||
link_schemas() {
|
||||
mkdir -p qx-package-schemas
|
||||
${schemaSupport.schemaLinkCommands}
|
||||
}
|
||||
|
||||
base="$(find_schema_root || true)"
|
||||
if [ -n "$base" ]; then
|
||||
(cd "$base/src" && link_schemas && qx_package_schemas_update_yarnrc)
|
||||
if [ -d "$base/schema" ]; then
|
||||
ln -sfn "$base/schema" "$base/src/qx-package-schemas/${schemaSupport.selfSchemaName}"
|
||||
fi
|
||||
fi
|
||||
''
|
||||
else "";
|
||||
|
||||
devShellHook = devShellHookBase + extraDevShellHook;
|
||||
|
||||
devShellPackages = normalizeList extraDevShellPackages;
|
||||
|
||||
checks =
|
||||
{ schema = schemaSupport.schemaCheck; }
|
||||
// (if packageServerCheck != null then { default = packageServerCheck; } else { });
|
||||
extraDevShells = if serverResult ? devShells then serverResult.devShells else { };
|
||||
in
|
||||
{
|
||||
packages.default = pkgs.symlinkJoin {
|
||||
name = combinedName;
|
||||
paths = [ packageServer schemaSupport.schema ];
|
||||
};
|
||||
packages.server = packageServer;
|
||||
packages.schema = schemaSupport.schema;
|
||||
|
||||
apps.default = {
|
||||
type = "app";
|
||||
program = appProgramFinal;
|
||||
meta.description = "Quixos package server";
|
||||
};
|
||||
|
||||
checks = checks;
|
||||
|
||||
devShells = extraDevShells // {
|
||||
default = pkgs.mkShell {
|
||||
inputsFrom = [ packageServer ] ++ builtins.attrValues schemaSupport.schemaPackages;
|
||||
packages = devShellPackages;
|
||||
shellHook = devShellHook;
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
in
|
||||
{
|
||||
inherit mkQxPackageFlake mkTsPackageServer mkSchemaSupport;
|
||||
}
|
||||
Reference in New Issue
Block a user