-
-
Save aaronksaunders/1792878 to your computer and use it in GitHub Desktop.
Develop a RESTful API Using Node.js With Express and Mongoose
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var application_root = __dirname, | |
express = require("express"), | |
path = require("path"), | |
mongoose = require('mongoose'); | |
var app = express.createServer(); | |
// database | |
mongoose.connect('mongodb://localhost/ecomm_database'); | |
// config | |
app.configure(function () { | |
app.use(express.bodyParser()); | |
app.use(express.methodOverride()); | |
app.use(app.router); | |
app.use(express.static(path.join(application_root, "public"))); | |
app.use(express.errorHandler({ dumpExceptions: true, showStack: true })); | |
}); | |
var Schema = mongoose.Schema; //Schema.ObjectId | |
// Schemas | |
var Sizes = new Schema({ | |
size: { type: String, required: true }, | |
available: { type: Number, required: true, min: 0, max: 1000 }, | |
sku: { | |
type: String, | |
required: true, | |
validate: [/[a-zA-Z0-9]/, 'Product sku should only have letters and numbers'] | |
}, | |
price: { type: Number, required: true, min: 0 } | |
}); | |
var Images = new Schema({ | |
kind: { | |
type: String, | |
enum: ['thumbnail', 'catalog', 'detail', 'zoom'], | |
required: true | |
}, | |
url: { type: String, required: true } | |
}); | |
var Variants = new Schema({ | |
color: String, | |
images: [Images], | |
sizes: [Sizes] | |
}); | |
var Categories = new Schema({ | |
name: String | |
}); | |
var Catalogs = new Schema({ | |
name: String | |
}); | |
// Product Model | |
var Product = new Schema({ | |
title: { type: String, required: true }, | |
description: { type: String, required: true }, | |
style: { type: String, unique: true }, | |
images: [Images], | |
categories: [Categories], | |
catalogs: [Catalogs], | |
variants: [Variants], | |
modified: { type: Date, default: Date.now } | |
}); | |
// validation | |
Product.path('title').validate(function (v) { | |
console.log("validate title"); | |
console.log(v); | |
return v.length > 10 && v.length < 70; | |
}); | |
Product.path('style').validate(function (v) { | |
console.log("validate style"); | |
console.log(v); | |
return v.length < 40; | |
}, 'Product style attribute is should be less than 40 characters'); | |
Product.path('description').validate(function (v) { | |
console.log("validate description"); | |
console.log(v); | |
return v.length > 10; | |
}, 'Product description should be more than 10 characters'); | |
var ProductModel = mongoose.model('Product', Product); | |
/* Product Document | |
[ | |
{ | |
"title": "My Awesome T-shirt", | |
"description": "All about the details. Of course it's black.", | |
"images": [ | |
{ | |
"kind": "thumbnail", | |
"url": "images/products/1234/main.jpg" | |
} | |
], | |
"categories": [ | |
{ "name": "Clothes" }, | |
{ "name": "Shirts" } | |
], | |
"style": "1234", | |
"variants": [ | |
{ | |
"color": "Black", | |
"images": [ | |
{ | |
"kind": "thumbnail", | |
"url": "images/products/1234/thumbnail.jpg" | |
}, | |
{ | |
"kind": "catalog", | |
"url": "images/products/1234/black.jpg" | |
} | |
], | |
"sizes": [ | |
{ | |
"size": "S", | |
"available": 10, | |
"sku": "CAT-1234-Blk-S", | |
"price": 99.99 | |
}, | |
{ | |
"size": "M", | |
"available": 7, | |
"sku": "CAT-1234-Blk-M", | |
"price": 109.99 | |
} | |
] | |
} | |
], | |
"catalogs": [ | |
{ "name": "Apparel" } | |
] | |
} | |
] | |
*/ | |
// REST api | |
app.get('/api', function (req, res) { | |
res.send('Ecomm API is running'); | |
}); | |
// POST to CREATE | |
app.post('/api/products', function (req, res) { | |
var product; | |
console.log("POST: "); | |
console.log(req.body); | |
product = new ProductModel({ | |
title: req.body.title, | |
description: req.body.description, | |
style: req.body.style, | |
images: req.body.images, | |
categories: req.body.categories, | |
catalogs: req.body.catalogs, | |
variants: req.body.variants | |
}); | |
product.save(function (err) { | |
if (!err) { | |
return console.log("created"); | |
} else { | |
return console.log(err); | |
} | |
}); | |
return res.send(product); | |
}); | |
// PUT to UPDATE | |
app.put('/api/products/:id', function (req, res) { | |
return ProductModel.findById(req.params.id, function (err, product) { | |
product.title = req.body.title; | |
product.description = req.body.description; | |
product.style = req.body.style; | |
product.images = req.body.images; | |
product.categories = req.body.categories; | |
product.catalogs = req.body.catalogs; | |
product.variants = req.body.variants; | |
return product.save(function (err) { | |
if (!err) { | |
console.log("updated"); | |
} else { | |
console.log(err); | |
} | |
return res.send(product); | |
}); | |
}); | |
}); | |
// GET to READ | |
app.get('/api/products', function (req, res) { | |
return ProductModel.find(function (err, products) { | |
if (!err) { | |
return res.send(products); | |
} else { | |
return console.log(err); | |
} | |
}); | |
}); | |
app.get('/api/products/:id', function (req, res) { | |
return ProductModel.findById(req.params.id, function (err, product) { | |
if (!err) { | |
return res.send(product); | |
} else { | |
return console.log(err); | |
} | |
}); | |
}); | |
// DELETE to DESTROY | |
app.delete('/api/products/:id', function (req, res) { | |
return ProductModel.findById(req.params.id, function (err, product) { | |
return product.remove(function (err) { | |
if (!err) { | |
console.log("removed"); | |
return res.send(''); | |
} else { | |
console.log(err); | |
} | |
}); | |
}); | |
}); | |
// launch server | |
app.listen(4242); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!DOCTYPE html> | |
<html lang="en"> | |
<head> | |
<meta charset="utf-8"> | |
<title>API index</title> | |
</head> | |
<body> | |
<section> | |
<h1>Nouns...</h1> | |
<p> | |
/products<br> | |
/products/:id | |
</p> | |
</section> | |
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// jQuery snippets used in the console to use the REST api created with app.js | |
// CREATE | |
jQuery.post("/api/products", { | |
"title": "My Awesome T-shirt", | |
"description": "All about the details. Of course it's black.", | |
"images": [ | |
{ | |
"kind": "thumbnail", | |
"url": "images/products/1234/main.jpg" | |
} | |
], | |
"categories": [ | |
{ "name": "Clothes" }, | |
{ "name": "Shirts" } | |
], | |
"style": "1234", | |
"variants": [ | |
{ | |
"color": "Black", | |
"images": [ | |
{ | |
"kind": "thumbnail", | |
"url": "images/products/1234/thumbnail.jpg" | |
}, | |
{ | |
"kind": "catalog", | |
"url": "images/products/1234/black.jpg" | |
} | |
], | |
"sizes": [ | |
{ | |
"size": "S", | |
"available": 10, | |
"sku": "CAT-1234-Blk-S", | |
"price": 99.99 | |
}, | |
{ | |
"size": "M", | |
"available": 7, | |
"sku": "CAT-1234-Blk-M", | |
"price": 109.99 | |
} | |
] | |
} | |
], | |
"catalogs": [ | |
{ "name": "Apparel" } | |
] | |
}, function(data, textStatus, jqXHR) { | |
console.log("Post resposne:"); console.dir(data); console.log(textStatus); console.dir(jqXHR); | |
}); | |
// generated a product document with automatically assigned ID, e.g. 4f34734d21289c1c28000007 | |
// READ | |
jQuery.get("/api/products/", function(data, textStatus, jqXHR) { | |
console.log("Post resposne:"); | |
console.dir(data); | |
console.log(textStatus); | |
console.dir(jqXHR); | |
}); | |
jQuery.get("/api/products/4f34734d21289c1c28000007", function(data, textStatus, jqXHR) { | |
console.log("Post resposne:"); | |
console.dir(data); | |
console.log(textStatus); | |
console.dir(jqXHR); | |
}); | |
// UPDATE | |
jQuery.ajax({ | |
url: "/api/products/4f34734d21289c1c28000007", | |
type: "PUT", | |
data: { | |
"title": "My Awesome T-shirt", | |
"description": "All about the details. Of course it's black, and longsleeve.", | |
"images": [ | |
{ | |
"kind": "thumbnail", | |
"url": "images/products/1234/main.jpg" | |
} | |
], | |
"categories": [ | |
{ "name": "Clothes" }, | |
{ "name": "Shirts" } | |
], | |
"style": "1234", | |
"variants": [ | |
{ | |
"color": "Black", | |
"images": [ | |
{ | |
"kind": "zoom", | |
"url": "images/products/1234/zoom.jpg" | |
} | |
], | |
"sizes": [ | |
{ | |
"size": "L", | |
"available": 77, | |
"sku": "CAT-1234-Blk-L", | |
"price": 99.99 | |
} | |
] | |
} | |
], | |
"catalogs": [ | |
{ "name": "Apparel" } | |
] | |
}, | |
success: function(data, textStatus, jqXHR) { | |
console.log("PUT resposne:"); | |
console.dir(data); | |
console.log(textStatus); | |
console.dir(jqXHR); | |
} | |
}); | |
// Delete | |
jQuery.ajax({url: "/api/products/4f34734d21289c1c28000007", type: "DELETE", success: function(data, textStatus, jqXHR) { console.dir(data); }}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment