Procházet zdrojové kódy

Use insertOne in POST Recipe endpoint

Tati před 7 roky
rodič
revize
9b8f1aa4ae

+ 0 - 0
ktchn/src/custom.d.ts


+ 13 - 0
ktchn/src/mongo.ts

@@ -0,0 +1,13 @@
+import { Db, connect, MongoClient, InsertOneWriteOpResult, Collection } from 'mongodb';
+import { Request, Response, NextFunction } from 'express';
+
+export default (db: Db) => (col: string) => {
+  const collection:Collection = db.collection(col);
+
+  return {
+    insertOne: (data: any):Promise<InsertOneWriteOpResult> => {
+      return collection.insertOne(data);
+    }
+  }
+};
+

+ 21 - 0
ktchn/src/recipes/controller.ts

@@ -0,0 +1,21 @@
+import { Request, Response, NextFunction } from 'express'
+import { Recipe } from './model';
+
+function isValidRecipe(data: any): data is Recipe {
+  return data.name !== undefined;
+}
+
+function validateRecipe({ body }:Request, res:Response, next:NextFunction) {
+  if (isValidRecipe(body)) {
+    res.locals = {
+      data: body as Recipe
+    };
+    next();
+  } else {
+    next(new Error('Missing recipe information: name'));
+  }
+}
+
+export {
+  validateRecipe,
+}

+ 22 - 0
ktchn/src/recipes/data.ts

@@ -0,0 +1,22 @@
+import { Recipe, RecipeDB } from './model';
+import { Request, Response, NextFunction } from 'express'
+import MongoClient from 'mongodb';
+import mongo from './../mongo';
+
+function storeRecipe(db: MongoClient.Db) {
+  return async function (req: Request, res: Response, next: NextFunction) {
+    try {
+      const data = await db.collection('recipes').insertOne(res.locals.data);
+      res.locals.savedData = data.ops[0] as RecipeDB;
+      res.json(data.ops[0]);
+      next();
+    }
+    catch (error) {
+      return next(error);
+    }
+  } 
+}
+
+export {
+  storeRecipe,
+}

+ 6 - 0
ktchn/src/recipes/model.ts

@@ -1,3 +1,5 @@
+import { ObjectID } from 'mongodb';
+
 interface QtyMetric {
   qty: number;
   unit: string;
@@ -53,3 +55,7 @@ export interface Recipe {
   course?: string[];
   summary?: string;
 }
+
+export interface RecipeDB extends Recipe {
+  _id: ObjectID;
+}

+ 15 - 13
ktchn/src/recipes/routes.ts

@@ -1,27 +1,25 @@
-import { Request, Response, Router } from "express";
+import { Request, Response, Router, NextFunction } from "express";
 import Scrape from "./scrape";
 import { Recipe } from './model';
+import { validateRecipe } from './controller';
+import { storeRecipe } from './data';
+import MongoClient from 'mongodb';
 
 class RecipeRoutes {
   public router: Router;
-  public constructor() {
+
+  public constructor(db: MongoClient.Db) {
     this.router = Router();
-    this.init();
+    this.init(db);
   }
 
-  private init() {
+  private init(db: MongoClient.Db) {
     this.router.get("/", (req, res, next) => {
       res.json({
         message: 'hey recipes bb'
       });
     })
-    this.router.post("/", (req, res, next) => {
-      const recipe = req.body as Recipe;
-      console.log(req.app.locals.db);
-      res.json({
-        message: 'k'
-      });
-    })
+    this.router.post("/", validateRecipe, storeRecipe(db), this.logData)
     this.router.post("/scrape", (req, res, next) => {
        return Scrape(req.body.url).then((x)=>{
          res.json(x)
@@ -33,7 +31,11 @@ class RecipeRoutes {
       ));
     })
   }
+
+  private logData(req:Request, res:Response, next: NextFunction): void {
+    console.log(`data: ${res.locals.savedData}`);
+    next();
+  }
 }
 
-const recipeRoutes = new RecipeRoutes();
-export default recipeRoutes.router;
+export default RecipeRoutes;

+ 29 - 10
ktchn/src/server.ts

@@ -2,12 +2,32 @@ import * as path from "path";
 import cookieParser from "cookie-parser";
 import * as bodyParser from "body-parser";
 import logger from "morgan";
-import express from "express";
+import express, { Application } from "express";
 import rootRouter from "./routes/root";
 import recipeRouter from "./recipes/routes";
 import nano from 'nano';
 import dotenv from 'dotenv';
 import MongoClient from 'mongodb';
+import { Response } from 'express';
+import mongoService from './mongo';
+import { RecipeDB } from './recipes/model';
+
+namespace Application {
+  locals: {
+    db: MongoClient.MongoClient
+  }
+}
+
+declare global {
+  namespace Express {
+    interface Response {
+      app: Application,
+      locals: {
+        savedData: RecipeDB
+      }
+    }
+  }
+}
 
 class App {
   public app: express.Application;
@@ -16,16 +36,15 @@ class App {
     this.dotENV();
     this.app = express();
     this.middleware();
-    this.routes();
-    this.launchConf();
+    this.launchApp();
   }
 
   private dotENV(): void {
     dotenv.config();
   }
   
-  private routes(): void {
-    this.app.use("/recipes", recipeRouter);
+  private routes(db: MongoClient.Db): void {
+    this.app.use("/recipes", new recipeRouter(db).router);
     this.app.use("/", rootRouter);
   }
 
@@ -39,13 +58,13 @@ class App {
     this.app.use(express.static(path.join(__dirname, "public")));
   }
 
-  private launchMongoDb(): Promise<MongoClient.MongoClient> {
-    return MongoClient.connect('mongodb://127.0.0.1:27017/api');
+  private connectDB(): Promise<MongoClient.Db> {
+    return MongoClient.connect('mongodb://127.0.0.1:27017').then(dbClient => dbClient.db('ktchn'));
   }
 
-  private launchConf() {
-    this.launchMongoDb().then(dbClient => {
-      this.app.locals.db = dbClient;
+  private launchApp() {
+    this.connectDB().then(db => {
+      this.routes(db);
       const port = this.app.get("port");
       this.app.listen(port, () => {
         console.log(