@graffy/server 0.15.16 → 0.15.19-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/Readme.md CHANGED
@@ -4,4 +4,4 @@ Node.js library for building an API for a Graffy store.
4
4
 
5
5
  This creates an HTTP request handler for serving an API that is compatible with Graffy Client. The request handler can be used with the Node.js built-in http, https and http2 `createServer()` and with Express.js.
6
6
 
7
- See [Graffy documentation](https://aravindet.github.io/graffy/#/GraffyServer) for more.
7
+ See [Graffy documentation](https://graffy.org#/GraffyServer) for more.
package/index.cjs CHANGED
@@ -23,22 +23,21 @@ exports[Symbol.toStringTag] = "Module";
23
23
  var url = require("url");
24
24
  var common = require("@graffy/common");
25
25
  var debug = require("debug");
26
- var WebSocket = require("ws");
26
+ var ws = require("ws");
27
27
  function _interopDefaultLegacy(e) {
28
28
  return e && typeof e === "object" && "default" in e ? e : { "default": e };
29
29
  }
30
30
  var url__default = /* @__PURE__ */ _interopDefaultLegacy(url);
31
31
  var debug__default = /* @__PURE__ */ _interopDefaultLegacy(debug);
32
- var WebSocket__default = /* @__PURE__ */ _interopDefaultLegacy(WebSocket);
33
32
  const log$1 = debug__default["default"]("graffy:server:http");
34
- function server$1(store) {
33
+ function server$1(store, { auth } = {}) {
35
34
  if (!store)
36
35
  throw new Error("server.store_undef");
37
36
  return async (req, res) => {
38
37
  const parsed = url__default["default"].parse(req.url, true);
39
- const query = parsed.query.q && common.decodeUrl(parsed.query.q);
40
38
  const options = parsed.query.opts && !Array.isArray(parsed.query.opts) && common.deserialize(decodeURIComponent(parsed.query.opts));
41
39
  if (req.method === "GET") {
40
+ const query = parsed.query.q && common.decodeUrl(parsed.query.q);
42
41
  try {
43
42
  if (req.headers["accept"] === "text/event-stream") {
44
43
  res.setHeader("content-type", "text/event-stream");
@@ -79,7 +78,7 @@ data: ${e.message}
79
78
  }
80
79
  } else if (req.method === "POST") {
81
80
  try {
82
- const op = req.query.op;
81
+ const op = parsed.query.op;
83
82
  if (op !== "write" && op !== "read") {
84
83
  throw Error("httpServer.unsupported_op: " + op);
85
84
  }
@@ -87,6 +86,11 @@ data: ${e.message}
87
86
  for await (const chunk of req)
88
87
  chunks.push(chunk);
89
88
  const payload = common.deserialize(Buffer.concat(chunks).toString());
89
+ if (auth && !await auth(op, payload, options)) {
90
+ res.writeHead(401);
91
+ res.end("unauthorized");
92
+ return;
93
+ }
90
94
  const value = await store.call(op, payload, options);
91
95
  res.writeHead(200);
92
96
  res.end(common.serialize(value));
@@ -107,14 +111,14 @@ const PING_INTERVAL = 3e4;
107
111
  function server(store) {
108
112
  if (!store)
109
113
  throw new Error("server.store_undef");
110
- const wss = new WebSocket__default["default"].Server({ noServer: true });
111
- wss.on("connection", function connection(ws) {
112
- ws.graffyStreams = {};
113
- ws.on("message", async function message(msg) {
114
+ const wss = new ws.WebSocketServer({ noServer: true });
115
+ wss.on("connection", function connection(ws2) {
116
+ ws2.graffyStreams = {};
117
+ ws2.on("message", async function message(msg) {
114
118
  try {
115
119
  const [id, op, payload, options] = common.deserialize(msg);
116
120
  if (id === ":pong") {
117
- ws.pingPending = false;
121
+ ws2.pingPending = false;
118
122
  return;
119
123
  }
120
124
  switch (op) {
@@ -122,10 +126,10 @@ function server(store) {
122
126
  case "write":
123
127
  try {
124
128
  const result = await store.call(op, payload, options);
125
- ws.send(common.serialize([id, null, result]));
129
+ ws2.send(common.serialize([id, null, result]));
126
130
  } catch (e) {
127
131
  log(op + "error:" + e.message + " " + payload);
128
- ws.send(common.serialize([id, e.message]));
132
+ ws2.send(common.serialize([id, e.message]));
129
133
  }
130
134
  break;
131
135
  case "watch":
@@ -133,44 +137,44 @@ function server(store) {
133
137
  const stream = store.call("watch", payload, __spreadProps(__spreadValues({}, options), {
134
138
  raw: true
135
139
  }));
136
- ws.graffyStreams[id] = stream;
140
+ ws2.graffyStreams[id] = stream;
137
141
  for await (const value of stream) {
138
- ws.send(common.serialize([id, null, value]));
142
+ ws2.send(common.serialize([id, null, value]));
139
143
  }
140
144
  } catch (e) {
141
145
  log(op + "error:" + e.message + " " + payload);
142
- ws.send(common.serialize([id, e.message]));
146
+ ws2.send(common.serialize([id, e.message]));
143
147
  }
144
148
  break;
145
149
  case "unwatch":
146
- if (!ws.graffyStreams[id])
150
+ if (!ws2.graffyStreams[id])
147
151
  break;
148
- ws.graffyStreams[id].return();
149
- delete ws.graffyStreams[id];
152
+ ws2.graffyStreams[id].return();
153
+ delete ws2.graffyStreams[id];
150
154
  break;
151
155
  }
152
156
  } catch (_) {
153
- ws.close();
157
+ ws2.close();
154
158
  }
155
159
  });
156
- ws.on("close", () => {
157
- for (const id in ws.graffyStreams) {
158
- ws.graffyStreams[id].return();
159
- delete ws.graffyStreams[id];
160
+ ws2.on("close", () => {
161
+ for (const id in ws2.graffyStreams) {
162
+ ws2.graffyStreams[id].return();
163
+ delete ws2.graffyStreams[id];
160
164
  }
161
165
  });
162
166
  });
163
167
  setInterval(function ping() {
164
- wss.clients.forEach(function each(ws) {
165
- if (ws.pingPending)
166
- return ws.terminate();
167
- ws.pingPending = true;
168
- ws.send(common.serialize([":ping", Date.now()]));
168
+ wss.clients.forEach(function each(ws2) {
169
+ if (ws2.pingPending)
170
+ return ws2.terminate();
171
+ ws2.pingPending = true;
172
+ ws2.send(common.serialize([":ping", Date.now()]));
169
173
  });
170
174
  }, PING_INTERVAL);
171
175
  return async (request, socket, head) => {
172
- wss.handleUpgrade(request, socket, head, function done(ws) {
173
- wss.emit("connection", ws, request);
176
+ wss.handleUpgrade(request, socket, head, function done(ws2) {
177
+ wss.emit("connection", ws2, request);
174
178
  });
175
179
  };
176
180
  }
package/index.mjs CHANGED
@@ -18,18 +18,18 @@ var __spreadValues = (a, b) => {
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
20
  import url from "url";
21
- import { decodeUrl, deserialize, serialize } from "@graffy/common";
21
+ import { deserialize, decodeUrl, serialize } from "@graffy/common";
22
22
  import debug from "debug";
23
- import WebSocket from "ws";
23
+ import { WebSocketServer } from "ws";
24
24
  const log$1 = debug("graffy:server:http");
25
- function server$1(store) {
25
+ function server$1(store, { auth } = {}) {
26
26
  if (!store)
27
27
  throw new Error("server.store_undef");
28
28
  return async (req, res) => {
29
29
  const parsed = url.parse(req.url, true);
30
- const query = parsed.query.q && decodeUrl(parsed.query.q);
31
30
  const options = parsed.query.opts && !Array.isArray(parsed.query.opts) && deserialize(decodeURIComponent(parsed.query.opts));
32
31
  if (req.method === "GET") {
32
+ const query = parsed.query.q && decodeUrl(parsed.query.q);
33
33
  try {
34
34
  if (req.headers["accept"] === "text/event-stream") {
35
35
  res.setHeader("content-type", "text/event-stream");
@@ -70,7 +70,7 @@ data: ${e.message}
70
70
  }
71
71
  } else if (req.method === "POST") {
72
72
  try {
73
- const op = req.query.op;
73
+ const op = parsed.query.op;
74
74
  if (op !== "write" && op !== "read") {
75
75
  throw Error("httpServer.unsupported_op: " + op);
76
76
  }
@@ -78,6 +78,11 @@ data: ${e.message}
78
78
  for await (const chunk of req)
79
79
  chunks.push(chunk);
80
80
  const payload = deserialize(Buffer.concat(chunks).toString());
81
+ if (auth && !await auth(op, payload, options)) {
82
+ res.writeHead(401);
83
+ res.end("unauthorized");
84
+ return;
85
+ }
81
86
  const value = await store.call(op, payload, options);
82
87
  res.writeHead(200);
83
88
  res.end(serialize(value));
@@ -98,7 +103,7 @@ const PING_INTERVAL = 3e4;
98
103
  function server(store) {
99
104
  if (!store)
100
105
  throw new Error("server.store_undef");
101
- const wss = new WebSocket.Server({ noServer: true });
106
+ const wss = new WebSocketServer({ noServer: true });
102
107
  wss.on("connection", function connection(ws) {
103
108
  ws.graffyStreams = {};
104
109
  ws.on("message", async function message(msg) {
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@graffy/server",
3
3
  "description": "Node.js library for building an API for a Graffy store.",
4
4
  "author": "aravind (https://github.com/aravindet)",
5
- "version": "0.15.16",
5
+ "version": "0.15.19-alpha.1",
6
6
  "main": "./index.cjs",
7
7
  "exports": {
8
8
  "import": "./index.mjs",
@@ -16,8 +16,8 @@
16
16
  },
17
17
  "license": "Apache-2.0",
18
18
  "dependencies": {
19
- "@graffy/common": "0.15.16",
20
- "debug": "^4.3.2",
21
- "ws": "^7.0.0"
19
+ "@graffy/common": "0.15.19-alpha.1",
20
+ "debug": "^4.3.3",
21
+ "ws": "^8.4.2"
22
22
  }
23
23
  }
@@ -1 +1,12 @@
1
- export default function server(store: any): (req: any, res: any) => Promise<void>;
1
+ /**
2
+ * @typedef {import('@graffy/core').default} GraffyStore
3
+ * @param {GraffyStore} store
4
+ * @param {{
5
+ * auth?: (operation: string, payload: any, options: any) => Promise<boolean>
6
+ * } | undefined} options
7
+ * @returns
8
+ */
9
+ export default function server(store: any, { auth }?: {
10
+ auth?: (operation: string, payload: any, options: any) => Promise<boolean>;
11
+ }): (req: any, res: any) => Promise<void>;
12
+ export type GraffyStore = any;