1
votes

My question is: how can I make node available to a shell script on Cloud functions for Firebase when I use an npm package like xml2json?

Context:

I am moving a piece of software from short-living Docker containers to Cloud functions for Firebase. The software processes large XML files and converts parts to JSON.

Due to the memory consumption, I use xmllint and xml2json via the shell.

var cmd = './xmllint --xpath "//OrderData" ' + this.filename + ' | ' + __dirname + '/node_modules/xml2json/bin/xml2json';
exec(cmd, function(error, stdout, stderr) { ... }

Xmllint works as expected (distributed in the npm package that I added to package.json in the functions directory)

"@niekoost/convertini": "file:niekoost-convertini-1.0.1.tgz"

But the pipe through xml2json produces the problem: The first line of xml2json is causing my issue

#!/usr/bin/env node

This leads to an error in the Cloud Functions log in the Firebase console

Error: Command failed: ./xmllint --xpath "//OrderData" 
/tmp/kdjf6kv9hku86xw4h392j4i.xml | /user_code/node_modules/xml2json/bin/xml2json
/usr/bin/env: node: No such file or directory

Where is node located on Cloud functions for Firebase? Can I make it available to /usr/bin/env? Or should I fork the xml2json npm package and change that code.

1
Don't assume that anything is available for execution other than what's documented (right now, just imagemagick). Prefer doing all work in the function runtime itself.Doug Stevenson
Hi Doug, thanks for your response. Since the main function is al ready executed with the Node binary, I think that it is completely safe to assume that Node is installed and that a shell script can also get access to that binary.Niek Oost

1 Answers

2
votes

After some additional searches I have found a solution for my situation, without having to change the npm package that is provided for xml2json.

Since xml2json is used in a command that is being executed by 'exec', we only need to make the path to the Node binary available in the environment of that exec. This path can be derived from 'process.execPath':

var exec    = require('child_process').exec;
var process = require('process');

// get path where the node binary is located from within the code that
// is being executed by the node runtime provided by Firebase
var nodePath = process.execPath;
nodePath = nodePath.split('/');
nodePath = nodePath.splice(0, nodePath.length-1).join('/');

// add path to the environment
process.env.PATH += ':' + nodePath;

var cmd = './xmllint --xpath "//OrderData" /xyz.xml | /user_code/node_modules/xml2json/bin/xml2json';

// call the command and provide the extended env
exec(cmd, {env: process.env}, function(error, stdout, stderr) {
  ...
});