/typescript-node-express-mongo

Typescript, Node, Express and Mongo starting project.

Primary LanguageTypeScript

typescript-node-express-mongo

Typescript, Node, Express and Mongo starting project.

USING

  • NodeJS
  • ExpressJS
  • GulpJS
  • TypeScript

STEPS
 Create project's directory > 'mkdir <your-project's-name>'
 Create tsconfig.json > 'touch tsconfig.json'
TypeScript compiler configuration
 Add a 'src' directory > 'mkdir src'
 Create package.json inside src > 'npm init -y'
 Install TypeScript > 'npm install typescript --save-dev'
 Install gulp > 'npm install gulp --save-dev'
 Install gulp-typescript > 'npm install gulp-typescript --save-dev'
 Add gulpfile.js to the root directory > 'touch gulpfile.js'
 Install ExpressJS > 'npm install express --save'
 Install Debug > 'npm install debug --save'
 Install types NodeJS > 'npm install @types/node --save-dev'
 Install types ExpressJS > 'npm install @types/express --save-dev'
 Install types Debug > 'npm install @types/debug --save-dev'
 Create index file within source directory > 'touch index.js'
 Add start script to package.json > "scripts": {
"start": "node dist/index.js",
"test": "mocha --reporter spec --compilers ts:ts-node/register 'test/**/*.test.ts'"
}
 Create App.js within src file > 'touch App.js'
 Install Body Parser > 'npm install body-parser --save'
 Install Morgan > 'npm install morgan --save'
 Install types Body Parser > 'npm install @types/body-parser --save-dev'
 Install types Morgan > 'npm install @types/morgan --save-dev'
 Gulp scripts
 npm start
 Install mocha > 'npm install mocha --save-dev'
 Install chai > 'npm install chai --save-dev'
 Install chai-http > 'npm install chai-http --save-dev'
 Install types mocha > 'npm install @types/mocha --save-dev'
 Install types chai > 'npm install @types/chai --save-dev'
 Install types chai-http > 'npm install @types/chai-http --save-dev'
 Install ts-node > 'npm install ts-node --save-dev'
 Create test folder
 Create file helloWorld.test.ts
 Run tests > 'npm test'

CONTENT
tsconfig.json

{
  "compilerOptions": {
    "target": "es6",
    "module": "commonjs",
    "outDir": "dist"
  },
  "include": [
    "src/**/*.ts"
  ],
  "exclude": [
    "node_modules"
  ]
}

gulpfile.js

const gulp = require('gulp');
const ts = require('gulp-typescript');
const JSON_FILES = ['src/*.json', 'src/**/*.json'];

// pull in the project TypeScript config
const tsProject = ts.createProject('tsconfig.json');

gulp.task('scripts', () => {
  const tsResult = tsProject.src()
  .pipe(tsProject());
  return tsResult.js.pipe(gulp.dest('dist'));
});

gulp.task('watch', ['scripts'], () => {
  gulp.watch('src/**/*.ts', ['scripts']);
});

gulp.task('assets', function() {
  return gulp.src(JSON_FILES)
  .pipe(gulp.dest('dist'));
});

gulp.task('default', ['watch', 'assets']);

index.ts

import * as http from 'http';
import * as debug from 'debug';

import App from './App';

debug('ts-express:server');

const port = normalizePort(process.env.PORT || 3000);
App.set('port', port);

const server = http.createServer(App);
server.listen(port);
server.on('error', onError);
server.on('listening', onListening);

function normalizePort(val: number|string): number|string|boolean {
  let port: number = (typeof val === 'string') ? parseInt(val, 10) : val;
  if (isNaN(port)) return val;
  else if (port >= 0) return port;
  else return false;
}

function onError(error: NodeJS.ErrnoException): void {
  if (error.syscall !== 'listen') throw error;
  let bind = (typeof port === 'string') ? 'Pipe ' + port : 'Port ' + port;
  switch(error.code) {
    case 'EACCES':
      console.error(`${bind} requires elevated privileges`);
      process.exit(1);
      break;
    case 'EADDRINUSE':
      console.error(`${bind} is already in use`);
      process.exit(1);
      break;
    default:
      throw error;
  }
}

function onListening(): void {
  let addr = server.address();
  let bind = (typeof addr === 'string') ? `pipe ${addr}` : `port ${addr.port}`;
  debug(`Listening on ${bind}`);
}

App.js

import * as path from 'path';
import * as express from 'express';
import * as logger from 'morgan';
import * as bodyParser from 'body-parser';

// Creates and configures an ExpressJS web server.
class App {

  // ref to Express instance
  public express: express.Application;

  //Run configuration methods on the Express instance.
  constructor() {
    this.express = express();
    this.middleware();
    this.routes();
  }

  // Configure Express middleware.
  private middleware(): void {
    this.express.use(logger('dev'));
    this.express.use(bodyParser.json());
    this.express.use(bodyParser.urlencoded({ extended: false }));
  }

  // Configure API endpoints.
  private routes(): void {
    /* This is just to get up and running, and to make sure what we've got is
     * working so far. This function will change when we start to add more
     * API endpoints */
    let router = express.Router();
    // placeholder route handler
    router.get('/', (req, res, next) => {
      res.json({
        message: 'Hello World!'
      });
    });
    this.express.use('/', router);
  }

}

export default new App().express;

helloWorld.test.ts

import * as mocha from 'mocha';
import * as chai from 'chai';
import chaiHttp = require('chai-http');

import app from '../src/App';

chai.use(chaiHttp);
const expect = chai.expect;

describe('baseRoute', () => {

  it('should be json', () => {
    return chai.request(app).get('/')
    .then(res => {
      expect(res.type).to.eql('application/json');
    });
  });

  it('should have a message prop', () => {
    return chai.request(app).get('/')
    .then(res => {
      expect(res.body.message).to.eql('Hello World!');
    });
  });

});