Merge pull request #42 from stephank/tweak-shell

Tweak Nix shell, add ESM support
This commit is contained in:
Stéphan Kochen
2022-10-18 22:03:43 +02:00
committed by GitHub
8 changed files with 79 additions and 49 deletions
+1
View File
@@ -15,6 +15,7 @@ const EXTERNALS = [
`clipanion`, `clipanion`,
`crypto`, `crypto`,
`os`, `os`,
`url`,
]; ];
const compiler = webpack({ const compiler = webpack({
+1 -1
View File
File diff suppressed because one or more lines are too long
+2 -2
View File
@@ -19,7 +19,7 @@
"@yarnpkg/core": "^3.0.0", "@yarnpkg/core": "^3.0.0",
"@yarnpkg/fslib": "^2.5.1", "@yarnpkg/fslib": "^2.5.1",
"@yarnpkg/plugin-patch": "^3.0.0", "@yarnpkg/plugin-patch": "^3.0.0",
"@yarnpkg/plugin-pnp": "^3.0.0", "@yarnpkg/plugin-pnp": "^3.1.0",
"babel-loader": "^8.1.0", "babel-loader": "^8.1.0",
"clipanion": "^3.0.0", "clipanion": "^3.0.0",
"prettier": "2.5.1", "prettier": "2.5.1",
@@ -47,7 +47,7 @@
"@yarnpkg/plugin-npm-cli": "3.0.0", "@yarnpkg/plugin-npm-cli": "3.0.0",
"@yarnpkg/plugin-pack": "3.0.0", "@yarnpkg/plugin-pack": "3.0.0",
"@yarnpkg/plugin-patch": "3.0.0", "@yarnpkg/plugin-patch": "3.0.0",
"@yarnpkg/plugin-pnp": "3.0.1", "@yarnpkg/plugin-pnp": "3.1.0",
"@yarnpkg/plugin-stage": "3.0.0", "@yarnpkg/plugin-stage": "3.0.0",
"@yarnpkg/shell": "3.0.0" "@yarnpkg/shell": "3.0.0"
} }
+18 -2
View File
@@ -13,6 +13,7 @@ import {
import binWrapperNodeModulesTmpl from "./tmpl/bin-wrapper-node-modules.sh.in"; import binWrapperNodeModulesTmpl from "./tmpl/bin-wrapper-node-modules.sh.in";
import binWrapperPnpTmpl from "./tmpl/bin-wrapper-pnp.sh.in"; import binWrapperPnpTmpl from "./tmpl/bin-wrapper-pnp.sh.in";
import { renderTmpl } from "./textUtils"; import { renderTmpl } from "./textUtils";
import { pathToFileURL } from "url";
// Internal command that creates wrappers for binaries. // Internal command that creates wrappers for binaries.
// Used inside the Nix install phase. // Used inside the Nix install phase.
@@ -82,13 +83,28 @@ export default class InstallBinCommand extends Command<CommandContext> {
) { ) {
let wrapper; let wrapper;
switch (configuration.get(`nodeLinker`)) { switch (configuration.get(`nodeLinker`)) {
case `pnp`: case `pnp`: {
const pnpPath = getPnpPath(project);
const nodeOptions = [];
if (await xfs.existsPromise(pnpPath.cjs)) {
nodeOptions.push(
`--require "${npath.fromPortablePath(pnpPath.cjs)}"`
);
}
if (await xfs.existsPromise(pnpPath.esmLoader)) {
nodeOptions.push(
`--experimental-loader "${
pathToFileURL(npath.fromPortablePath(pnpPath.esmLoader)).href
}"`
);
}
wrapper = renderTmpl(binWrapperPnpTmpl, { wrapper = renderTmpl(binWrapperPnpTmpl, {
NODE_PATH: process.execPath, NODE_PATH: process.execPath,
PNP_PATH: getPnpPath(project).cjs, NODE_OPTIONS: nodeOptions.join(" "),
BINARY_PATH: binaryPath, BINARY_PATH: binaryPath,
}); });
break; break;
}
case `node-modules`: case `node-modules`:
wrapper = renderTmpl(binWrapperNodeModulesTmpl, { wrapper = renderTmpl(binWrapperNodeModulesTmpl, {
NODE_PATH: process.execPath, NODE_PATH: process.execPath,
+5 -2
View File
@@ -46,13 +46,16 @@ export const renderTmpl = (
let result = tmpl; let result = tmpl;
for (const [name, value] of Object.entries(vars)) { for (const [name, value] of Object.entries(vars)) {
if (typeof value === "string") { if (typeof value === "string") {
result = result.replace(`@@${name}@@`, value); result = result.replace(new RegExp(`@@${name}@@`, "g"), value);
} }
if (typeof value === "boolean") { if (typeof value === "boolean") {
while (true) {
const lines = result.split("\n"); const lines = result.split("\n");
const startIdx = lines.indexOf(`#@@ IF ${name}`); const startIdx = lines.indexOf(`#@@ IF ${name}`);
const endIdx = lines.indexOf(`#@@ ENDIF ${name}`); const endIdx = lines.indexOf(`#@@ ENDIF ${name}`);
if (startIdx !== -1 && endIdx > startIdx) { if (startIdx === -1 || endIdx < startIdx) {
break;
}
if (value) { if (value) {
lines.splice(endIdx, 1); lines.splice(endIdx, 1);
lines.splice(startIdx, 1); lines.splice(startIdx, 1);
+1 -1
View File
@@ -1,3 +1,3 @@
#!/bin/sh #!/bin/sh
export NODE_OPTIONS="--require @@PNP_PATH@@" export NODE_OPTIONS='@@NODE_OPTIONS@@'
exec '@@NODE_PATH@@' '@@BINARY_PATH@@' "$@" exec '@@NODE_PATH@@' '@@BINARY_PATH@@' "$@"
+36 -26
View File
@@ -1,49 +1,58 @@
# This file is generated by running "yarn install" inside your project. # This file is generated by running "yarn install" inside your project.
# Manual changes might be lost - proceed with caution! # Manual changes might be lost - proceed with caution!
{ lib, nodejs, stdenv, fetchurl, writeText, git, cacert, writeShellApplication }: { lib, stdenv, nodejs, git, cacert, fetchurl, writeShellScript, writeShellScriptBin }:
{ src, overrideAttrs ? null, ... } @ args: { src, overrideAttrs ? null, ... } @ args:
let let
yarnPath = ./@@YARN_PATH@@;
lockfile = ./@@LOCKFILE@@;
cacheFolder = @@CACHE_FOLDER@@; cacheFolder = @@CACHE_FOLDER@@;
#@@ IF NEED_ISOLATED_BUILD_SUPPRORT
lockfile = ./@@LOCKFILE@@;
#@@ ENDIF NEED_ISOLATED_BUILD_SUPPRORT
# Call overrideAttrs on a derivation if a function is provided. # Call overrideAttrs on a derivation if a function is provided.
optionalOverride = fn: drv: optionalOverride = fn: drv:
if fn == null then drv else drv.overrideAttrs fn; if fn == null then drv else drv.overrideAttrs fn;
# Simple stub that provides the global yarn command.
yarn = writeShellScriptBin "yarn" ''
exec '${nodejs}/bin/node' '${./@@YARN_PATH@@}' "$@"
'';
# Common attributes between Yarn derivations. # Common attributes between Yarn derivations.
drvCommon = { drvCommon = {
# Make sure the build uses the right Node.js version everywhere. # Make sure the build uses the right Node.js version everywhere.
buildInputs = [ nodejs ]; buildInputs = [ nodejs yarn ];
# Tell node-gyp to use the provided Node.js headers for native code builds. # Tell node-gyp to use the provided Node.js headers for native code builds.
npm_config_nodedir = nodejs; npm_config_nodedir = nodejs;
# Tell node-pre-gyp to never fetch binaries / always build from source.
npm_config_build_from_source = "true";
# Defines the shell alias to run Yarn.
postHook = ''
yarn() {
CI=1 node "${yarnPath}" "$@"
}
'';
}; };
# Comman variables that we set in a Nix build, but not in a Nix shell.
buildVars = ''
# Make Yarn produce friendlier logging for automated builds.
export CI=1
# Tell node-pre-gyp to never fetch binaries / always build from source.
export npm_config_build_from_source=true
# Disable Nixify plugin to save on some unnecessary processing.
export yarn_enable_nixify=false
'';
# Create derivations for fetching dependencies. # Create derivations for fetching dependencies.
cacheDrvs = let cacheDrvs = let
builder = builtins.toFile "builder.sh" '' builder = writeShellScript "yarn-cache-builder" ''
source $stdenv/setup source $stdenv/setup
cd "$src" cd "$src"
HOME="$TMP" yarn_cache_folder="$TMP" CI=1 \ ${buildVars}
node '${yarnPath}' nixify fetch-one $locator HOME="$TMP" yarn_cache_folder="$TMP" \
yarn nixify fetch-one $locator
# Because we change the cache dir, Yarn may generate a different name. # Because we change the cache dir, Yarn may generate a different name.
mv "$TMP/$(sed 's/-[^-]*\.[^-]*$//' <<< "$outputFilename")"-* $out mv "$TMP/$(sed 's/-[^-]*\.[^-]*$//' <<< "$outputFilename")"-* $out
''; '';
in lib.mapAttrs (locator: { filename, sha512 }: stdenv.mkDerivation { in lib.mapAttrs (locator: { filename, sha512 }: stdenv.mkDerivation {
inherit src builder locator; inherit src builder locator;
name = lib.strings.sanitizeDerivationName locator; name = lib.strings.sanitizeDerivationName locator;
buildInputs = [ nodejs git cacert ]; buildInputs = [ yarn git cacert ];
outputFilename = filename; outputFilename = filename;
outputHashMode = "flat"; outputHashMode = "flat";
outputHashAlgo = "sha512"; outputHashAlgo = "sha512";
@@ -52,7 +61,7 @@ let
# Create a shell snippet to copy dependencies from a list of derivations. # Create a shell snippet to copy dependencies from a list of derivations.
mkCacheBuilderForDrvs = drvs: mkCacheBuilderForDrvs = drvs:
writeText "collect-cache.sh" (lib.concatMapStrings (drv: '' writeShellScript "collect-yarn-cache" (lib.concatMapStrings (drv: ''
cp ${drv} '${drv.outputFilename}' cp ${drv} '${drv.outputFilename}'
'') drvs); '') drvs);
@@ -66,7 +75,12 @@ let
# Create a derivation that builds a node-pre-gyp module in isolation. # Create a derivation that builds a node-pre-gyp module in isolation.
mkIsolatedBuild = { pname, version, reference, locators }: stdenv.mkDerivation (drvCommon // { mkIsolatedBuild = { pname, version, reference, locators }: stdenv.mkDerivation (drvCommon // {
inherit pname version; inherit pname version;
phases = [ "buildPhase" "installPhase" ]; dontUnpack = true;
configurePhase = ''
${buildVars}
unset yarn_enable_nixify # plugin is not present
'';
buildPhase = '' buildPhase = ''
mkdir -p .yarn/cache mkdir -p .yarn/cache
@@ -97,10 +111,10 @@ let
project = stdenv.mkDerivation (drvCommon // { project = stdenv.mkDerivation (drvCommon // {
inherit src; inherit src;
name = @@PROJECT_NAME@@; name = @@PROJECT_NAME@@;
# Disable Nixify plugin to save on some unnecessary processing.
yarn_enable_nixify = "false";
configurePhase = '' configurePhase = ''
${buildVars}
# Copy over the Yarn cache. # Copy over the Yarn cache.
rm -fr '${cacheFolder}' rm -fr '${cacheFolder}'
mkdir -p '${cacheFolder}' mkdir -p '${cacheFolder}'
@@ -172,14 +186,10 @@ let
passthru = { passthru = {
inherit nodejs; inherit nodejs;
yarn = writeShellApplication { yarn = writeShellScriptBin "yarn" ''
name = "yarn"; exec '${yarn}/bin/yarn' --cwd '${project}/libexec/${project.name}' "$@"
runtimeInputs = [ nodejs ];
text = ''
${yarnPath} --cwd ${project}/libexec/${project.name} "$@"
''; '';
}; };
};
}); });
@@CACHE_ENTRIES@@ @@CACHE_ENTRIES@@
+11 -11
View File
@@ -1074,22 +1074,22 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@yarnpkg/plugin-pnp@npm:3.0.1": "@yarnpkg/plugin-pnp@npm:3.1.0":
version: 3.0.1 version: 3.1.0
resolution: "@yarnpkg/plugin-pnp@npm:3.0.1" resolution: "@yarnpkg/plugin-pnp@npm:3.1.0"
dependencies: dependencies:
"@types/semver": ^7.1.0 "@types/semver": ^7.1.0
"@yarnpkg/fslib": ^2.5.1 "@yarnpkg/fslib": ^2.6.0
"@yarnpkg/plugin-stage": ^3.0.0 "@yarnpkg/plugin-stage": ^3.1.0
"@yarnpkg/pnp": ^3.0.1 "@yarnpkg/pnp": ^3.1.0
clipanion: ^3.0.1 clipanion: ^3.0.1
micromatch: ^4.0.2 micromatch: ^4.0.2
semver: ^7.1.2 semver: ^7.1.2
tslib: ^1.13.0 tslib: ^1.13.0
peerDependencies: peerDependencies:
"@yarnpkg/cli": ^3.0.1 "@yarnpkg/cli": ^3.1.0
"@yarnpkg/core": ^3.0.0 "@yarnpkg/core": ^3.1.0
checksum: 682fdaab91583a6fb662be05e660a76510df94e5d79c42f51dd19db9d5e3310b29d91111e5a8ed9fc6e382e2b581a9e0342f37852e2af96c98d33c50d9331bd4 checksum: 9ffd901263f60c83a116a38e8bb76a9196185b36fde514c95b0336affc879308099db12ae9bd20b8f70f3253791f1127bf4f87ced5a62d2b4529a02115347f6d
languageName: node languageName: node
linkType: hard linkType: hard
@@ -1124,7 +1124,7 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"@yarnpkg/pnp@npm:^3.0.1, @yarnpkg/pnp@npm:^3.1.0": "@yarnpkg/pnp@npm:^3.1.0":
version: 3.1.0 version: 3.1.0
resolution: "@yarnpkg/pnp@npm:3.1.0" resolution: "@yarnpkg/pnp@npm:3.1.0"
dependencies: dependencies:
@@ -3307,7 +3307,7 @@ __metadata:
"@yarnpkg/core": ^3.0.0 "@yarnpkg/core": ^3.0.0
"@yarnpkg/fslib": ^2.5.1 "@yarnpkg/fslib": ^2.5.1
"@yarnpkg/plugin-patch": ^3.0.0 "@yarnpkg/plugin-patch": ^3.0.0
"@yarnpkg/plugin-pnp": ^3.0.0 "@yarnpkg/plugin-pnp": ^3.1.0
babel-loader: ^8.1.0 babel-loader: ^8.1.0
clipanion: ^3.0.0 clipanion: ^3.0.0
prettier: 2.5.1 prettier: 2.5.1