How to build and publish a Typescript package to NPM


Step 1: init package

mkdir name-typescript-package && cd name-typescript-package
npm init -y

Example:

mkdir express-ip && cd express-ip
npm init -y

Result:

D:\AppServ\www\node3>mkdir express-ip && cd express-ip

D:\AppServ\www\node3\express-ip>npm init -y
Wrote to D:\AppServ\www\node3\express-ip\package.json:

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

Step 2: install typescript

npm i --save-dev typescript

Result:

D:\AppServ\www\node3\express-ip>npm i --save-dev typescript
npm notice created a lockfile as package-lock.json. You should commit this file.

npm WARN express-ip@1.0.0 No description
npm WARN express-ip@1.0.0 No repository field.

+ typescript@4.4.2
added 1 package from 1 contributor and audited 1 package in 7.943s
found 0 vulnerabilities

Step 3: configuration Typescript:

npx tsc --init

Result:

D:\AppServ\www\node3\express-ip>npx tsc --init
message TS6071: Successfully created a tsconfig.json file.

Step 4: edit file tsconfig.json

{
  "compilerOptions": {
    "target": "es2015"      /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */,
    "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */,
    "declaration": true  /* Generates corresponding '.d.ts' file. */,
    "outDir": "./lib"    /* Redirect output structure to the directory. */,
    "strict": true       /* Enable all strict type-checking options. */
  },
  "include": ["src"],    /* Typescript source code */
  "exclude": ["node_modules", "test"]
}

Step 5: write your own codes
Example: create file ./src/index.ts

import * as geoip from 'geoip-country'

export function getIpInfo (ip:string) {        	
	var lookedUpIP = geoip.lookup(ip);

	if (!lookedUpIP){
		return { error: "Error occured while trying to process the information" }
	}
	return lookedUpIP;
}

export function getIpInfoMiddleware (opts={DEVIP:'1.1.1.1'}){
	return function (req:any, res:any, next:any) {
		var xForwardedFor = (req.headers['x-forwarded-for'] || '').replace(/:\d+$/, '');
		var cfConnectingIp = req.headers['cf-connecting-ip'] || '';
		var incapClientIp = req.headers['incap-client-ip'] || '';
		var xSucuriClientIp = req.headers['x-sucuri-clientip'] || '';
		var ip = cfConnectingIp || incapClientIp || xSucuriClientIp || xForwardedFor            
		ip = (ip && ip.split(",").shift()) || req.connection.remoteAddress;
		if (ip.includes('::ffff:')) {
			ip = ip.split(':').reverse()[0]
		}	
		if ((ip === '127.0.0.1' || ip === '::1')) {
			ip = opts.DEVIP || '1.1.1.1'
		}
		req.ipInfo = { ip, ...getIpInfo(ip) };
		next();
	}
}

Step 6: edit file package.json

{
  "name": "@sansamour/express-ip",
  "version": "1.0.0",
  "description": "",
  "main": "lib/index.js",
  "types": "lib/index.d.ts",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
	"prepare" : "npm run build",
    "build": "tsc"  
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "typescript": "^4.4.2"  
  },
  "files": [
    "lib"
  ]
}

Step 7: install dependencies:
Example: npm i geoip-country

D:\AppServ\www\node3\express-ip>npm i geoip-country
npm WARN @sansamour/express-ip@1.0.0 No description
npm WARN @sansamour/express-ip@1.0.0 No repository field.

+ geoip-country@4.0.83
added 31 packages from 23 contributors and audited 32 packages in 9.256s

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities
npm i --save-dev @types/geoip-country
D:\AppServ\www\node3\express-ip>npm i --save-dev @types/geoip-country
npm WARN @sansamour/express-ip@1.0.0 No description
npm WARN @sansamour/express-ip@1.0.0 No repository field.

+ @types/geoip-country@4.0.0
added 1 package from 1 contributor and audited 33 packages in 2.882s

1 package is looking for funding
  run `npm fund` for details

found 0 vulnerabilities

Step 8: build

D:\AppServ\www\node3\express-ip>npm run build

> @sansamour/express-ip@1.0.0 build D:\AppServ\www\node3\express-ip
> tsc

Step 9: test your package:

Create file test/test.js

const request = require('supertest');
const express = require('express');
const {getIpInfoMiddleware} = require('../lib/index');

const app = express();
app.use(getIpInfoMiddleware());

app.get('/ipInfo', function(req, res) {
  res.status(200).json(req.ipInfo);
});

request(app)
  .get('/ipInfo')
  .expect('Content-Type', /json/)
  .expect(200)
  .end(function(err, res) {
    if (err) throw err;
	console.log(res.body);
  });

Edit file package.json

"test": "node test/test.js",

Install dependencies:

npm install supertest --save-dev
npm install express --save-dev

Run:

D:\AppServ\www\node3\express-ip>npm run test

> @sansamour/express-ip@1.0.0 test D:\AppServ\www\node3\express-ip
> node test/test.js

{ ip: '1.1.1.1', range: [ 16843008, 16843263 ], country: 'AU' }

Step 9.2 (Option): create file .npmignore

/ignore
/.gitignore
/node_modules
/.npmignore
/.git

Step 10: publish to NPM

Login npm: npm login

Result:

D:\AppServ\www\node3\express-ip>npm login
Username: sansamour
Password:
Email: (this IS public) tutorialspots.com@gmail.com
Logged in as sansamour on https://registry.npmjs.org/.

npm login

Publish: npm publish --scope sansamour --access public

Result:

D:\AppServ\www\node3\express-ip>npm publish --scope sansamour --access public

> @sansamour/express-ip@1.0.0 prepare .
> npm run build


> @sansamour/express-ip@1.0.0 build D:\AppServ\www\node3\express-ip
> tsc

npm notice
npm notice package: @sansamour/express-ip@1.0.0
npm notice === Tarball Contents ===
npm notice 1.3kB lib/index.js
npm notice 524B  package.json
npm notice 262B  lib/index.d.ts
npm notice === Tarball Details ===
npm notice name:          @sansamour/express-ip
npm notice version:       1.0.0
npm notice package size:  1.1 kB
npm notice unpacked size: 2.1 kB
npm notice shasum:        f98e27f08cfbaf9d14da2ba4597ec36e929d39be
npm notice integrity:     sha512-JhEx6ghh+ije0[...]cchiymrRsC0Ew==
npm notice total files:   3
npm notice
+ @sansamour/express-ip@1.0.0

npm publish

Leave a Reply