Published: 02-08-2016
A log of how to create and publish NPM modules, using bitbucket with NPM and semmantic versioning. Little bit on Typescript too.
Modules
A module is just bunch of code that can be reused. A module, or modules, can be published as a package to the NPM registry making the code easily accessible to others. Node uses CommonJS to define modules. Modules are created and used by 'exporting' and 'requiring', like this:
			
// logger.js
// Exposes the logMessage function 
// publically

exports.logMessage = function (message) {
	console.log(message);
}
			
		
			
// myCode.js
// requires the logger.js file
// to use the logMessage function

var logger = require('logger');
logger.logMessage('Hello World')

// Hello World
			
		
This is the essence of how it works. Things of course get a little more complex when the code grows. Often the modules are abstracted further and nested. This is why NPM expects an entry point in the package.json (config) file so it knows where to start.
NPM
NPM is a package manager that is really useful for sharing code in the form of packages. This code normally takes the shape of modules for Node but really it could be anything, i.e. a front end library like Angular. It takes the hassle out of using libraries by managing them for you. NPM handles all the dependencies (packages that use other packages that use other packages). It puts everything in a nice organised place (node_modules) so modules can be simply 'required' in your own code. You can install, update, uninstall, publish packages etc. all through the NPM CLI tool which is installed by default with Node. An NPM package is defined by its config file 'package.json'. This file contains all the information about the package itself i.e. author, dependencies, license etc.
Making a package
The package.json file can be created manually or by using the NPM CLI. Simply running NPM init will start an interactive initialisation of a new package.json file.

:~/Programming/npm-test$ npm init

name: (npm-test) 
version: (1.0.0) 
description: NPM Package Demo
entry point: (index.js) 
test command: 
git repository: 
keywords: Demo
author: Tom
license: (ISC) 
About to write to /home/thomas/Programming/npm-test/package.json:

{
  "name": "npm-test",
  "version": "1.0.0",
  "description": "NPM Package Demo",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "Demo"
  ],
  "author": "Tom",
  "license": "ISC"
}


Now we could write some some code and export it. The package.json points to index.js as the entry point by default so this is where we need to put our exports. This basically tells Node where to look when we use require().
NPM account
In order to publish the package to the NPM registry you must have an user account. This is managed with the following commands:

npm adduser    # Starts interactive user signup

npm login      # Logs you in on the client

npm config ls  # Used to check the credentials stored on the client

Publishing package
The 'npm publish' command publishes a package to the registry. Everything is included except stuff that is ignored by .gitignore and .npmignore.
Package Versions
By default when running 'npm init', the version 1.0.0 is added to the package.json. NPM recommends semantic versioning, see here for details. Simply put it is arranged like this: MAJOR.MINOR.PATCH and each is incremented when:
  1. MAJOR - you make incompatible API changes
  2. MINOR - you add functionality in a backwards-compatible manner
  3. Patch - you make backwards-compatible bug fixes
The version can be bumped by manually changing the package.json of by running 'npm version major/minor/patch' Then run 'npm publish' again to update the registry. Note, the README displayed on the site will not be updated unless a new version of the package is publish.
Using Bitbucket and/or Github with NPM
I don't think it's a good idea to publish code still in development (might just be because I'm shy), so being able to install packages from Bitbucket seems attractive. Bitbucket offers ultimited private repos and a simplified versioning system can still be used by incorporating git tags.
Setting up the SSH
To pull down a repo from bitbucket without any passwords or interaction requires SSH to be set up. A keypair needs to be generated using ssh-keygen. The public key is uploaded to bitbucket and the private key kept on the local machine. To generate the keygen run:

$ ssh-keygen -t rsa -C "myemail@mydomain.com" -b 4096 -f ~/.ssh/bitbucket_key

Bitbucket needs to be supplied with the public key so it can authorise us. The public key can be uploaded for a particular repo or the entire account. Uploading the key for a single repo only grants read access. Our SSH client needs to know where our private key is so it can connect to bitbucket. To help it out create a config file at ~/.ssh/config and populate it with:

Host bitbucket.org
	IdentityFile ~/.ssh/bitbucket_key
	IdentitiesOnly yes
	UserKnownHostsFile=/dev/null
	StrictHostKeyChecking no

This helps point it to the right place and stops a few other checks that might ask for user input. For more config options check out the man page with man ssh_config. The config file allows multiple hosts to be setup. You could set this up on NPM's preinstall and tear it down on postinstall if you wanted to but I'm just mucking around on my computer not deploying or anything. Now installing NPM packages from bitbucket is as simple as:

"dependencies": {
	"bitbucket-package": "git@bitbucket.org:trickard/npm-test.git"
},

// Or with a git tag for versioning

"dependencies": {
	"bitbucket-package": "git@bitbucket.org:trickard/npm-test.git#v1.0.0"
},

Creating Typescript Packages
Creating typescript packages is actually pretty simple as Typescript knows where to look for module 'imports' [2]. It's just a matter of separating the .ts and .js files, emitting the typings .d.ts and letting the typescript compiler know where all these things are/should go. Requiring plain JavaScript modules still requires manually getting the typings but this is made easier by the typings module. The directory structure is as follows:

- lib
- src
	- index.ts
- .gitignore
- .npmignore
- package.json
- tsconfig.json

The package.json and tsconfig.json files tell the Typescript compilier and NPM where things are/should go:
			
// package.json

{
	"name": "npm-typescript-package",
	"version": "1.0.0",
	"main": "./lib/index.js",
	"typings": "./lib/index",
	"scripts": {
		"build": "tsc"
	},
	"devDependencies": {
		"typescript": "^1.8.10"
	}
}
			
		
			
// tsconfig.json

{
	"compilerOptions": {
		"module": "commonjs",
		"declaration": true,
		"outDir": "lib/"
	},
	"files": [
		"./src/index.ts"
	]
}
			
		
The .gitignore config tells git to ignore the node_modules. The .npmignore tells NPM to ignore the node_modules and the src folder as apparently typescript files should left out of npm packages.