Npm deps in python project

TL;DR: Can we use importNpmLock in a python derivation to install node with all dependencies listed in package[-lock].json?

I’m trying to build robotframework-browser. The problem is that this project uses both python and npm. For now, the python part works fine, but the python calls at some point some node script, and it stuggle to find the node dependencies (of course they are not installed), listed in the package.json and package-lock.json files.

I tried to add the dependencies in pkgs/development/node-packages/node-packages.json + call generate.sh (and it seems to work, at least it works for one of them)… but I feel like it is not the proper solution to globally install the dependencies.

Instead, for python + pnpm packages like pkgs/by-name/fr/froide/package.nix I’ve seen people using pnpm.configHook + pnpmDeps = pnpm.fetchDeps { … } to automatically install the npm dependencies of the current project.

For npm, it seems like one can use importNpmLock (or the more complex fetchNpmDeps according to the doc), the problem is that this will only be available in buildNpmPackage, while I need it to work in a python derivation. Is there some kind of hooks… I can add to install npm deps in a python derivation?

EDIT For the reference, here is the file I’m using right now:

{
  lib,
  stdenv,
  buildPythonPackage,
  fetchPypi,
  pythonOlder,
  robotframework,
  robotframework-pythonlibcore,
  robotframework-assertion-engine,
  grpcio,
  grpcio-tools,
  protobuf,
  overrides,
  click,
  seedir,
  wrapt,
}:
# Maybe get inspiration from pkgs/by-name/fr/froide/package.nix
buildPythonPackage rec {
  version = "19.6.0";
  pname = "robotframework-browser";

  disabled = pythonOlder "3.9";

  src = fetchPypi {
    inherit version;
    pname = "robotframework_browser";
    sha256 = "sha256-7f0FeqoMaSqXhr4gofULMUV7DOjiqvQoc5CBn/WQOhQ=";
  };

  # We fake a run of rfbrowser init
  patchPhase = ''
    substituteInPlace ./Browser/playwright.py \
      --replace-fail '(installation_dir / "node_modules").is_dir()' 'True'
  '';

  dependencies = [
    robotframework
    robotframework-pythonlibcore
    robotframework-assertion-engine
    grpcio
    grpcio-tools
    protobuf
    overrides
    click
    seedir
    wrapt
  ];

  meta = with lib; {
    description = "Robot Framework Browser library powered by Playwright. ";
    homepage = "https://robotframework-browser.org/";
    license = licenses.asl20;
    maintainers = with maintainers; [ tobiasBora ];
  };

}

located in pkgs/development/python-modules/robotframework-browser/default.nix, and testing with the following shell:

let pkgs = import ./. {}; in
pkgs.mkShell {
  buildInputs = [
    (pkgs.python3.withPackages (ps: with ps; [
      robotframework robotframework-browser playwright
    ]))
    pkgs.nodejs_latest
    pkgs.playwright
    pkgs.nodePackages.google-protobuf
  ];

  nativeBuildInputs = [
    pkgs.playwright-driver.browsers
  ];

  shellHook = ''
    export PLAYWRIGHT_BROWSERS_PATH=${pkgs.playwright-driver.browsers}
    export PLAYWRIGHT_SKIP_VALIDATE_HOST_REQUIREMENTS=true
  '';

}

I also needed to bump the version in pkgs/development/python-modules/grpcio-tools/default.nix and pkgs/development/python-modules/grpcio/default.nix to 1.73.0 (just changed the version and the hash and it worked directly).

EDIT2 I also tried this: no more error… but lib/node_modules is not created…

{
  lib,
  stdenv,
  buildPythonPackage,
  fetchPypi,
  pythonOlder,
  robotframework,
  robotframework-pythonlibcore,
  robotframework-assertion-engine,
  grpcio,
  grpcio-tools,
  protobuf,
  overrides,
  click,
  seedir,
  wrapt,
  importNpmLock,
  npmHooks,
  nodejs_latest,
  fetchNpmDeps,
  fetchFromGitHub,
}:
# Maybe get inspiration from pkgs/by-name/fr/froide/package.nix
buildPythonPackage rec {
  version = "19.6.0";
  pname = "robotframework-browser";

  disabled = pythonOlder "3.9";

  nativeBuildInputs = [
    #importNpmLock.npmConfigHook
    npmHooks.npmConfigHook
    npmHooks.npmInstallHook
    nodejs_latest
  ];
  npmDeps = fetchNpmDeps {
    #inherit src;
    src = fetchFromGitHub {
      owner = "MarketSquare";
      repo = "robotframework-browser";
      rev = "v${version}";
      hash = "sha256-kOifD+Fa1WCYbNZSRX89FlZio9oJ7Rh6aXQGVmVPXRI=";
    };
    hash = "sha256-paVNge7wlG+znGyc9wXHKYF4fpQUotREq/iddU1Pafo=";
  };
  # npmDeps = importNpmLock {
  #   # ? How to use the same path as src? So far it complains it is compressed
  #   npmRoot = ".";
  # };

  src = fetchPypi {
    inherit version;
    pname = "robotframework_browser";
    sha256 = "sha256-7f0FeqoMaSqXhr4gofULMUV7DOjiqvQoc5CBn/WQOhQ=";
  };

  # We fake a run of rfbrowser init
  patchPhase = ''
    substituteInPlace ./Browser/playwright.py \
      --replace-fail '(installation_dir / "node_modules").is_dir()' 'True'
  '';

  dependencies = [
    robotframework
    robotframework-pythonlibcore
    robotframework-assertion-engine
    grpcio
    grpcio-tools
    protobuf
    overrides
    click
    seedir
    wrapt
  ];

  postInstall = ''
  #runHook preInstall
  echo "AAAAAAAAAAAAAAaa"
  ls -al
  echo "dist"
  ls -al dist
  #runHook postInstall
  '';

  meta = with lib; {
    description = "Robot Framework Browser library powered by Playwright. ";
    homepage = "https://robotframework-browser.org/";
    license = licenses.asl20;
    maintainers = with maintainers; [ tobiasBora ];
  };

}

I made a step further by adding runHook pro/postPatch, but now get a new error, cf new question in Grpc-tools in node programs tries to access internet while building