Getting your npm package version from bash

This question came up for me and since I spent more than 5 minutes looking it up and didn’t find this answer anywhere else I wanted to document it.

The way to do it through npm is to add a script to your package.json file like so:

{
  "name": "example",
  "version": "1.0.0",
  "scripts": {
    "version": "echo $npm_package_version"
  }
}

Then you can do this to get the version from bash:

$ CURRENT_VERSION=$(npm run version --silent)

If you want to do automation as npm scripts, you can just access the $npm_package_version variable directly in your scripts.

The longer explanation here is that when you run an npm script it will automatically pull out all of the values from the package.json and put them into environment variables with the pattern npm_package_*. This means you can expose those variables as scripts if you want to use them externally.

The alternate version that I saw elsewhere was to just grab it using node like so:

$ CURRENT_VERSION=$(node -p "require('./package.json').version")

I’m officially a node.js contributor.

This was a couple months ago but I forgot to mention it here!

Here is the commit:
https://github.com/nodejs/node/commit/8593b3e8ebcb89b75d25ba0cb13a63d85b6f41b4

The problem was that, on Windows, loading a native module with a file system path that was longer than 256 characters hit the classic MAX_PATH windows issue. Node actually has a way to successfully load files with long paths, and that way was applied to all path handling except in this one particular spot. It just so happened that I was the only person in the world trying to load native modules from a long path on windows it seems!

Open Source is Software Feudalism

I’m a big fan of open source. One of the things I have enjoyed since my departure from Microsoft is being more involved in the open source community. I have been contributing changes to projects that I am using as well as trying to make more of my code open source. Of course I’ve been relying on Github heavily as most people do, and have been enjoying it quite a bit.

One problem I’ve been noticing as a member of the Open Source community is that while Open Source projects claim to be open and free they do still have owners and controls which can limit participation.

I was discussing this with my good friend Leo and he called Open Source “Feudalism with infinite land”. Because an open source project stakes a claim in the land of software-needs and then controls it tyrannically. It’s easy to see a lot of parallels where this analogy makes sense. Such as the fact that projects have owners who have power over its community of users. Popular projects are like duchies, you are able to claim “land” in popular package managers such as npm. Once you’ve branded your project and claimed the names you effectively control that territory forever.

To take the analogy a little further the GPL license itself is a little bit like the Catholicism of this feudal system, with Linus Torvalds as its Pope. It’s the one true religion that all believers should conform to, even though most of us are secretly MIT heathens in our day to day lives. Furthermore, like the vow of chastity which is used to consolidate the inheritance of priests’ wealth, the viral nature of the GPL license is designed to ensure that more IP is slowly inherited over time by church of Open Source.

Now I don’t want to slam Open Source too much but it would be really nice to see it turn in a more truly free and open direction, away from tyranny and more towards anarchy. But what would this even look like?

For starters I think there should be a feature for any open project in Github to allow the community to control the owners of the project. Meaning, for a given project there should be a voting mechanism, which periodically allows the community to add or remove people from the set of project owners.

Similarly there should be a mechanism for individual Pull Requests where the community could vote on said PR to influence its acceptance.

Furthermore, a culture where people are happy to transfer ownership and view it as a healthy way to vitalize projects and limit power consolidation is necessary.

Additionally, I would like to see a feature where a project can, in a structured way, declare what kind of contributions they are seeking. From owners, to developers, to design work, to specific features and bugs. There should then be a master list where anybody could go and see this list of work sought and after a period of time automatically join into a project they find interesting.

Projects that go stagnant would have ownership roles automatically go up onto the board. Ownership roles that have more applicants than are available would have community based voting before the role is granted.

Most of these ideas are just things I came up with this morning (with the help of Leo of course). So I’m not saying they’re perfect or even well thought out. However I think the general principal is sound, which is that there is a problem of tyranny currently in Open Source and I would like to see it move into an even more open, anarchistic direction.

Executing shell commands from node.js on Windows

If you’re on Windows and driving node.js through the shell that came with git for windows instead of CMD, it can be surprisingly difficult to invoke shell commands from javascript. The child_process.exec function will always call into CMD.exe instead of bash and if you try to use spawn it will expect you to parse your command into an array as well as escape strings and use backslashes.

It was surprisingly difficult to execute an arbitrary shell command for me so I just wanted to share the small amount of code I ended up writing to achieve it.

Note: this assumes you have Git for Windows or some other shell which you are then running node from.

var spawn = require('child_process').spawn;

function run(cmd, env, callback) {
    if (!cmd) return callback();
    var p = spawn('sh', ['-c', cmd], {
        env: env,
        stdio: 'inherit'
    });
    p.on('close', function (code) {
        if (code !== 0) return callback(new Error('Command failed', code, cmd));
        callback();
    });
}

module.exports = {
    run: run
};