mirror of
				https://github.com/KevinMidboe/planetposen.git
				synced 2025-10-29 17:50:32 +00:00 
			
		
		
		
	Server setup with mongodb.
Server handles creating and fetching products and their variations. Models are saved to mongo using mongoose. STILL PRETTY BARE BONES!
This commit is contained in:
		| @@ -5,7 +5,8 @@ | |||||||
|   "main": "server.js", |   "main": "server.js", | ||||||
|   "repository": "git@github.com:kevinmidboe/planetposen.git", |   "repository": "git@github.com:kevinmidboe/planetposen.git", | ||||||
|   "scripts": { |   "scripts": { | ||||||
|     "dev": "cross-env NODE_ENV=development webpack-dev-server --progress" |     "dev": "cross-env NODE_ENV=development webpack-dev-server --progress", | ||||||
|  |     "server": "NODE_PATH=server node server/app.js" | ||||||
|   }, |   }, | ||||||
|   "author": "KevinMidboe <kevin.midboe@gmail.com>", |   "author": "KevinMidboe <kevin.midboe@gmail.com>", | ||||||
|   "license": "MIT", |   "license": "MIT", | ||||||
| @@ -14,6 +15,7 @@ | |||||||
|     "clean-webpack-plugin": "^3.0.0", |     "clean-webpack-plugin": "^3.0.0", | ||||||
|     "extract-text-webpack-plugin": "^3.0.2", |     "extract-text-webpack-plugin": "^3.0.2", | ||||||
|     "moment": "^2.24.0", |     "moment": "^2.24.0", | ||||||
|  |     "mongoose": "^5.9.24", | ||||||
|     "node-fetch": "^2.6.0", |     "node-fetch": "^2.6.0", | ||||||
|     "node-sass": "^4.13.0", |     "node-sass": "^4.13.0", | ||||||
|     "vue": "~2.6", |     "vue": "~2.6", | ||||||
|   | |||||||
							
								
								
									
										29
									
								
								server/app.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								server/app.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | |||||||
|  | const express = require('express'); | ||||||
|  | const app = express(); | ||||||
|  | const router = express.Router(); | ||||||
|  | const server = require('http').Server(app); | ||||||
|  | const path = require('path'); | ||||||
|  |  | ||||||
|  | const mongoose = require('mongoose'); | ||||||
|  | // const MongoStore = require('connect-mongo'); | ||||||
|  | mongoose.promise = global.Promise; | ||||||
|  | mongoose.connect('mongodb://localhost/planetposen'); | ||||||
|  | mongoose.set('debug', true); | ||||||
|  |  | ||||||
|  | const PORT = 30010; | ||||||
|  |  | ||||||
|  | const productsController = require('./controllers/product.js'); | ||||||
|  | const variationsController = require('./controllers/variation.js'); | ||||||
|  |  | ||||||
|  | app.use(express.json()); | ||||||
|  | // app.use(express.urlencoded()); | ||||||
|  |  | ||||||
|  | router.get('/products', productsController.allProducts) | ||||||
|  | router.get('/product/:id', productsController.productById) | ||||||
|  | router.post('/product', productsController.addNewProduct) | ||||||
|  |  | ||||||
|  | router.post('/variation/:id', variationsController.addNewVariationToProduct); | ||||||
|  | app.use('/api', router); | ||||||
|  |  | ||||||
|  | console.log(`Planetposen backend running on port: ${PORT}`) | ||||||
|  | server.listen(PORT); | ||||||
							
								
								
									
										53
									
								
								server/controllers/product.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								server/controllers/product.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | |||||||
