Skip to content

Commit 4de5b9a

Browse files
committed
Initial commit
0 parents  commit 4de5b9a

File tree

12 files changed

+3674
-0
lines changed

12 files changed

+3674
-0
lines changed

.env

Whitespace-only changes.

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
node_modules
2+
.DS_Store
3+
build/

package.json

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "typescript-express-server",
3+
"version": "1.0.0",
4+
"main": "index.js",
5+
"license": "MIT",
6+
"scripts": {
7+
"server:dev": "tsc && nodemon ./build/server/index.js",
8+
"server:prod": "node ./build/server/index.js"
9+
},
10+
"dependencies": {
11+
"bcrypt-nodejs": "^0.0.3",
12+
"bluebird": "^3.5.0",
13+
"body-parser": "^1.17.1",
14+
"compression": "^1.6.2",
15+
"cookie-parser": "^1.4.3",
16+
"cors": "^2.8.3",
17+
"dotenv": "^4.0.0",
18+
"express": "^4.15.2",
19+
"handlebars": "^4.0.6",
20+
"helmet": "^3.5.0",
21+
"lodash": "^4.17.4",
22+
"mongoose": "^4.9.4",
23+
"morgan": "^1.8.1",
24+
"rxjs": "^5.3.0",
25+
"socket.io": "^1.7.3",
26+
"socket.io-client": "^1.7.3"
27+
},
28+
"devDependencies": {
29+
"@types/bluebird": "^3.5.2",
30+
"@types/body-parser": "^1.16.3",
31+
"@types/cookie-parser": "^1.3.30",
32+
"@types/cors": "^2.8.1",
33+
"@types/express": "^4.0.35",
34+
"@types/mongoose": "^4.7.10",
35+
"@types/node": "^7.0.12",
36+
"nodemon": "^1.11.0",
37+
"typescript": "^2.2.2",
38+
"webpack": "^2.4.1",
39+
"webpack-dev-server": "2.4.0"
40+
}
41+
}

src/controllers/PostController.ts

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
import { Request, Response, NextFunction } from 'express';
2+
import * as Promise from 'bluebird';
3+
import Post from '../models/Post';
4+
5+
6+
class PostController {
7+
8+
// get all posts
9+
public static get(params, callback): void {
10+
11+
Post.find(params, (err, posts) => {
12+
if (err) {
13+
callback(err, null);
14+
}
15+
callback(null, posts);
16+
})
17+
}
18+
19+
20+
21+
// get post by slug
22+
public static getBySlug(slug, params, callback): void {
23+
24+
Post.findOne({slug}, (err, post) => {
25+
if (err){
26+
if (callback != null)
27+
callback({ message:'Profile Not Found' }, null)
28+
29+
return
30+
}
31+
32+
if (callback != null)
33+
callback(null, post)
34+
})
35+
}
36+
37+
38+
39+
// create post
40+
41+
42+
// update post
43+
44+
45+
46+
// delete post
47+
48+
49+
}
50+
51+
52+
export default PostController;

src/index.ts

+46
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import * as http from 'http';
2+
import * as debug from 'debug';
3+
4+
import Server from './server';
5+
6+
debug('ts-express:server');
7+
8+
const port = normalizePort(process.env.PORT || 3000);
9+
Server.set('port', port);
10+
11+
console.log(`Server listening on port ${port}`);
12+
13+
const server = http.createServer(Server);
14+
server.listen(port);
15+
server.on('error', onError);
16+
server.on('listening', onListening);
17+
18+
function normalizePort(val: number|string): number|string|boolean {
19+
let port: number = (typeof val === 'string') ? parseInt(val, 10) : val;
20+
if (isNaN(port)) return val;
21+
else if (port >= 0) return port;
22+
else return false;
23+
}
24+
25+
function onError(error: NodeJS.ErrnoException): void {
26+
if (error.syscall !== 'listen') throw error;
27+
let bind = (typeof port === 'string') ? 'Pipe ' + port : 'Port ' + port;
28+
switch(error.code) {
29+
case 'EACCES':
30+
console.error(`${bind} requires elevated privileges`);
31+
process.exit(1);
32+
break;
33+
case 'EADDRINUSE':
34+
console.error(`${bind} is already in use`);
35+
process.exit(1);
36+
break;
37+
default:
38+
throw error;
39+
}
40+
}
41+
42+
function onListening(): void {
43+
let addr = server.address();
44+
let bind = (typeof addr === 'string') ? `pipe ${addr}` : `port ${addr.port}`;
45+
debug(`Listening on ${bind}`);
46+
}

src/models/Post.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import * as mongoose from 'mongoose';
2+
const Schema = mongoose.Schema;
3+
4+
const PostSchema = new Schema({
5+
timestamp: {
6+
type: Date,
7+
default: Date.now
8+
},
9+
title: {
10+
type: String,
11+
default: '',
12+
required: true
13+
},
14+
slug: {
15+
type: String,
16+
default: '',
17+
required: true,
18+
unique: true,
19+
trim: true
20+
},
21+
content: {
22+
type: String,
23+
default: '',
24+
required: true,
25+
unique: true
26+
},
27+
author: {
28+
type: Schema.Types.ObjectId,
29+
ref: 'User'
30+
}
31+
});
32+
33+
export default mongoose.model('Post', PostSchema);

