diff options
author | Nick Van Doorn <vandoorn.nick@gmail.com> | 2019-01-20 20:12:42 -0800 |
---|---|---|
committer | Nick Van Doorn <vandoorn.nick@gmail.com> | 2019-01-20 20:12:42 -0800 |
commit | 32dc1dc50ac8af58c27b25b1fa9017f48cbd995f (patch) | |
tree | a50c2ad6ae60d733787eda1ffea75924ab1820c5 | |
parent | add434f81bdfdedb6ad4897b3dc96ac291793f52 (diff) |
Implement naive-server
-rw-r--r-- | server/bin/index.ts | 10 | ||||
-rw-r--r-- | server/src/context.model.ts | 5 | ||||
-rw-r--r-- | server/src/operations.ts | 53 | ||||
-rw-r--r-- | server/src/server.test.ts | 27 | ||||
-rw-r--r-- | server/src/server.ts | 18 | ||||
-rw-r--r-- | server/tsconfig.json | 2 |
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. */ |