Npm in python part

Hey,
I am trying to package Fidus Writer, which is a python project. The packaging itself works by reusing most of a pypi setup.py file.

However, I am having trouble getting access to an npm executable from within Fidus Writer. Fidus Writer needs to run npm every now and then while it is running (so not just for building). I tried to add npm as a stage package, but the npm executable is not available that way.

For now what has worked is to add nodejs/npm as an extra make-part in which I basically download the nodejs sources and build them from scratch. It works, but it takes quite a bit of time to build nodejs/npm so I’d prefer installing a package of some kind.

Any ideas?

have you tried using the node plugin instead of building it from source ?

it should just download the pre-compiled tarball from upstream.

I went as far as that but it then complained about there being no package.json. The thing is there is no package.json at the time of build. The python app creates package.json files later on (depending on the user’s configuration) and then tries to run npm on it.

Maybe I should try to start with an empty package.json file?

well, if the empty packages.json doesnt work you can always simply wget a tarball from an overrid-build snippet or a plugin: nil part from https://nodejs.org/en/download/

Hmm, yeah the empty package.json didn’t work either. It did build alright, but the “npm” executable is not available inside of the snap. It’s the same as when I tried to add npm to the stage packages.

  node:
    plugin: nodejs
    nodejs-package-manager: npm
    source: .
    override-pull: |
        echo '{"name": "fiduswriter", "version": "1.0.0"}' > package.json
        snapcraftctl pull

I will now try with your suggestion.

It sounds like you need to bundle npm with your snap, not that you need to necessarily bundle a NodeJS application with the snap. The NodeJS/npm plugin is for building a NodeJS application, not for bundling npm in the snap, but since npm is itself a NodeJS package, I think you can just specify npm in node-packages. Alternatively, as @ogra said you can just download npm in the snap.

You should take a look at the node-red snap, they do the same thing by bundling npm in the snap. I don’t know where their snapcraft.yaml is on the internet, but you can see it from inside the snap with:

$ snap install node-red && cat /snap/node-red/current/snap/snapcraft.yaml
1 Like

Thanks everyone, that did get me onto something. node-red seem to use an older version of the nodejs plugin which allowed one to specify node-packages. That seems to be gone in the current version of the nodejs plugin.

After studying the sources of the nodejs plugin [1] carefully, I came up with this (hack) of a part hat seems to work:

  node:
    plugin: nodejs
    nodejs-package-manager: npm
    source: ./travis
    override-pull: |
      echo '{"name": "fiduswriter", "version": "1.0.0", "dependencies": {"npm": "*"}, "bin": {"npm": "node_modules/.bin/npm"}}' > package.json
      snapcraftctl pull
      rm -f configuration.py

I chose the “travis” dir for the sources as it is the emptiest directory around. It only contains a configuration.py file, which I delete subsequently. It’s not possible to just skip snapcraftctl pull as that breaks it. For some reason this is dumping the package.json file in the root of the snap. I don’t know what the point of that is, but it doesn’t seem to hurt either.

[1] https://github.com/snapcore/snapcraft/blob/master/snapcraft/plugins/nodejs.py

Hey,
for anyone else coming across issues with getting npm to run, this is how I made it work in the end: snapcraft.yaml and npm folder. It turned out that npm did not just have the issues discussed here, but additionally, it would cause issues if run as root (by a daemon or alike). So instead of executing npm directly, I had to add a wrapper script to make npm think it is not in sudo session and to not block it from executing scripts as root.