src/router/ApiRouter.ts

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import { Router, Request, Response, NextFunction } from 'express';
2+
import * as express from 'express';
3+
const router = express.Router();
4+
5+
import PostController from '../controllers/PostController';
6+
7+
8+
let controllers = {
9+
posts: PostController
10+
};
11+
12+
13+
export class ApiRouter {
14+
15+
16+
// get all resources
17+
public static getAll( router: Router ): void {
18+
19+
router.get('/:resource', (req: Request, res: Response, next: NextFunction) => {
20+
const resource = req.params.resource;
21+
const controller = controllers[resource];
22+
23+
if (!controller) {
24+
res.status(404).json({ error: '404 - Resource Not Found' });
25+
}
26+
27+
controller.get(req.query, (error, results) => {
28+
if (error) {
29+
res.status(500).json({ error });
30+
}
31+
res.status(200).json({ results });
32+
});
33+
});
34+
}
35+
36+
37+
// get a resource by slug
38+
public static getBySlug( router: Router ): void {
39+
40+
router.get('/:resource/:slug', (req: Request, res: Response, next: NextFunction) => {
41+
const slug = req.params.slug;
42+
const resource = req.params.resource;
43+
const controller = controllers[resource];
44+
45+
if (!controller) {
46+
res.status(404).json({ error: '404 - Resource Not Found' });
47+
}
48+
49+
controller.get(slug, req.query, (error, result) => {
50+
if (error) {
51+
res.status(500).json({ error });
52+
}
53+
res.status(200).json({ result });
54+
});
55+
});
56+
}
57+
58+
59+
// create a resource
60+
public static create( router: Router ): void {
61+
62+
}
63+
64+
65+
66+
// update a resource by slug
67+
public static updateBySlug( router: Router): void {
68+
69+
}
70+
71+
72+
73+
74+
// delete a resource by slug
75+
public static deleteBySlug( router: Router ): void {
76+
77+
}
78+
79+
80+
81+
82+
}

src/router/PostRouter.ts

+106
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,106 @@
1+
import { Router, Request, Response, NextFunction } from "express";
2+
import Post from '../models/Post';
3+
4+
5+
export class PostRouter {
6+
7+
router: Router;
8+
9+
constructor() {
10+
this.router = Router();
11+
this.routes();
12+
}
13+
14+
public getAllPosts(req: Request, res: Response, next: NextFunction) {
15+
Post.find()
16+
.then((posts) => {
17+
res.status(200).json({ posts });
18+
})
19+
.catch((error) => {
20+
res.status(500).json({ error });
21+
})
22+
}
23+
24+
public getPostBySlug(req: Request, res: Response, next: NextFunction) {
25+
const slug = req.params.slug;
26+
27+
Post.findOne({slug})
28+
.then((post) => {
29+
res.status(200).json({ post });
30+
})
31+
.catch((error) => {
32+
res.status(500).json({ error });
33+
})
34+
}
35+
36+
37+
// create post
38+
public createPost(req: Request, res: Response, next: NextFunction): void {
39+
const title = req.body.title;
40+
const slug = req.body.slug;
41+
const content = req.body.content;
42+
43+
if (!title || !slug || !content) {
44+
res.status(422).json({ message: 'All Fields Required.' });
45+
}
46+
47+
const post = new Post({
48+
title,
49+
slug,
50+
content
51+
});
52+
53+
post.save()
54+
.then((post) => {
55+
res.status(200).json({ post });
56+
})
57+
.catch((error) => {
58+
res.status(500).json({ error });
59+
})
60+
}
61+
62+
63+
// update post by slug
64+
public updatePost(req: Request, res: Response, next: NextFunction): void {
65+
const slug = req.body.slug;
66+
67+
Post.findOneAndUpdate({slug}, req.body)
68+
.then((post) => {
69+
res.status(200).json({ post });
70+
})
71+
.catch((error) => {
72+
res.status(500).json({ error });
73+
})
74+
}
75+
76+
77+
// delete post by slug
78+
public deletePost(req: Request, res: Response, next: NextFunction): void {
79+
const slug = req.body.slug;
80+
81+
Post.findOneAndRemove({slug})
82+
.then((post) => {
83+
res.status(200).json({ post });
84+
})
85+
.catch((error) => {
86+
res.status(500).json({ error });
87+
})
88+
}
89+
90+
91+
92+
routes() {
93+
this.router.get('/', this.getAllPosts);
94+
this.router.get('/:slug', this.getPostBySlug);
95+
this.router.post('/', this.createPost);
96+
this.router.put('/:slug', this.updatePost);
97+
this.router.delete('/:slug', this.deletePost);
98+
}
99+
100+
101+
}
102+
103+
const postRoutes = new PostRouter();
104+
postRoutes.routes();
105+
106+
export default postRoutes.router;

0 commit comments

Comments
 (0)