|  | const Products = require('src/products.js') | ||||||
|  | const products = new Products(); | ||||||
|  |  | ||||||
|  | // HELPERS | ||||||
|  | const handleError = (error, res) => { | ||||||
|  |   const { message, status, success } = error; | ||||||
|  |  | ||||||
|  |   return res.status(status || 500).send({ | ||||||
|  |     success: success || false, | ||||||
|  |     message: message || 'Unable to find product.' | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const handleReturnProduct = (product, res) => { | ||||||
|  |   return res.send({ | ||||||
|  |     success: true, | ||||||
|  |     product | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ROUTES | ||||||
|  | const allProducts = (req, res) => { | ||||||
|  |   return products.allProducts() | ||||||
|  |     .then(products => res.json(products)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const productById = (req, res) => { | ||||||
|  |   const { id } = req.params; | ||||||
|  |  | ||||||
|  |   if (id != null) { | ||||||
|  |     return products.getById(id) | ||||||
|  |       .then(product => handleReturnProduct(product, res)) | ||||||
|  |       .catch(err => handleError(err, res)) | ||||||
|  |   } else { | ||||||
|  |     return res.status(422).send({ | ||||||
|  |       success: true, | ||||||
|  |       message: 'Id must be number. Invalid request.' | ||||||
|  |     }) | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const addNewProduct = (req, res) => { | ||||||
|  |   const { product } = req.body; | ||||||
|  |  | ||||||
|  |   return products.saveNewProduct(product) | ||||||
|  |     .then(resp => res.send(resp)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  |   allProducts, | ||||||
|  |   productById, | ||||||
|  |   addNewProduct | ||||||
|  | }; | ||||||
							
								
								
									
										40
									
								
								server/controllers/variation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								server/controllers/variation.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | |||||||
|  | const { saveNewVariation } = require('src/variation.js') | ||||||
|  | const Products = require('src/products'); | ||||||
|  | const products = new Products(); | ||||||
|  |  | ||||||
|  | // HELPERS | ||||||
|  | const handleError = (error, res) => { | ||||||
|  |   const { message, status, success } = error; | ||||||
|  |  | ||||||
|  |   return res.status(status || 500).send({ | ||||||
|  |     success: success || false, | ||||||
|  |     message: message || 'Unable to find product.' | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const handleReturnProduct = (product, res) => { | ||||||
|  |   return res.send({ | ||||||
|  |     success: true, | ||||||
|  |     product | ||||||
|  |   }) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | // ROUTES | ||||||
|  | const addNewVariationToProduct = async (req, res) => { | ||||||
|  |   const productId = req.params.id; | ||||||
|  |   const { variation } = req.body; | ||||||
|  |  | ||||||
|  |   console.log('id: ', productId); | ||||||
|  |   console.log('variation: ', variation); | ||||||
|  |  | ||||||
|  |   const newVariation = await saveNewVariation(variation); | ||||||
|  |    | ||||||
|  |   return saveNewVariation(variation) | ||||||
|  |     .then(newVariation => products.addVariationToProduct(newVariation, productId)) | ||||||
|  |     .then(() => res.send('New relation added to product')) | ||||||
|  |     .catch(err => handleError(err, res)) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  |   addNewVariationToProduct | ||||||
|  | }; | ||||||
							
								
								
									
										15
									
								
								server/schemas/Product.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								server/schemas/Product.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | |||||||
|  | const mongoose = require('mongoose'); | ||||||
|  | const Schema = mongoose.Schema; | ||||||
|  |  | ||||||
|  | const Product = new Schema({ | ||||||
|  |   name: String, | ||||||
|  |   image: String, | ||||||
|  |   description: String, | ||||||
|  |   urlSlug: String, | ||||||
|  |   variations: [{ | ||||||
|  |     type: Schema.Types.ObjectId, | ||||||
|  |     ref: "Variation" | ||||||
|  |   }] | ||||||
|  |  }); | ||||||
|  |  | ||||||
|  | module.exports = mongoose.model("Product", Product) | ||||||
							
								
								
									
										12
									
								
								server/schemas/Variation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								server/schemas/Variation.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | |||||||
|  | const mongoose = require('mongoose'); | ||||||
|  | const Schema = mongoose.Schema; | ||||||
|  |  | ||||||
|  | const Variation = new Schema({ | ||||||
|  |   size: String, | ||||||
|  |   description: String, | ||||||
|  |   stock: Number, | ||||||
|  |   price: Number, | ||||||
|  |   discount: Number | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | module.exports = mongoose.model("Variation", Variation); | ||||||
							
								
								
									
										37
									
								
								server/src/products.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								server/src/products.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | |||||||
|  | const Product = require('schemas/Product'); | ||||||
|  | const { slugify } = require('src/utils'); | ||||||
|  |  | ||||||
|  | class Products { | ||||||
|  |   constructor() { | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async addVariationToProduct(variation, id) { | ||||||
|  |     return Product.findById(id) | ||||||
|  |       .then(product => { | ||||||
|  |         product.variations.push(variation); | ||||||
|  |         return product.save(); | ||||||
|  |       }) | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   async saveNewProduct(product) { | ||||||
|  |  | ||||||
|  |     const newProduct = new Product({ | ||||||
|  |       name: product.name, | ||||||
|  |       description: product.description, | ||||||
|  |       urlSlug: slugify(product.name), | ||||||
|  |       image: product.image | ||||||
|  |     }) | ||||||
|  |  | ||||||
|  |     return newProduct.save(); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   allProducts() { | ||||||
|  |     return Product.find().populate('variations'); | ||||||
|  |   } | ||||||
|  |  | ||||||
|  |   getById(id) { | ||||||
|  |     return Product.findById(id).populate('variations'); | ||||||
|  |   } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = Products; | ||||||
							
								
								
									
										19
									
								
								server/src/utils.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								server/src/utils.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,19 @@ | |||||||
|  |  | ||||||
|  | const slugify = (string) => { | ||||||
|  |   const a = 'àáâäæãåāăąçćčđďèéêëēėęěğǵḧîïíīįìłḿñńǹňôöòóœøōõőṕŕřßśšşșťțûüùúūǘůűųẃẍÿýžźż·/_,:;' | ||||||
|  |   const b = 'aaaaaaaaaacccddeeeeeeeegghiiiiiilmnnnnoooooooooprrsssssttuuuuuuuuuwxyyzzz------' | ||||||
|  |   const p = new RegExp(a.split('').join('|'), 'g') | ||||||
|  |  | ||||||
|  |   return string.toString().toLowerCase() | ||||||
|  |     .replace(/\s+/g, '-') // Replace spaces with - | ||||||
|  |     .replace(p, c => b.charAt(a.indexOf(c))) // Replace special characters | ||||||
|  |     .replace(/&/g, '-and-') // Replace & with 'and' | ||||||
|  |     .replace(/[^\w\-]+/g, '') // Remove all non-word characters | ||||||
|  |     .replace(/\-\-+/g, '-') // Replace multiple - with single - | ||||||
|  |     .replace(/^-+/, '') // Trim - from start of text | ||||||
|  |     .replace(/-+$/, '') // Trim - from end of text | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  |   slugify | ||||||
|  | } | ||||||
							
								
								
									
										22
									
								
								server/src/variation.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								server/src/variation.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | |||||||
|  | const Variation = require('schemas/Variation'); | ||||||
|  |  | ||||||
|  | const updateVariation = () => { | ||||||
|  |   return | ||||||
|  | } | ||||||
|  |  | ||||||
|  | const saveNewVariation = async (variation) => { | ||||||
|  |   const newVariation = new Variation({ | ||||||
|  |     size: variation.size, | ||||||
|  |     description: variation.description, | ||||||
|  |     stock: variation.stock || 0, | ||||||
|  |     price: variation.price, | ||||||
|  |     discount: null | ||||||
|  |   }) | ||||||
|  |  | ||||||
|  |   await newVariation.save(); | ||||||
|  |   return newVariation; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | module.exports = { | ||||||
|  |   saveNewVariation | ||||||
|  | } | ||||||
		Reference in New Issue
	
	Block a user