Skip to content

Commit 2869449

Browse files
committed
Initial commit
1 parent d35ba59 commit 2869449

File tree

9 files changed

+443
-0
lines changed

9 files changed

+443
-0
lines changed

.gitignore

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
.tscache
2+
.baseDir.ts
3+
dist
4+
node_modules

README.md

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# TypeScript 2 + Express + Node.js
2+
3+
This is a repository to go with my article on creating an Express web application using TypeScript 2.
4+
5+
## Install
6+
7+
Install the node packages via:
8+
9+
`$ npm install`
10+
11+
And then run the grunt task to compile the TypeScript:
12+
13+
`$ npm run grunt`
14+
15+
## Starting
16+
17+
To start the server run:
18+
19+
`$ npm start`

bin/www

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
#!/usr/bin/env node
2+
"use strict";
3+
4+
//module dependencies
5+
var server = require("../dist/server");
6+
var debug = require("debug")("express:server");
7+
var http = require("http");
8+
9+
//create http server
10+
var httpPort = normalizePort(process.env.PORT || 8080);
11+
var app = server.Server.bootstrap().app;
12+
app.set("port", httpPort);
13+
var httpServer = http.createServer(app);
14+
15+
//listen on provided ports
16+
httpServer.listen(httpPort);
17+
18+
//add error handler
19+
httpServer.on("error", onError);
20+
21+
//start listening on port
22+
httpServer.on("listening", onListening);
23+
24+
25+
/**
26+
* Normalize a port into a number, string, or false.
27+
*/
28+
function normalizePort(val) {
29+
var port = parseInt(val, 10);
30+
31+
if (isNaN(port)) {
32+
// named pipe
33+
return val;
34+
}
35+
36+
if (port >= 0) {
37+
// port number
38+
return port;
39+
}
40+
41+
return false;
42+
}
43+
44+
/**
45+
* Event listener for HTTP server "error" event.
46+
*/
47+
function onError(error) {
48+
if (error.syscall !== "listen") {
49+
throw error;
50+
}
51+
52+
var bind = typeof port === "string"
53+
? "Pipe " + port
54+
: "Port " + port;
55+
56+
// handle specific listen errors with friendly messages
57+
switch (error.code) {
58+
case "EACCES":
59+
console.error(bind + " requires elevated privileges");
60+
process.exit(1);
61+
break;
62+
case "EADDRINUSE":
63+
console.error(bind + " is already in use");
64+
process.exit(1);
65+
break;
66+
default:
67+
throw error;
68+
}
69+
}
70+
71+
/**
72+
* Event listener for HTTP server "listening" event.
73+
*/
74+
function onListening() {
75+
var addr = httpServer.address();
76+
var bind = typeof addr === "string"
77+
? "pipe " + addr
78+
: "port " + addr.port;
79+
debug("Listening on " + bind);
80+
}

gruntfile.js

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
module.exports = function(grunt) {
2+
"use strict";
3+
4+
grunt.initConfig({
5+
copy: {
6+
build: {
7+
files: [
8+
{
9+
expand: true,
10+
cwd: "./public",
11+
src: ["**"],
12+
dest: "dist/public"
13+
},
14+
{
15+
expand: true,
16+
cwd: "./views",
17+
src: ["**"],
18+
dest: "dist/views"
19+
}
20+
]
21+
}
22+
},
23+
ts: {
24+
app: {
25+
files: [{
26+
src: ["src/\*\*/\*.ts", "!src/.baseDir.ts"],
27+
dest: "./dist"
28+
}],
29+
options: {
30+
module: "commonjs",
31+
target: "es6",
32+
sourceMap: false
33+
}
34+
}
35+
},
36+
watch: {
37+
ts: {
38+
files: ["src/\*\*/\*.ts"],
39+
tasks: ["ts"]
40+
},
41+
views: {
42+
files: ["views/**/*.pug"],
43+
tasks: ["copy"]
44+
}
45+
}
46+
});
47+
48+
grunt.loadNpmTasks("grunt-contrib-copy");
49+
grunt.loadNpmTasks("grunt-contrib-watch");
50+
grunt.loadNpmTasks("grunt-ts");
51+
52+
grunt.registerTask("default", [
53+
"copy",
54+
"ts"
55+
]);
56+
57+
};

package.json

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"name": "heros",
3+
"description": "The tour of heros",
4+
"version": "1.0.0",
5+
"private": true,
6+
"author": "Brian Love",
7+
"scripts": {
8+
"dev": "NODE_ENV=development nodemon ./bin/www",
9+
"grunt": "grunt",
10+
"start": "node ./bin/www"
11+
},
12+
"dependencies": {
13+
"body-parser": "^1.15.2",
14+
"cookie-parser": "^1.4.3",
15+
"errorhandler": "^1.4.3",
16+
"express": "^4.14.0",
17+
"method-override": "^2.3.6",
18+
"morgan": "^1.7.0",
19+
"pug": "^2.0.0-beta6"
20+
},
21+
"devDependencies": {
22+
"@types/body-parser": "0.0.33",
23+
"@types/cookie-parser": "^1.3.30",
24+
"@types/errorhandler": "0.0.30",
25+
"@types/method-override": "0.0.29",
26+
"@types/morgan": "^1.7.32",
27+
"grunt": "^1.0.1",
28+
"grunt-contrib-copy": "^1.0.0",
29+
"grunt-contrib-watch": "^1.0.0",
30+
"grunt-ts": "^6.0.0-beta.3",
31+
"typescript": "^2.0.8"
32+
}
33+
}

src/routes/index.ts

+60
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { NextFunction, Request, Response, Router } from "express";
2+
import { BaseRoute } from "./route";
3+
4+
5+
/**
6+
* / route
7+
*
8+
* @class User
9+
*/
10+
export class IndexRoute extends BaseRoute {
11+
12+
/**
13+
* Create the routes.
14+
*
15+
* @class IndexRoute
16+
* @method create
17+
* @static
18+
*/
19+
public static create(router: Router) {
20+
//log
21+
console.log("[IndexRoute::create] Creating index route.");
22+
23+
//add home page route
24+
router.get("/", (req: Request, res: Response, next: NextFunction) => {
25+
new IndexRoute().index(req, res, next);
26+
});
27+
}
28+
29+
/**
30+
* Constructor
31+
*
32+
* @class IndexRoute
33+
* @constructor
34+
*/
35+
constructor() {
36+
super();
37+
}
38+
39+
/**
40+
* The home page route.
41+
*
42+
* @class IndexRoute
43+
* @method index
44+
* @param req {Request} The express Request object.
45+
* @param res {Response} The express Response object.
46+
* @next {NextFunction} Execute the next method.
47+
*/
48+
public index(req: Request, res: Response, next: NextFunction) {
49+
//set custom title
50+
this.title = "Home | Tour of Heros";
51+
52+
//set message
53+
let options: Object = {
54+
"message": "Welcome to the Tour of Heros"
55+
};
56+
57+
//render template
58+
this.render(req, res, "index", options);
59+
}
60+
}

src/routes/route.ts

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { NextFunction, Request, Response } from "express";
2+
3+
/**
4+
* Constructor
5+
*
6+
* @class BaseRoute
7+
*/
8+
export class BaseRoute {
9+
10+
protected title: string;
11+
12+
private scripts: string[];
13+
14+
15+
/**
16+
* Constructor
17+
*
18+
* @class BaseRoute
19+
* @constructor
20+
*/
21+
constructor() {
22+
//initialize variables
23+
this.title = "Tour of Heros";
24+
this.scripts = [];
25+
}
26+
27+
/**
28+
* Add a JS external file to the request.
29+
*
30+
* @class BaseRoute
31+
* @method addScript
32+
* @param src {string} The src to the external JS file.
33+
* @return {BaseRoute} Self for chaining
34+
*/
35+
public addScript(src: string): BaseRoute {
36+
this.scripts.push(src);
37+
return this;
38+
}
39+
40+
/**
41+
* Render a page.
42+
*
43+
* @class BaseRoute
44+
* @method render
45+
* @param req {Request} The request object.
46+
* @param res {Response} The response object.
47+
* @param view {String} The view to render.
48+
* @param options {Object} Additional options to append to the view's local scope.
49+
* @return void
50+
*/
51+
public render(req: Request, res: Response, view: string, options?: Object) {
52+
//add constants
53+
res.locals.BASE_URL = "/";
54+
55+
//add scripts
56+
res.locals.scripts = this.scripts;
57+
58+
//add title
59+
res.locals.title = this.title;
60+
61+
//render view
62+
res.render(view, options);
63+
}
64+
}

0 commit comments

Comments
 (0)