├── .vscode └── settings.json ├── README.md ├── main.ts └── view.ts /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enable": true, 3 | "deno.lint": true, 4 | "deno.unstable": true, 5 | "deno.suggest.imports.hosts": { 6 | "https://deno.land": false 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # deno-deploy-mongo 2 | A sample project using Deno + Deno Deploy + MongoDB + Oak 3 | 4 | ## Link 5 | https://mongo-demo.deno.dev/ 6 | 7 | ## Screenshot 8 | 9 | ![Screenshot from 2021-12-13 21-00-25](https://user-images.githubusercontent.com/47688578/145860382-0f1f1e15-45b9-43dc-b228-c7f488f9b189.png) 10 | -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | import { 2 | Application, 3 | Router, 4 | Status, 5 | } from "https://deno.land/x/oak@v10.0.0/mod.ts"; 6 | import { Bson, MongoClient } from "https://deno.land/x/mongo@v0.29.3/mod.ts"; 7 | import { timeAgo } from "https://deno.land/x/time_ago@v1/mod.ts"; 8 | 9 | import view from "./view.ts"; 10 | 11 | const MONGO_URI = Deno.env.get("MONGO_URI"); 12 | if (!MONGO_URI) throw new Error("MONGO_URI not found"); 13 | 14 | const deploymentTime = Date.now(); 15 | 16 | const app = new Application(); 17 | const router = new Router(); 18 | 19 | const client = new MongoClient(); 20 | try { 21 | await client.connect(MONGO_URI); 22 | } catch (err) { 23 | console.error("Error connecting to MongoDB", err); 24 | throw err; 25 | } 26 | 27 | interface Post { 28 | _id: Bson.ObjectId; 29 | title: string; 30 | } 31 | 32 | const collection = client.database().collection("posts"); 33 | 34 | router.get("/", async (ctx) => { 35 | try { 36 | const posts = await collection 37 | .find({}, { noCursorTimeout: false }) 38 | .sort({ 39 | _id: -1, 40 | }) 41 | .map((post) => ({ 42 | ...post, 43 | timeAgo: timeAgo(post._id.getTimestamp()), 44 | })); 45 | 46 | ctx.response.body = view(posts)!; 47 | } catch (err) { 48 | console.error("Error on find", Date.now() - deploymentTime, err); 49 | throw err; 50 | } 51 | }); 52 | 53 | router.post("/", async (ctx) => { 54 | if (!ctx.request.hasBody) ctx.throw(Status.BadRequest, "Bad Request"); 55 | 56 | const body = await ctx.request.body().value; 57 | if (!body) ctx.throw(Status.BadRequest, "Bad Request"); 58 | 59 | const title = body.title; 60 | if (!title) ctx.throw(Status.BadRequest, "Title is required"); 61 | 62 | const post = { 63 | _id: new Bson.ObjectId(), 64 | title, 65 | }; 66 | 67 | await collection.insertOne(post); 68 | 69 | ctx.response.body = post; 70 | }); 71 | 72 | app.use(router.routes()); 73 | app.use(router.allowedMethods()); 74 | 75 | app.listen({ port: 8000 }); 76 | -------------------------------------------------------------------------------- /view.ts: -------------------------------------------------------------------------------- 1 | const e = (s: string) => 2 | s.replace(/&/g, "&").replace(//g, ">"); 3 | 4 | interface Post { 5 | title: string; 6 | timeAgo: string; 7 | } 8 | 9 | const script = `async function post() { 10 | const input = document.getElementById("message"); 11 | const title = input.value; 12 | 13 | if (!title) return; 14 | 15 | const response = await fetch("/", { 16 | method: "POST", 17 | headers: { 18 | "Content-Type": "application/json" 19 | }, 20 | body: JSON.stringify({ title }) 21 | }); 22 | 23 | if (response.ok) { 24 | // Reload the page 25 | location.reload(); 26 | } 27 | }`; 28 | 29 | const head = ` 30 | Deno + Deno Deploy + MongoDB Demo 31 | 32 | 33 | 34 | 35 | 36 | `; 37 | 38 | const post = (p: Post) => 39 | `
40 |
41 |
${e(p.title)}
42 |

${p.timeAgo}

43 |
44 |
`; 45 | 46 | const body = (p: Post[]) => 47 | `
48 |

Deno + Deno Deploy + MongoDB Demo

49 |
50 | 51 | 52 |
53 |

Posts

54 |
55 | ${p.map(post).join("")} 56 |
57 |
`; 58 | 59 | const footer = ``; 64 | 65 | export default (p: Post[]) => 66 | ` 67 | 68 | ${head} 69 | 70 | ${body(p)} 71 | ${footer} 72 | 73 | `; 74 | --------------------------------------------------------------------------------