├── .gitignore ├── config └── db.ts ├── controllers └── goods.ts ├── deps.ts ├── public └── index.html ├── readme.md └── server.ts /.gitignore: -------------------------------------------------------------------------------- 1 | .deno_plugins/ -------------------------------------------------------------------------------- /config/db.ts: -------------------------------------------------------------------------------- 1 | import { init, MongoClient } from "../deps.ts"; 2 | 3 | // Initialize the plugin 4 | await init(); 5 | 6 | class Database { 7 | public client: MongoClient; 8 | constructor(public dbName: string, public url: string) { 9 | this.dbName = dbName; 10 | this.url = url; 11 | this.client = {} as MongoClient; 12 | } 13 | connect() { 14 | const client = new MongoClient(); 15 | client.connectWithUri(this.url); 16 | this.client = client; 17 | } 18 | 19 | get getDatabase() { 20 | return this.client.database(this.dbName); 21 | } 22 | } 23 | 24 | const dbName = "deno_supermarket"; 25 | const dbHostUrl = "mongodb://localhost:27017"; 26 | const db = new Database(dbName, dbHostUrl); 27 | db.connect(); 28 | 29 | export default db; -------------------------------------------------------------------------------- /controllers/goods.ts: -------------------------------------------------------------------------------- 1 | import { 2 | HandlerFunc, 3 | Context, 4 | } from "../deps.ts"; 5 | 6 | import db from "../config/db.ts"; 7 | 8 | // DB collection made 9 | const database = db.getDatabase; 10 | const goods = database.collection("goods"); 11 | 12 | interface Good { 13 | _id: { 14 | $oid: string; 15 | }; 16 | name: string; 17 | price: string; 18 | desc: string; 19 | } 20 | 21 | export const createGood: HandlerFunc = async (c: Context) => { 22 | try { 23 | const body = await (c.body()); 24 | if (!Object.keys(body).length) { 25 | return c.json({ 26 | code: 400, 27 | msg: `Request can't be empty` 28 | }, 200); 29 | } 30 | const { name, price, desc } = body; 31 | 32 | const insertedGood = await goods.insertOne({ 33 | name, 34 | price, 35 | desc, 36 | }); 37 | 38 | return c.json({ 39 | code: 200, 40 | msg: 'create successfully' 41 | }, 200); 42 | } catch (error) { 43 | return c.json(error, 500); 44 | } 45 | }; 46 | 47 | export const fetchAllGoods: HandlerFunc = async (c: Context) => { 48 | try { 49 | const fetchedGoods: Good[] = await goods.find(); 50 | 51 | if (fetchedGoods) { 52 | const fetchedGoodsList = fetchedGoods.length 53 | ? fetchedGoods.map((good) => { 54 | const { _id: { $oid }, name, price, desc } = good; 55 | return { id: $oid, name, price, desc }; 56 | }) 57 | : []; 58 | return c.json({ 59 | code: 200, 60 | data: fetchedGoodsList 61 | }, 200); 62 | } 63 | } catch (error) { 64 | return c.json(error, 500); 65 | } 66 | }; 67 | 68 | export const fetchOneGood: HandlerFunc = async (c: Context) => { 69 | try { 70 | const { name } = c.params as { name: string }; 71 | 72 | const fetchedGood = await goods.findOne({name: decodeURIComponent(name)}); 73 | 74 | if (fetchedGood) { 75 | const { _id: { $oid }, name, price, desc } = fetchedGood; 76 | return c.json({ 77 | code: 200, 78 | data: { 79 | id: $oid, name, price, desc 80 | } 81 | }, 200); 82 | } 83 | return c.json({ 84 | code: 404, 85 | msg: 'Good not found' 86 | }, 200); 87 | } catch (error) { 88 | return c.json(error, 500); 89 | } 90 | }; 91 | 92 | export const updateGood: HandlerFunc = async (c: Context) => { 93 | try { 94 | const { id } = c.params as { id: string }; 95 | 96 | const body = await (c.body()) as { 97 | name?: string; 98 | price?: string; 99 | desc?: string; 100 | }; 101 | 102 | if (!Object.keys(body).length) { 103 | return c.json({ 104 | code: 400, 105 | msg: "Request can't be empty", 106 | }, 200); 107 | } 108 | 109 | const fetchedGood = await goods.findOne({ _id: { "$oid": id } }); 110 | 111 | if (fetchedGood) { 112 | const { matchedCount } = await goods.updateOne( 113 | { _id: { "$oid": id } }, 114 | { $set: body }, 115 | ); 116 | if (matchedCount) { 117 | return c.json({ 118 | code: 200, 119 | msg: 'Good updated successfully!' 120 | }, 200); 121 | } 122 | return c.json({ 123 | code: 500, 124 | msg: 'Unable to update Good' 125 | }, 200); 126 | } 127 | 128 | return c.json({ 129 | code: 404, 130 | msg: 'Good not found' 131 | }, 200); 132 | } catch (error) { 133 | return c.json(error, 500); 134 | } 135 | }; 136 | 137 | export const deleteGood: HandlerFunc = async (c: Context) => { 138 | try { 139 | const { id } = c.params as { id: string }; 140 | 141 | const fetchedGood = await goods.findOne({ _id: { "$oid": id } }); 142 | 143 | if (fetchedGood) { 144 | const deleteCount = await goods.deleteOne({ _id: { "$oid": id } }); 145 | console.log(deleteCount) 146 | if (deleteCount) { 147 | return c.json({code: 200, msg: 'ok'}, 200); 148 | } 149 | return c.json({code: 500, msg: 'Unable to delete good'}, 200); 150 | } 151 | 152 | return c.json({ 153 | code: 404, 154 | msg: 'good not found' 155 | }, 200); 156 | } catch (error) { 157 | return c.json(error, 500); 158 | } 159 | }; -------------------------------------------------------------------------------- /deps.ts: -------------------------------------------------------------------------------- 1 | export * from 'https://deno.land/x/abc@v1.0.0-rc2/mod.ts'; 2 | export * from 'https://deno.land/x/mongo@v0.6.0/mod.ts' -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Deno Supermarket 7 | 8 | 9 | 10 | 11 | 32 | 33 | 34 |
35 |
36 | 37 | 38 | 39 |
40 | 41 |
42 | 43 | 44 | 78 |
79 | 80 | 262 | 263 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | ## What's it? 2 | Use deno + ts + mongodb to build a supermarket App! 3 | 4 | > Tips: You should install deno 1.0 and mongodb on your machine. 5 | 6 | ## How to lauch it ? 7 | ```bash 8 | # goto the root dir, then: 9 | deno run -A --unstable ./server.ts 10 | ``` 11 | 12 | After launching successfully, you can visit the page on http://localhost:8000/pages/ . 13 | 14 | 15 | 16 | ## UI 17 | ![](https://ok.166.net/gameyw-misc/opd/squash/20200521/173754-5hdm8j1w6c.png) 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /server.ts: -------------------------------------------------------------------------------- 1 | import { Application, Context } from "./deps.ts"; 2 | import { 3 | createGood, 4 | fetchAllGoods, 5 | fetchOneGood, 6 | updateGood, 7 | deleteGood, 8 | } from "./controllers/goods.ts"; 9 | 10 | const app = new Application(); 11 | 12 | app 13 | .static('/pages', './public') // 静态资源 14 | 15 | // 以下是增删查改的api 16 | .get("/api/goods", fetchAllGoods) 17 | .post("/api/goods", createGood) 18 | .get("/api/goods/:name", fetchOneGood) 19 | .put("/api/goods/:id", updateGood) 20 | .delete("/api/goods/:id", deleteGood) 21 | 22 | .start({ port: 8000 }); 23 | console.log('start successfully. you can visit it on http://localhost:8000/pages/') 24 | --------------------------------------------------------------------------------