summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Van Doorn <vandoorn.nick@gmail.com>2019-01-20 20:12:42 -0800
committerNick Van Doorn <vandoorn.nick@gmail.com>2019-01-20 20:12:42 -0800
commit32dc1dc50ac8af58c27b25b1fa9017f48cbd995f (patch)
treea50c2ad6ae60d733787eda1ffea75924ab1820c5
parentadd434f81bdfdedb6ad4897b3dc96ac291793f52 (diff)
Implement naive-server
-rw-r--r--server/bin/index.ts10
-rw-r--r--server/src/context.model.ts5
-rw-r--r--server/src/operations.ts53
-rw-r--r--server/src/server.test.ts27
-rw-r--r--server/src/server.ts18
-rw-r--r--server/tsconfig.json2
6 files changed, 114 insertions, 1 deletions
diff --git a/server/bin/index.ts b/server/bin/index.ts
new file mode 100644
index 0000000..fdf1352
--- /dev/null
+++ b/server/bin/index.ts
@@ -0,0 +1,10 @@
+import { runServer } from "../src/server";
+import process from "process";
+
+const port = +(process.env.PORT || 5000);
+
+runServer({
+ httpPort: port,
+ wsPort: port + 1,
+ logger: console.log
+});
diff --git a/server/src/context.model.ts b/server/src/context.model.ts
new file mode 100644
index 0000000..d8419d4
--- /dev/null
+++ b/server/src/context.model.ts
@@ -0,0 +1,5 @@
+export interface Context {
+ httpPort: number;
+ wsPort: number;
+ logger: (e: any) => any;
+}
diff --git a/server/src/operations.ts b/server/src/operations.ts
new file mode 100644
index 0000000..32b3b75
--- /dev/null
+++ b/server/src/operations.ts
@@ -0,0 +1,53 @@
+import { Context } from "./context.model";
+import { SubscriptionRequest } from "../../lib/subscription-req.model";
+import { WriteRequest } from "../../lib/write-req.model";
+import { DatabaseChange } from "../../lib/database-change.model";
+
+import { DatabaseInterface } from "naive-core";
+
+import express, { RequestHandler } from "express";
+
+export const bindOperations = (
+ ctx: Context,
+ db: DatabaseInterface,
+ send: (e: DatabaseChange) => Promise<any>
+) => {
+ const unsubs: { [key: string]: () => any } = {};
+
+ const writeHandler: RequestHandler = async (req, res) => {
+ const { path, toWrite } = req.body as WriteRequest;
+ await db.write(path, toWrite);
+ };
+
+ const addSubHandler: RequestHandler = async (req, res) => {
+ const { path } = req.body as SubscriptionRequest;
+ // only allow users to subscribe
+ // to a given path once
+ // TODO return a better error
+ if (unsubs[path]) {
+ res.status(500).end();
+ return;
+ }
+ unsubs[path] = db.subscribe(path, async (change: Object) => {
+ await send({
+ path,
+ change
+ });
+ });
+ res.status(200).end();
+ };
+
+ const removeSubHandler: RequestHandler = async (req, res) => {
+ const { path } = req.body as SubscriptionRequest;
+ const unsub = unsubs[path];
+ if (unsub) unsub();
+ };
+
+ const router = express();
+ router.post("/write", writeHandler);
+ router
+ .route("/subscribe")
+ .post(addSubHandler)
+ .delete(removeSubHandler);
+ router.listen(ctx.httpPort, () => ctx.logger("HTTPS server started"));
+};
diff --git a/server/src/server.test.ts b/server/src/server.test.ts
new file mode 100644
index 0000000..d92ae0f
--- /dev/null
+++ b/server/src/server.test.ts
@@ -0,0 +1,27 @@
+import { runServer } from "./server";
+import process from "process";
+
+// we test the server using the client
+import { dbFactory, DatabaseConnection } from "naive-client";
+
+const port = +(process.env.PORT || 5000);
+const httpPort = port;
+const wsPort = port + 1;
+
+describe("Server module", async () => {
+ let db: DatabaseConnection;
+ beforeAll(async () => {
+ await runServer({
+ httpPort,
+ wsPort,
+ logger: console.log
+ });
+ db = dbFactory({ httpPort, wsPort, url: "localhost" });
+ await db.init();
+ });
+ test("it should work", async () => {
+ await db.write("/hello/world", {
+ my: "data"
+ });
+ });
+});
diff --git a/server/src/server.ts b/server/src/server.ts
new file mode 100644
index 0000000..f80bd2b
--- /dev/null
+++ b/server/src/server.ts
@@ -0,0 +1,18 @@
+import { Context } from "./context.model";
+import { bindOperations } from "./operations";
+import { DatabaseChange } from "../../lib/database-change.model";
+import WebSocket from "ws";
+
+import { Database, Context as CoreContext } from "naive-core";
+
+export const runServer = async (ctx: Context) => {
+ const db = new Database();
+ await db.init();
+ const wss = new WebSocket.Server({ port: ctx.wsPort });
+
+ bindOperations(ctx, db, async (dbChange: DatabaseChange) => {
+ for (let client of wss.clients) {
+ client.send(dbChange);
+ }
+ });
+};
diff --git a/server/tsconfig.json b/server/tsconfig.json
index 9e35360..3bae4ad 100644
--- a/server/tsconfig.json
+++ b/server/tsconfig.json
@@ -14,7 +14,7 @@
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
"outDir": "./dist" /* Redirect output structure to the directory. */,
- // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
+ "rootDir": "../" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */,
// "composite": true, /* Enable project compilation */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */