diff --git a/pkgs/by-name/de/deno/fetch-deps/default.nix b/pkgs/by-name/de/deno/fetch-deps/default.nix new file mode 100644 index 0000000000000..01817a1b394bc --- /dev/null +++ b/pkgs/by-name/de/deno/fetch-deps/default.nix @@ -0,0 +1,107 @@ +{ + lib, + stdenv, + deno, + jq, +}: +{ + hash ? "", + pname, + denoLock ? "", + denoJson ? "", + denoEntrypoints ? [ ], + preDenoInstall ? "", + denoInstallFlags ? [ ], + ... +}@args: +let + args' = builtins.removeAttrs args [ + "hash" + "pname" + ]; +in +stdenv.mkDerivation ( + args' + // { + name = "${pname}-deno-deps"; + + nativeBuildInputs = [ + deno + jq + ]; + + dontConfigure = true; + dontBuild = true; + + denoInstallFlags = + (lib.cli.toGNUCommandLine { } { + vendor = true; + frozen = true; + node-modules-dir = true; + entrypoint = if denoEntrypoints == [ ] then null else denoEntrypoints; + }) + ++ denoInstallFlags; + + inherit denoLock denoJson denoEntrypoints; + + installPhase = '' + export DENO_DIR=$(mktemp -d) + export DENO_NO_UPDATE_CHECK=true + + if [[ -z "$denoLock" ]]; then + echo "autodetecting lock file" + else + if [[ ! -f "$denoLock" ]]; then + echo "error: lock file '$denoLock' is specified but not found" >&2 + exit 1 + fi + cp "$denoLock" deno.lock + fi + + if [[ -z "$denoJson" ]]; then + echo "autodetecting Deno config" + else + if [[ ! -f "$denoJson" ]]; then + echo "error: Deno config '$denoJson' is specified but not found" >&2 + exit 1 + fi + cp "$denoJson" deno.json + fi + + for entrypoint in "''${denoEntrypoints[@]}"; do + if [[ -n "$entrypoint" && ! -f "$entrypoint" ]]; then + echo "error: entrypoint '$entrypoint' is specified but not found" >&2 + exit 1 + fi + done + + ${preDenoInstall} + + deno install ''${denoInstallFlags[@]} + + # Remove redundant & unreproducible files + rm -f node_modules/.deno/.deno.lock{,.poll} + + # TODO: I'm not exactly sure if this is necessary anymore + if [[ -f vendor/manifest.json ]]; then + jq -S '.' vendor/manifest.json > vendor/manifest.json.tmp + mv vendor/manifest.json.tmp vendor/manifest.json + fi + + + mkdir -p $out + [[ -d node_modules ]] && cp -a node_modules -t $out || true + [[ -d vendor ]] && cp -a vendor -t $out || true + [[ -n deno.json ]] && cp deno.json -t $out || true + [[ -n deno.lock ]] && cp deno.lock -t $out || true + ''; + + dontFixup = true; + + outputHash = hash; + outputHashMode = "recursive"; + } + // lib.optionalAttrs (hash == "") { + outputHashAlgo = "sha256"; + } +) diff --git a/pkgs/by-name/de/deno/hooks/compile-hook.sh b/pkgs/by-name/de/deno/hooks/compile-hook.sh new file mode 100644 index 0000000000000..6db8f80a7f8a0 --- /dev/null +++ b/pkgs/by-name/de/deno/hooks/compile-hook.sh @@ -0,0 +1,51 @@ +# shellcheck shell=bash + +denoCompileBuildPhase() { + export DENORT_BIN="@deno@/bin/denort" + export DENO_COMPILE_OUT=$(mktemp -d) + + if [[ -z "${denoCompileEntrypoints[@]}" ]]; then + if [[ -z "${denoEntrypoints[@]}" ]]; then + echo "error: neither denoEntrypoints nor denoCompileEntrypoints is set - can't compile anything!" >&2 + exit 1 + fi + + denoCompileEntrypoints=("${denoEntrypoints[@]}") + fi + for entrypoint in "${denoCompileEntrypoints[@]}"; do + if [[ -n "$entrypoint" && ! -f "$entrypoint" ]]; then + echo "error: entrypoint '$entrypoint' is specified but not found" >&2 + exit 1 + fi + done + + deno compile \ + --output $DENO_COMPILE_OUT/ \ + --cached-only \ + --vendor \ + --node-modules-dir \ + ${denoCompileFlags[@]} \ + ${denoCompileEntrypoints[@]} + + # `deno compile` works by inserting JavaScript in the data segments of the executables. + # Stripping them would just completely defeat the point and render the executable unusable. + for file in $DENO_COMPILE_OUT/*; do + stripExclude+=("${file#"$DENO_COMPILE_OUT/"}") + done +} + +denoCompileInstallPhase() { + mkdir -p $out/bin + cp -a $DENO_COMPILE_OUT/. -t $out/bin +} + +# Why don't we have any kind of dontDenoCompile flag? Because if you don't want to run `deno compile`, +# you shouldn't include this hook in your nativeBuildInputs. Simple as. +if [[ -z "${buildPhase-}" ]]; then + setOutputFlags= + buildPhase=denoCompileBuildPhase +fi +if [[ -z "${installPhase-}" ]]; then + setOutputFlags= + installPhase=denoCompileInstallPhase +fi diff --git a/pkgs/by-name/de/deno/hooks/setup-hook.sh b/pkgs/by-name/de/deno/hooks/setup-hook.sh new file mode 100644 index 0000000000000..43f6ad9dd0a60 --- /dev/null +++ b/pkgs/by-name/de/deno/hooks/setup-hook.sh @@ -0,0 +1,36 @@ +# shellcheck shell=bash + +denoConfigHook() { + echo "Executing denoConfigHook" + + if [[ -n "${denoRoot-}" ]]; then + pushd "$denoRoot" + fi + + if [[ -z "${denoDeps-}" ]]; then + echo "denoDeps not set - skipping" + exit 0 + fi + + export DENO_DIR=$(mktemp -d) + + if [[ -d $denoDeps/node_modules ]]; then + cp -a $denoDeps/node_modules -t . + chmod -R +w node_modules + + echo "Patching scripts" + patchShebangs node_modules/{*,.*} + fi + + [[ -d $denoDeps/vendor ]] && cp -a $denoDeps/vendor -t . || true + [[ -f $denoDeps/deno.json ]] && cp $denoDeps/deno.json deno.json || true + [[ -f $denoDeps/deno.lock ]] && cp $denoDeps/deno.lock deno.lock || true + + if [[ -n "${denoRoot-}" ]]; then + popd + fi + + echo "Finished denoConfigHook" +} + +postConfigureHooks+=(denoConfigHook) diff --git a/pkgs/by-name/de/deno/package.nix b/pkgs/by-name/de/deno/package.nix index ae16f88a4e85a..9ddbd7f56484e 100644 --- a/pkgs/by-name/de/deno/package.nix +++ b/pkgs/by-name/de/deno/package.nix @@ -12,6 +12,8 @@ librusty_v8 ? callPackage ./librusty_v8.nix { inherit (callPackage ./fetchers.nix { }) fetchLibrustyV8; }, + makeSetupHook, + deno, }: let @@ -83,8 +85,20 @@ rustPlatform.buildRustPackage rec { runHook postInstallCheck ''; - passthru.updateScript = ./update/update.ts; - passthru.tests = callPackage ./tests { }; + passthru = { + updateScript = ./update/update.ts; + tests = callPackage ./tests { }; + fetchDeps = callPackage ./fetch-deps { }; + setupHook = makeSetupHook { + name = "deno-setup-hook"; + propagatedBuildInputs = [ deno ]; + } ./hooks/setup-hook.sh; + compileHook = makeSetupHook { + name = "deno-compile-hook"; + propagatedBuildInputs = [ deno ]; + substitutions.deno = deno; + } ./hooks/compile-hook.sh; + }; meta = with lib; { homepage = "https://deno.land/";