-1

The title of my question is how to run a command line tool from a node.js application because I think an answer here will apply to all command line utilities installable from npm. I have seen questions related to running command line from node.js, but they don't seem to be working for my situation. Specifically I am trying to run a node command line utility similar to npm (in how it is used, but not its function) called tilemantle.

tilemantle's documentation shows installing tilemantle globally and running the program from the command line.

What I would like to do is install tilemantle locally as a part of a npm project using npm install tilemantle --save and then run tilemantle from inside my project.

I've tried `tilemantle = require('tilemantle'), but the index.js file in the tilemantle project is empty, so I think this won't help with anything.

I tried the project node-cmd

const cmd = require('node-cmd');
cmd.run('./node_modules/tilemantle/bin/tilemantle', 'http://localhost:5000/layer/{z}/{x}/{y}/tile.png', '-z 0-11', '--delay=100ms', '--point=37.819895,-122.478674', '--buffer=100mi'

This doesn't throw any errors, but it also just doesn't work.

I also tried child processes

const child_process = require('child_process');
child_process.exec('./node_modules/tilemantle/bin/tilemantle', 'http://localhost:5000/layer/{z}/{x}/{y}/tile.png, -z 0-11 --delay=100ms --point=37.819895,-122.478674 --buffer=100mi'

This also doesn't throw any errors, but it also doesn't work.

Is there a way to get this working, so that I can run tilemantle from inside my program and not need to install it globally?

Update

I can get tilemantle to run from my terminal with

node './node_modules/tilemantle/bin/tilemantle', 'http://localhost:5000/layer/{z}/{x}/{y}/tile.png', '--delay=100ms', '--point=37.819895,-122.478674', '--buffer=100mi', '-z 0-11'

If I run the following as suggested by jkwok

child_process.spawn('tilemantle', ['http://myhost.com/{z}/{x}/{y}.png',
  '--point=44.523333,-109.057222', '--buffer=12mi', '-z', '10-14'],
  { stdio: 'inherit' });

I am getting spawn tilemantle ENOENT and if I replace tilemantle with ./node_modules/tilemantle/bin/tilemantle.js I get spawn UNKNOWN

Based on jfriend00's answer it sounds like I need to actually be spawning node, so I tried the following

child_process.spawn('node', ['./node_modules/tilemantle/bin/tilemantle.js', 'http://myhost.com/{z}/{x}/{y}.png', '--point=44.523333,-109.057222', '--buffer=12mi', '-z', '10-14'], { stdio: 'inherit' });

Which gives me the error spawn node ENOENT which seems strange since I can run it from my terminal and I checked my path variable and C:\Program Files\nodejs is on my path.

Just to check I tried running the following with a full path to node.

child_process.spawn('c:/program files/nodejs/node.exe', ['./node_modules/tilemantle/bin/tilemantle.js', 'http://myhost.com/{z}/{x}/{y}.png', '--point=44.523333,-109.057222', '--buffer=12mi', '-z', '10-14'], { stdio: 'inherit' });

which runs without the ENOENT error, but again it is failing silently and is just not warming up my tile server.

I am running Windows 10 x64 with Node 6.11.0

Community
  • 1
  • 1
TJ Rockefeller
  • 3,178
  • 17
  • 43
  • The post I linked to has a comment about running on Windows [here](https://stackoverflow.com/questions/17516772/using-nodejss-spawn-causes-unknown-option-and-error-spawn-enoent-err/17537559#17537559) – jkwok Aug 31 '17 at 10:25

3 Answers3

0

You can install any executable locally and then run it with child_process. To do so, you just have to figure out what the exact path is to the executable and pass that path to the child_process.exec() or child_process.spawn() call.

What it looks like you ultimately want to run is a command line that does:

node <somepath>/tilemantle.js

When you install on windows, it will do most of that for you if you run:

node_modules\.bin\tilemantle.cmd

If you want to run the js file directly (e.g. on other platforms), then you need to run:

node node_modules/tilemantle/bin/tilemantle.js

Note, with child_process, you have to specify the actual executable which in this case is "node" itself and then the path to the js file that you wish to run.

This, of course, all assumes that node is in your path so the system can find it. If it is not in your path, then you will have to use the full path to the node executable also.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

It looks like you are trying to capture the output of tilemantle from running a file rather than from the command line. If so, I did the following and got it to work.

Installed tilemantle and child_process locally into a new npm project as you did, and added the following into a file in that project.

//  test.js file
var spawn = require('child_process').spawn;

spawn('tilemantle', ['http://myhost.com/{z}/{x}/{y}.png', '--
  point=44.523333,-109.057222', '--buffer=12mi', '-z', '10-14'], { stdio: 'inherit' });

Run it using node test.js inside the project.

I tried a bunch of the other options in this post but could only get the above one to print the progress along with other output. Hope this helps!

jkwok
  • 111
  • 4
-1

Many command line utilities come with a "programmatic" API. Unfortunately, tilemantle does not, which is why you are unable to require that module in your code.

You can, however, easily access a locally installed version of the CLI from npm scripts. I don't know anything about tilemantle, so I'll provide an example using the tldr command line tool. In your package.json:

{
  "name": "my-lib",
  "version": "1.0.0",
  "scripts": {
    "test": "tldr curl"
  },
  "dependencies": {
    "tldr": "^2.0.1"
  }
}

You can now run npm test from the terminal in your project as an alias for tldr curl.

Per this post, you can use the global-npm package to run npm scripts from your code:

const npm = require('global-npm')

npm.load({}, (err) => {
  if (err) throw err

  npm.commands.run(['test'])
})

And voila, you can now run the locally installed CLI programmatically(ish), even though it has not offered an API for that.

djfdev
  • 5,747
  • 3
  • 19
  • 38