Skip to content

Commit

Permalink
refactor bunch of stuff (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
BoxenOfDonuts committed Jul 14, 2024
1 parent a411763 commit 34517c6
Show file tree
Hide file tree
Showing 9 changed files with 352 additions and 193 deletions.
25 changes: 25 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
**/.classpath
**/.dockerignore
**/.env
**/.git
**/.gitignore
**/.project
**/.settings
**/.toolstarget
**/.vs
**/.vscode
**/*.*proj.user
**/*.dbmdl
**/*.jfm
**/bin
**/charts
**/docker-compose*
**/compose*
**/Dockerfile*
**/node_modules
**/npm-debug.log
**/obj
**/secrets.dev.yaml
**/values.dev.yaml
LICENSE
README.md
15 changes: 15 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
FROM denoland/deno

EXPOSE 8000

WORKDIR /app

# prefer not to run as root
USER deno

# Cache the dependencies as a layer (the following two steps are re-run only when deps.ts is modified).
# Ideally cache deps.ts will download and compile _all_ external files used in main.ts.
COPY . /app
RUN deno cache main.ts

CMD ["run", "--allow-net", "--allow-env", "--allow-read", "--unstable-kv", "main.ts"]
35 changes: 35 additions & 0 deletions constants/constants.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { load } from "std/dotenv/mod.ts";
const env = await load();

const USER_NAME = getEnv("USER_NAME");
const PASSWORD = getEnv("PASSWORD");

Deno.env.set("DENO_KV_ACCESS_TOKEN", getEnv("DENO_KV_ACCESS_TOKEN"));
const KV_PATH = _undefinedEnv("KV_PATH");

const ROOM_KEY = "room";
const ROOM_CLIMATE_KEY = "room_climate";
const ROOM_BY_ID_KEY = "room_by_id";

function getEnv(key: string): string {
const result = env[key] || Deno.env.get(key);
if (!result) {
throw new Error(
`Missing env var ${key}, make sure you have a .env file or you pass it in via the command line`,
);
}
return result;
}

function _undefinedEnv(key: string): string | undefined {
return env[key] || Deno.env.get(key);
}

export {
KV_PATH,
PASSWORD,
ROOM_BY_ID_KEY,
ROOM_CLIMATE_KEY,
ROOM_KEY,
USER_NAME,
};
13 changes: 13 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
version: '3'

services:
web:
build: .
container_name: deno-container
environment:
- USER_NAME=<USER_NAME>
- PASSWORD=<PASSWORD>
- DENO_KV_ACCESS_TOKEN=<DENO_KV_ACCESS_TOKEN>
- KV_PATH=<KV_PATH>
ports:
- "8000:8000"
73 changes: 58 additions & 15 deletions main.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,20 @@
import { Application, Router } from "@oak/oak";
import { compareSync } from "bcrypt";
import { PASSWORD, USER_NAME } from "./src/constants.ts";
import { PASSWORD, USER_NAME } from "./constants/constants.ts";

import {
deleteRoomByName,
createRoom,
deleteAllKeys,
deleteRoom,
getAllKeys,
getAllRoomClimates,
getAllRooms,
getClimateByRoomName,
getRoomByName,
getClimate,
getRoom,
subscribeToChanges,
updateRoom,
upsertClimate,
upsertRoom,
} from "./src/db.ts";
} from "./services/db.ts";

const router = new Router();

Expand All @@ -25,41 +28,81 @@ router
})
.get("/rooms/:name/climate", async (ctx) => {
const name = ctx?.params?.name;
ctx.response.body = await getClimateByRoomName(name);
ctx.response.body = await getClimate(name);
})
.get("/rooms/:name", async (ctx) => {
const name = ctx?.params?.name;
ctx.response.body = await getRoomByName(name);
ctx.response.body = await getRoom(name);
})
.post("/rooms", async (ctx) => {
const body = ctx.request.body;
const room = await body.json();
await upsertRoom(room);
const success = await createRoom(room.name);
if (!success) {
ctx.response.status = 409;
return;
}
return ctx.response.status = 201;
})
.put("/rooms", async (ctx) => {
const body = ctx.request.body;
const room = await body.json();
const success = await updateRoom(room);
if (!success) {
ctx.response.status = 409;
return;
}
return ctx.response.status = 201;
})
.put("/rooms/:name/climate", async (ctx) => {
const name = ctx?.params?.name;
const body = ctx.request.body;
const climate = await body.json();
await upsertClimate(name, climate);
const success = await upsertClimate(name, climate);
if (!success) {
ctx.response.status = 409;
return;
}
return ctx.response.status = 201;
})
.delete("/rooms/:name", async (ctx) => {
const name = ctx?.params?.name;
await deleteRoomByName(name);
await deleteRoom(name);
return ctx.response.status = 204;
})
.get("/all", async (ctx) => {
ctx.response.body = await getAllKeys();
})
.get("/all/:prefix", async (ctx) => {
const prefix = ctx?.params?.prefix;
const prefix = ctx.request.url.searchParams.get("prefix");
ctx.response.body = await getAllKeys(prefix);
})
.delete("/all", async (ctx) => {
await deleteAllKeys();
ctx.response.status = 204;
})
.get("/server-sent-events", async (ctx) => {
console.log("server sent", ctx.request.url.searchParams.getAll("room"));
const roomIds = ctx.request.url.searchParams.getAll("room");
if (!roomIds.length) {
ctx.response.status = 400;
return;
}
const target = await ctx.sendEvents();
const cancel = subscribeToChanges(roomIds, (data) => {
target.dispatchMessage(data);
});
target.addEventListener("close", () => {
console.log("client closed connection");
cancel();
});
});

const app = new Application();

app.use(async (ctx, next) => {
// if going to /server-sent-events, we don't need to check for auth
if (ctx.request.url.pathname === "/server-sent-events") {
await next();
return;
}
const authHeader = ctx.request.headers.get("Authorization");
if (!authHeader) {
ctx.response.headers.append("WWW-Authenticate", "Basic");
Expand Down
Loading

0 comments on commit 34517c6

Please sign in to comment.