From bf6d521963b3a9d36a4af4d590dfb3562f7f46c3 Mon Sep 17 00:00:00 2001 From: Valerie Date: Thu, 21 Jul 2022 23:45:52 -0400 Subject: [PATCH] channel list --- .gitignore | 3 + docker-compose.yml | 8 +- packages/renderer/.eslintrc.json | 3 +- packages/renderer/index.html | 2 +- packages/renderer/src/index.tsx | 8 +- packages/renderer/src/lib/api.ts | 5 +- packages/renderer/src/pages/Channels.tsx | 51 ++++++++++++ packages/renderer/src/pages/Chat.tsx | 1 - packages/server/.env | 4 +- packages/server/.eslintrc.json | 3 +- packages/server/src/db/migrate.ts | 20 ++--- .../server/src/db/snippets/channel/list.sql | 2 +- packages/server/src/index.ts | 57 ++++---------- packages/server/src/lib/WebSocketServer.ts | 78 +++++++++++++++++++ packages/server/src/{ => lib}/router.ts | 4 +- packages/server/src/routers/channel.ts | 11 +++ packages/server/src/routers/message.ts | 25 +++--- packages/server/src/routers/root.ts | 9 --- 18 files changed, 200 insertions(+), 94 deletions(-) create mode 100644 packages/renderer/src/pages/Channels.tsx create mode 100644 packages/server/src/lib/WebSocketServer.ts rename packages/server/src/{ => lib}/router.ts (96%) create mode 100644 packages/server/src/routers/channel.ts delete mode 100644 packages/server/src/routers/root.ts diff --git a/.gitignore b/.gitignore index 170663c..223e1a0 100644 --- a/.gitignore +++ b/.gitignore @@ -56,3 +56,6 @@ thumbs.db # Editor-based Rest Client .idea/httpRequests /.idea/csv-plugin.xml + +# docker data +docker-volume diff --git a/docker-compose.yml b/docker-compose.yml index 3060647..fa0d93f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -6,12 +6,16 @@ services: restart: always environment: MARIADB_ROOT_PASSWORD: example - MARIADB_ROOT_HOST: '127.0.0.1' + MARIADB_DATABASE: corner + MARIADB_USER: corner + MARIADB_PASSWORD: corner ports: - 3306:3306 + # volumes: + # - ./docker-volume:/var/lib/mysql adminer: image: adminer restart: always ports: - - 8080:8080 \ No newline at end of file + - 8080:8080 diff --git a/packages/renderer/.eslintrc.json b/packages/renderer/.eslintrc.json index e3ff5e2..a12ca5f 100644 --- a/packages/renderer/.eslintrc.json +++ b/packages/renderer/.eslintrc.json @@ -16,6 +16,7 @@ "rules": { "no-unused-vars": "off", "@typescript-eslint/no-unused-vars": "off", - "@typescript-eslint/no-explicit-any": "off" + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/ban-types": "off" } } diff --git a/packages/renderer/index.html b/packages/renderer/index.html index f84cf68..72a6d18 100644 --- a/packages/renderer/index.html +++ b/packages/renderer/index.html @@ -7,7 +7,7 @@ Vite App -
+
diff --git a/packages/renderer/src/index.tsx b/packages/renderer/src/index.tsx index 11550a0..0fc1377 100644 --- a/packages/renderer/src/index.tsx +++ b/packages/renderer/src/index.tsx @@ -1,13 +1,17 @@ import React from 'react'; import ReactDOM from 'react-dom'; +import Channels from './pages/Channels'; import Chat from './pages/Chat'; ReactDOM.render( ( <> - + > */} + ), document.getElementById('app'), diff --git a/packages/renderer/src/lib/api.ts b/packages/renderer/src/lib/api.ts index bc3054e..4f0590b 100644 --- a/packages/renderer/src/lib/api.ts +++ b/packages/renderer/src/lib/api.ts @@ -27,21 +27,18 @@ const connect = async () => { if(socket === null) return; connectionAttempts = 0; // socket.send('Hello Server!'); - console.log('API Connected'); }); socket.addEventListener('message', (event) => { - console.log('API Broadcasted', event.data); const {action, data} = JSON.parse(event.data); + console.log('[IN]', action, data); for(const router of routers) { - // debugger; router(action, data); } }); socket.addEventListener('close', () => { socket = null; - console.log('API Closed'); connect(); }); }; diff --git a/packages/renderer/src/pages/Channels.tsx b/packages/renderer/src/pages/Channels.tsx new file mode 100644 index 0000000..bfe553d --- /dev/null +++ b/packages/renderer/src/pages/Channels.tsx @@ -0,0 +1,51 @@ +import { useEffect, useState } from 'react'; +import { registerRouter, router, send, unregisterRouter } from '../lib/api'; + +function useRouter(actions: Function | object, deps: any[]) { + const _router = typeof actions === 'object' ? router(actions) : actions; + useEffect(() => { + registerRouter(_router); + return () => { + unregisterRouter(_router); + }; + }, deps); + + return { + send: send, + }; +} + +interface IChannel { + uid: string; + name: string; +} + +export default function Channels() { + + const [channels, setChannels] = useState([]); + + const { send } = useRouter({ + 'channels:list'(data: any) { + // console.log(data) + setChannels(data); + }, + }, [channels]); + + useEffect(() => { + if(channels.length === 0) { + send('channels:list'); + } + }, [channels]); + + return ( + <> + {channels.map(channel => ( +
+ #{channel.name} +
+ ))} + + ); +} \ No newline at end of file diff --git a/packages/renderer/src/pages/Chat.tsx b/packages/renderer/src/pages/Chat.tsx index ddf8ba1..60dfea8 100644 --- a/packages/renderer/src/pages/Chat.tsx +++ b/packages/renderer/src/pages/Chat.tsx @@ -60,7 +60,6 @@ export default () => { <>
{ migrationConnection.query(` - SELECT SCHEMA_NAME - FROM INFORMATION_SCHEMA.SCHEMATA - WHERE SCHEMA_NAME = '${database}'; + SELECT COUNT(*) as tables + FROM information_schema.tables + WHERE table_schema = '${database}'; `, async (err, res, fields) => { - if(res.length === 0) { - await new Promise((resolve, reject) => { - migrationConnection.query(`CREATE DATABASE \`${database}\` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;`, (err, res) => { - if(err) return reject(err); - return resolve(res); - }); - }); + if(res[0].tables === 0) { + // await new Promise((resolve, reject) => { + // migrationConnection.query(`CREATE DATABASE \`${database}\` /*!40100 DEFAULT CHARACTER SET utf8mb4 */;`, (err, res) => { + // if(err) return reject(err); + // return resolve(res); + // }); + // }); resolve(0); } else { const version: number = await new Promise((resolve, reject) => { diff --git a/packages/server/src/db/snippets/channel/list.sql b/packages/server/src/db/snippets/channel/list.sql index e30fc6c..24466d3 100644 --- a/packages/server/src/db/snippets/channel/list.sql +++ b/packages/server/src/db/snippets/channel/list.sql @@ -1 +1 @@ -SELECT (name, uid) FROM channels; \ No newline at end of file +SELECT name, uid FROM channels; \ No newline at end of file diff --git a/packages/server/src/index.ts b/packages/server/src/index.ts index 0f8305f..9a0c234 100644 --- a/packages/server/src/index.ts +++ b/packages/server/src/index.ts @@ -1,54 +1,23 @@ -import { WebSocketServer } from 'ws'; -import router from './routers/root'; +import router from './lib/router'; +import message from './routers/message'; +import { expose } from './lib/WebSocketServer'; -const wss = new WebSocketServer({ - port: 3000, -}, () => { - console.log('ws chat server started on dev.valnet.xyz'); +const api = router({ + up() { + console.log(Date.now()); + }, + message: message, + messages: message, + channel: channel, + channels: channel, }); -wss.on('connection', (ws) => { - ws.on('message', async (str) => { - try { - const message = JSON.parse(str.toString()); - if(typeof message.action !== 'string') { - console.warn('invalid JSON message'); - return; - } - const {action, data} = message; - try { - console.log(action, data); - const _return = await (router(action, data) as unknown as Promise); - console.log(_return); - if(_return) { - ws.send(JSON.stringify(_return)); - } - } catch(e) { - console.warn(`error in action ${action}`); - console.error(e); - } - } catch (e) { - console.warn('JSON parse failed on message'); - console.error(e); - } - }); -}); - -export function send(client: any, action: string, data?: any) { - client.send(JSON.stringify({action, data})); -} - -export function broadcast(action: string, data?: any) { - for(const client of wss.clients) { - send(client, action, data); - } -} - -export default wss; +expose(api, 3000); // ------------- import { update } from './db/migrate'; +import channel from './routers/channel'; try { update(); diff --git a/packages/server/src/lib/WebSocketServer.ts b/packages/server/src/lib/WebSocketServer.ts new file mode 100644 index 0000000..cc356d7 --- /dev/null +++ b/packages/server/src/lib/WebSocketServer.ts @@ -0,0 +1,78 @@ +import { WebSocketServer } from 'ws'; + +export function expose(router: Function, port: number) { + const wss = new WebSocketServer({ + port: 3000, + }, () => { + console.log('ws chat server started on dev.valnet.xyz'); + }); + + wss.on('connection', (ws) => { + ws.on('message', async (str) => { + try { + const message = JSON.parse(str.toString()); + if(typeof message.action !== 'string') { + console.warn('invalid JSON message'); + return; + } + const {action, data} = message; + try { + console.log('[IN]', action, data); + const _return = await (router(action, data) as unknown as Promise); + console.log(_return); + if(_return) { + try { + switch(_return.type) { + case ResponseType.BROADCAST: { + console.log('[OUT_BROADCAST]', action, _return.data); + for(const client of wss.clients) { + send(client, action, _return.data); + } + break; + } + case ResponseType.REPLY: { + console.log('[OUT]', action, _return.data); + send(ws, action, _return.data); + break; + } + } + } catch(e) { + console.warn(e); + } + } + } catch(e) { + console.warn(`error in action ${action}`); + console.error(e); + } + } catch (e) { + console.warn('JSON parse failed on message'); + console.error(e); + } + }); + }); +} + +enum ResponseType { + BROADCAST, + REPLY +} + +function send(client: any, action: string, data?: any) { + client.send(JSON.stringify({action, data})); +} + +export function broadcast(data: any) { + return { + type: ResponseType.BROADCAST, + data, + }; +} + +export function reply(data: any) { + return { + type: ResponseType.REPLY, + data, + }; +} + +// export default wss; \ No newline at end of file diff --git a/packages/server/src/router.ts b/packages/server/src/lib/router.ts similarity index 96% rename from packages/server/src/router.ts rename to packages/server/src/lib/router.ts index 722816c..be804ed 100644 --- a/packages/server/src/router.ts +++ b/packages/server/src/lib/router.ts @@ -1,5 +1,6 @@ -export default function router(routes: any) { + +export default function router(routes: any) { for(const routeName in routes) { const route = routes[routeName]; if('routes' in route) { @@ -12,7 +13,6 @@ export default function router(routes: any) { } const sendFn = function(route: any, data: any) { - console.log(routes); if(route in routes) { return routes[route](data); } else { diff --git a/packages/server/src/routers/channel.ts b/packages/server/src/routers/channel.ts new file mode 100644 index 0000000..c7b2ee0 --- /dev/null +++ b/packages/server/src/routers/channel.ts @@ -0,0 +1,11 @@ +import query from '../db/query'; +import router from '../lib/router'; +import list from '../db/snippets/channel/list.sql'; +import { reply } from '../lib/WebSocketServer'; + +export default router({ + async list() { + const res = await query(list); + return reply(res ?? undefined); + }, +}); \ No newline at end of file diff --git a/packages/server/src/routers/message.ts b/packages/server/src/routers/message.ts index b7ee42f..bc68950 100644 --- a/packages/server/src/routers/message.ts +++ b/packages/server/src/routers/message.ts @@ -1,29 +1,26 @@ -import { broadcast } from '..'; import query from '../db/query'; -import router from '../router'; +import router from '../lib/router'; import newMessage from '../db/snippets/message/new.sql'; import recentMessages from '../db/snippets/message/recent.sql'; +import { broadcast, reply } from '../lib/WebSocketServer'; export default router({ async message(data: any) { const failed = null === await query(newMessage, data.text, data.from, data.uid, data.timestamp); if(failed) return; - broadcast('message:message', data); + return broadcast(data); }, async recent() { console.log('got recents request'); const messages = await query(recentMessages); if(messages === null) return; - return { - action: 'message:recent', - data: { - messages: messages.map(v => ({ - from: v.from, - uid: v.uid, - timestamp: v.t_sent * 1000, - text: v.text, - })), - }, - }; + return reply({ + messages: messages.map(v => ({ + from: v.from, + uid: v.uid, + timestamp: v.t_sent * 1000, + text: v.text, + })), + }); }, }); \ No newline at end of file diff --git a/packages/server/src/routers/root.ts b/packages/server/src/routers/root.ts deleted file mode 100644 index 67fd916..0000000 --- a/packages/server/src/routers/root.ts +++ /dev/null @@ -1,9 +0,0 @@ -import router from '../router'; -import message from './message'; - -export default router({ - up() { - console.log(Date.now()); - }, - message: message, -}); \ No newline at end of file