### Creating Tern index files

Orion provides JSON type definition files (http://ternjs.net/doc/manual.html#typedef) otherwise known as indexes for a number of common libraries.
This file goes over the steps used to generate them.  Note that the Tern plugins contain the templates as well as the JSON type def.

### Install Node and NPM

You need to run the Tern server from the command line as a Node.js server.  NPM will make it simpler to install Tern and the source to index.

### Install Tern

	npm install tern@0.6.2

This will install tern inside the node_modules directory of the directory you are currently in.  The @0.6.2 specifies a version of Tern to install.
The version you use should match the version of Tern Orion is using.  It is unknown whether indexes generated by later versions are backwards compatible.

If in the steps below the node Tern server cannot find modules such as acorn/acorn, you will have to modify the scripts to use the new paths (Tern's depends on 
acorn and other scripts which have changed folder structure).  You can simply compare the scripts to the latest version of Tern on github (https://github.com/marijnh/tern)
or fix them manually ('acorn/acorn' becomes 'acorn', etc.)

### Get the source

You can use git command line, find the github page for your source and clone the repo.  Or you can use npm install to get the source.

	npm installed amqp


### Run the Tern Condense utility

	node tern/bin/condense --name amqp --no-spans --plugin doc_comment --def ecma5 --def browser ../node-amqp/lib/*.js ../node-amqp/*.js > amqp.json
	node tern/bin/condense --name express --no-spans --plugin doc_comment --def ecma5 --def browser ../express/lib/*.js ../express/lib/middleware/*.js ../express/lib/router/*.js ../express/*.js > express.json
	node tern/bin/condense --name mongodb --no-spans --plugin doc_comment --def ecma5 --def browser ../node-mongodb-native/lib/bulk/*.js ../node-mongodb-native/lib/gridfs/*.js ../node-mongodb-native/lib/*.js ../node-mongodb-native/*.js > mongodb.json
	node tern/bin/condense --name mysql --no-spans --plugin doc_comment --def ecma5 --def browser ../node-mysql/lib/*.js ../node-mysql/lib/protocol/*.js ../node-mysql/lib/protocol/constants/*.js ../node-mysql/lib/protocol/packets/*.js ../node-mysql/lib/protocol/sequences/*.js ../node-mysql/*.js > mysql.json
	node tern/bin/condense --name postgres --no-spans --plugin doc_comment --def ecma5 --def browser ../node-postgres/lib/native/*.js ../node-postgres/lib/*.js > postgres
	node tern/bin/condense --name redis --no-spans --plugin doc_comment --def ecma5 --def browser redis/lib/*.js redis/lib/parser/*.js redis/*.js > redis.json
	
From the node_modules folder where you installed Tern, run the tern condense utility with appropriate arguments.  You will have to adjust the file list to
where you downloaded the source.  Because Win cmd can't handle wildcard file lists, you will need Cygwin or Git Bash to execute successfully on Windows.	

If you are doing this in Windows using the Git Bash shell you may encounter an error: ``output is not a tty''.  This is because the node program is outputting to the console
which is not the format Cygwin and Git Bash expect. The easiest workaround is to modify the condense application.  Add ''var fs = require('fs');'' to the file and at the
end replace the call to console.log with ''fs.writeFile("output.json",''.

The follow commands were used to create indexes in March 2016

	node tern/bin/condense --name amqp --no-spans --plugin doc_comment --def ecma5 --def browser amqp/lib/*.js amqp/*.js
	node tern/bin/condense --name express --no-spans --plugin doc_comment --def ecma5 --def browser express/lib/*.js express/lib/middleware/*.js express/lib/router/*.js express/*.js

### Manually fix indexes

#### Mark the index as a node module

All of the indexed libs we currently provide are node modules accessed via require('<name>'); For the defs entry in each plugin to be
recognized by the Tern node plug-in, you must add a special entry.  In Tern 16 this entry was **"!node"**.  In Tern 18 this entry was **"!known_modules"**.

Example for AMQP that defines what a require('amqp') statement would return:

	"!known_modules": {
	  "amqp": {
	    "Connection" : "Connection",
		"createConnection": "fn(options: Object, implOptions: Object, readyCallback: fn()) -> +Connection",
      }
    },


#### AMQP

Condense does not extract any useful information from the amqp.js file at the root.  We add in the contents there manually:

	"!node": {
	  "amqp": {
	    "Connection" : "Connection",
		"createConnection": "fn(options: Object, implOptions: Object, readyCallback: fn()) -> +Connection",
      }
    },

The on() function is not defined.  Add it to the connection protoype:

	"Connection": {
      "prototype": {
        "on": "fn(event: string, action: fn())",

#### Express

When the express index was run it did not include the !node entry for the top level express type resulting in no assist proposals for the created app object ''var app = express()''.
Also, the static function was missing due to it being a re-export from another module.  We added the following to the index (under !define):

	"!node": {
	      "express": {
	      	  "static" : {
		    		"!type": "fn(name: string)",
		    		"!doc": "Built-in middleware function.  Pass the name of the directory that contains the static assets."
		    	},
	          "!type": "fn() -> app",
	          "!url": "http://expressjs.com",
	          "!doc": "Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications."
          }
      },
     
You must also remove the type information for toString() and hasOwnProperty() as these override the functions with the same name in the Object prototype.

Index does not include all of the API functions at http://expressjs.com/en/api.html.  The following were added under "app"
	"delete": {
  		"!type": "fn()",
  	},
  	"get": {
  		"!type": "fn()",
  	},
  	"METHOD": {
  		"!type": "fn()",
  	},
  	"post": {
  		"!type": "fn()",
  	},
  	"put": {
  		"!type": "fn()",
  	},

#### Redis

The on() function is not defined.  Add it to the RedisClient type:

	   "RedisClient": {
	      "on": "fn(event: string, action: fn())",

### Indexes we provide

Plugins found in `web/javascript/ternPlugins/`.

* amqp.js (March 2016)
* express.js (March 2016)
* mongodb.js 
* mysql.js 
* postgres.js 
* redis.js (on() manually added March 2016)
