many updates

This commit is contained in:
Rolands 2022-10-31 18:55:15 +02:00
parent fc12f68151
commit a941eba154
9 changed files with 226 additions and 92 deletions

View file

@ -1,44 +1,69 @@
//https://stackoverflow.com/questions/38946112/es6-import-error-handling
let info = null
try { //for my logger
await import('@rolands/log')
setPrefix('Socio Client')
setShowTime(false)
} catch (e) {
info = (...objs) => console.log('[Socio Client]', ...objs)
}
//"Because he not only wants to perform well, he wants to be well receivedand the latter lies outside his control." /Epictetus/
export class WSClient {
constructor(url, {verbose=false} = {}) {
this.ws = new WebSocket(url)
if(window || undefined && url.startsWith('ws://'))
console.log('UNSECURE WEBSOCKET URL CONNECTION! Please use wss:// protocol to protect against man-in-the-middle attacks.')
// this.ws.addEventListener("close", () => {this.ws = new WebSocket(url)}); // <- rise from your grave!
// private:
#queries = {} //sql:[callback]
#is_ready = false
#verbose = false
#ws=null
this.queries = {} //sql:[callback]
this.is_ready = false
this.verbose = verbose
constructor(url, {name = '', verbose=false, keep_alive=true, reconnect_tries=3, push_callback=null} = {}) {
if (window || undefined && url.startsWith('ws://'))
info('UNSECURE WEBSOCKET URL CONNECTION! Please use wss:// and https:// protocols in production to protect against man-in-the-middle attacks.')
this.ws.addEventListener('message', this.message.bind(this));
// this.ws.addEventListener('pong', () => { console.log('pong')});
this.name = name
this.#verbose = verbose
this.push = push_callback
this.#connect(url, keep_alive, verbose, reconnect_tries)
this.#ws.addEventListener('message', this.message.bind(this));
}
#connect(url, keep_alive, verbose, reconnect_tries){
this.#ws = new WebSocket(url)
if (keep_alive && reconnect_tries)
this.#ws.addEventListener("close", () => {
if (this.#verbose) info(this.name, `WebSocket closed. Retrying...`);
this.#connect(url, keep_alive, verbose, reconnect_tries - 1)
}); // <- rise from your grave!
}
message(e) {
const [kind, data] = JSON.parse(e.data)
if (this.verbose) console.log(kind, data)
if (this.#verbose) info(kind, data)
switch(kind){
case 'CON': this.ses_id = data; this.is_ready = true; break;
case 'CON': this.ses_id = data; this.#is_ready = true; if (this.#verbose) info(this.name, `WebSocket connected.`); break;
case 'UPD':
if (data.sql in this.queries)
this.queries[data.sql].forEach(f => f(data.result));
else console.log(`UPD message for unregistered SQL query! [${data.sql}] with data:`, data)
if (data.sql in this.#queries)
this.#queries[data.sql].forEach(f => f(data.result));
else if (this.#verbose) info(`UPD message for unregistered SQL query! [${data.sql}] with data:`, data)
break;
case 'SQL':
if (data.sql in this.queries)
this.queries[data.sql](data.result);
if (data.sql in this.#queries)
this.#queries[data.sql](data.result);
break;
case 'PONG': if (this.#verbose) info('pong', data?.num); break;
case 'PUSH': this.push(data); break;
// case '': break;
default: console.log(`Unrecognized message kind! [${kind}] with data:`, data);
default: info(`Unrecognized message kind! [${kind}] with data:`, data);
}
}
ready(){
//idk a better solution. Checks every n ms if the ready flag is set
return new Promise((res) => {
const timer = setInterval(() => {
if(this.is_ready){
if(this.#is_ready){
clearInterval(timer)
res()
}
@ -46,23 +71,32 @@ export class WSClient {
})
}
//private method
#send(data=[]){
this.#ws.send(JSON.stringify([this.ses_id, ...data]))
}
subscribe({ sql = '', params = null } = {}, callback = null, t=null){
if (sql in this.queries)
this.queries[sql].push(t ? callback.bind(t) : callback)
if (sql in this.#queries)
this.#queries[sql].push(t ? callback.bind(t) : callback)
else{
this.queries[sql] = [t ? callback.bind(t) : callback]
this.ws.send(JSON.stringify([this.ses_id, 'REG', { sql: sql, params: params }]))
this.#queries[sql] = [t ? callback.bind(t) : callback]
this.#send(['REG', { sql: sql, params: params }])
}
// console.log('Registered', sql)
// info('Registered', sql)
}
async query(sql='', params=null){
//set up a promise which resolve function is in the queries data structure, such that in the message handler it can be called, therefor the promise resolved, therefor awaited and return from this function
const prom = new Promise((res) => {
this.queries[sql] = res
this.#queries[sql] = res
})
//send off the request, which will be resolved in the message handler
this.ws.send(JSON.stringify([this.ses_id, 'SQL', { sql: sql, params:params }]))
this.#send(['SQL', { sql: sql, params: params }])
return await prom
}
ping(num=0){
this.#send(['PING', { num: num }])
}
}

View file

@ -1,57 +1,65 @@
//Nullum magnum ingenium sine mixture dementia fuit. - There has been no great wisdom without an element of madness.
import { log, error, info, setPrefix} from '@rolands/log'
import { UUID, Secure } from './secure.js';
import { log, error, soft_error, info, setPrefix, setShowTime} from '@rolands/log'
import { UUID } from './secure.js';
import { WebSocketServer } from 'ws'; //https://github.com/websockets/ws https://github.com/websockets/ws/blob/master/doc/ws.md
//https://stackoverflow.com/questions/16280747/sending-message-to-a-specific-connected-users-using-websocket
export class SessionManager{
constructor(opts = {}, DB_query_callback = null, { verbose = false } = {}){
setPrefix('Socio') //for my logger
// private:
#wss=null
#sessions = {}//ses_id:websocket
#verbose=false
#secure=null
#lifecycleHooks = { CON: [], DISCON: [], message: [], update: [] } //, '': []
const wss = new WebSocketServer(opts); //take a look at the WebSocketServer docs - the opts can have a server param, that can be your http server
this.sessions = {} //ses_id:websocket
constructor(opts = {}, DB_query_callback = null, { secure =null, verbose = false } = {}){
setPrefix('Socio'); setShowTime(false); //for my logger
this.#wss = new WebSocketServer(opts); //take a look at the WebSocketServer docs - the opts can have a server param, that can be your http server
this.Query = DB_query_callback
this.verbose = verbose
this.#verbose = verbose
this.#secure = secure
wss.on('connection', this.Connect.bind(this)); //https://thenewstack.io/mastering-javascript-callbacks-bind-apply-call/ have to bind 'this' to the function, otherwise it will use the .on()'s 'this', so that this.[prop] are not undefined
wss.on('close', (...stuff) => { info('WebSocketServer close event', ...stuff) });
wss.on('error', (...stuff) => { error('WebSocketServer error event', ...stuff)});
this.#wss.on('connection', this.Connect.bind(this)); //https://thenewstack.io/mastering-javascript-callbacks-bind-apply-call/ have to bind 'this' to the function, otherwise it will use the .on()'s 'this', so that this.[prop] are not undefined
this.#wss.on('close', (...stuff) => { info('WebSocketServer close event', ...stuff) });
this.#wss.on('error', (...stuff) => { error('WebSocketServer error event', ...stuff)});
}
async Connect(conn, req){
const ses_id = UUID()
this.sessions[ses_id] = new Session(ses_id, conn)
this.#sessions[ses_id] = new Session(ses_id, conn)
conn.send(JSON.stringify(['CON', ses_id]));
log('CON', ses_id)
if (this.#verbose) info('CON', ses_id)
conn.on('message', this.Message.bind(this));
conn.on('close', () => {
log('DISCON', ses_id)
delete this.sessions[ses_id]
if (this.#verbose) info('DISCON', ses_id)
delete this.#sessions[ses_id]
});
}
async Message(req, head){
const [ses_id, kind, data] = JSON.parse(req.toString())
if (this.verbose) log(`received [${kind}] from [${ses_id}]: `, data);
if (this.#verbose) info(`received [${kind}] from [${ses_id}]`);
if (this.#secure && data?.sql) data.sql = this.#secure.DecryptString(data.sql) //if this is supposed to be secure and sql was received, then decrypt it before continuing
switch (kind) {
case 'REG':
if(ses_id in this.sessions)
this.sessions[ses_id].Send(['UPD', { sql: data.sql, result: await this.Query(data.sql, data.params) }])
if(ses_id in this.#sessions)
this.#sessions[ses_id].Send(['UPD', { sql: data.sql, result: await this.Query(data.sql, data.params) }])
//set up hook
if (QueryUtils.QueryIsSelect(data.sql))
QueryUtils.ParseSQLForTables(data.sql).forEach(t => this.sessions[ses_id].RegisterHook(t, data.sql, data.params));
QueryUtils.ParseSQLForTables(data.sql).forEach(t => this.#sessions[ses_id].RegisterHook(t, data.sql, data.params));
break;
case 'SQL':
const is_select = QueryUtils.QueryIsSelect(data.sql)
if (ses_id in this.sessions){
if (ses_id in this.#sessions){
const res = this.Query(data.sql, data.params)
if (is_select) //wait for result
this.sessions[ses_id].Send(['SQL', { sql: data.sql, result: await res }])
this.#sessions[ses_id].Send(['SQL', { sql: data.sql, result: await res }])
}
//if the sql wasnt a SELECT, but altered some resource, then need to propogate that to other connection hooks
@ -59,14 +67,17 @@ export class SessionManager{
this.Update(QueryUtils.ParseSQLForTables(data.sql))
break;
case 'PING': this.#sessions[ses_id].Send(['PONG', { num: data?.num}]); break;
// case '': break;
default: log(`Unrecognized message kind! [${kind}] with data:`, data);
default: if (this.#verbose) error(`Unrecognized message kind! [${kind}] with data:`, data);
}
}
//OPTIMIZATION dont await the query, but queue up all of them on another thread then await and send there
async Update(tables=[]){
Object.values(this.sessions).forEach(async (s) => {
// if (this.#lifecycleHooks.update) this.#lifecycleHooks.update.forEach(f => f(tables)) //call all the lifecycle hooks
Object.values(this.#sessions).forEach(async (s) => {
tables.forEach(async (t) => {
if(t in s.hooks)
for await (const data of s.hooks[t]){
@ -75,6 +86,24 @@ export class SessionManager{
})
})
}
//when the server wants to send some data to a specific session client - can be any raw data
SendTo(ses_id='', data={}){
if (ses_id in this.#sessions)
this.#sessions[ses_id].Send(['PUSH', data])
else soft_error(`The provided session ID [${ses_id}] was not found in the tracked web socket connections!`)
}
Emit(data=[]){
this.#wss.emit(JSON.stringify(['EMIT', ...data]));
}
RegisterLifecycleHook(name='', callback){
if(name in this.#lifecycleHooks)
this.#lifecycleHooks.push(callback)
else
error(`Lifecycle hook [${name}] does not exist!`)
}
}
@ -91,10 +120,10 @@ class Session{
this.hooks[table].push({ sql: sql, params: params })
else
this.hooks[table] = [{ sql:sql, params:params}]
log('reg hook', table, this.hooks[table])
// log('reg hook', table, this.hooks[table])
}
Send(data){
Send(data=[]){
this.ws.send(JSON.stringify(data))
}
}
@ -107,7 +136,7 @@ class QueryUtils{
static ParseSQLForTables(sql = '') {
return sql
.match(/(?:FROM|INTO)[\s\n\t](?<tables>[\w,\s\n\t]+)[\s\n\t]?(?:WHERE|VALUES|;|LIMIT|GROUP|ORDER)/mi)
.match(/(?:FROM|INTO)[\s\n\t](?<tables>[\w,\s\n\t]+?)[\s\n\t]?(?:WHERE|VALUES|;|LIMIT|GROUP|ORDER)/mi)
?.groups?.tables
.split(/,[\s\n\t\r]*/mig)
.map((t) => t.split(/[\s\n\t\r]/mi)[0].trim()) || []

18
core/package-lock.json generated
View file

@ -1,22 +1,22 @@
{
"name": "wsdb",
"name": "socio",
"version": "0.0.1",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "wsdb",
"name": "socio",
"version": "0.0.1",
"license": "ISC",
"dependencies": {
"@rolands/log": "^1.0.1",
"@rolands/log": "^1.1.1",
"ws": "^8.9.0"
}
},
"node_modules/@rolands/log": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@rolands/log/-/log-1.0.1.tgz",
"integrity": "sha512-VlQJG4UG+pQpJjGERcGlqBJm+s8z+TfbEKq9cbVgWxfIvFWD/TiQ+0sPQ9dOhH6O8/Ew7ktPZlfbIcU4oGe2ow=="
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@rolands/log/-/log-1.1.1.tgz",
"integrity": "sha512-j8jZxm0tF+7ke6V+qtdoCR2KlOba3Mog39QyxU+3pbmgJ/wuIfF7QuIqTSLqrtPQY5FzQjCwlJcvIizp33UYxg=="
},
"node_modules/ws": {
"version": "8.9.0",
@ -41,9 +41,9 @@
},
"dependencies": {
"@rolands/log": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@rolands/log/-/log-1.0.1.tgz",
"integrity": "sha512-VlQJG4UG+pQpJjGERcGlqBJm+s8z+TfbEKq9cbVgWxfIvFWD/TiQ+0sPQ9dOhH6O8/Ew7ktPZlfbIcU4oGe2ow=="
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@rolands/log/-/log-1.1.1.tgz",
"integrity": "sha512-j8jZxm0tF+7ke6V+qtdoCR2KlOba3Mog39QyxU+3pbmgJ/wuIfF7QuIqTSLqrtPQY5FzQjCwlJcvIizp33UYxg=="
},
"ws": {
"version": "8.9.0",

View file

@ -28,7 +28,7 @@
},
"homepage": "https://github.com/Rolands-Laucis/Socio.js/blob/master/README.md",
"dependencies": {
"@rolands/log": "^1.0.1",
"@rolands/log": "^1.1.1",
"ws": "^8.9.0"
}
}

View file

@ -1,15 +1,24 @@
import { randomUUID, createCipheriv, createDecipheriv, randomBytes } from 'crypto'
import { randomUUID, createCipheriv, createDecipheriv } from 'crypto'
//The aim of the wise is not to secure pleasure, but to avoid pain. /Aristotle/
export class SocioSecurity{
//private:
#key=''
#algo=''
#iv=''
export class Secure{
constructor({ secure_private_key = '', cipther_algorithm = 'AES-256-ctr', cipher_iv =''} = {}){
if (!cipher_iv) cipher_iv = UUID()
if (!secure_private_key || !cipther_algorithm || !cipher_iv) throw `Missing constructor arguments!`
if (secure_private_key.length < 32) throw `secure_private_key has to be at least 32 characters! Got ${secure_private_key.length}`
if (cipher_iv.length < 16) throw `cipher_iv has to be at least 16 characters! Got ${cipher_iv.length}`
if (!crypto.getCiphers().includes(cipther_algorithm)) throw `Unsupported algorithm [${cipther_algorithm}] by the Node.js Crypto module!`
const te = new TextEncoder()
this.key = te.encode(secure_private_key).slice(0,32)
this.algo = cipther_algorithm
this.iv = te.encode(cipher_iv).slice(0, 16)
this.#key = te.encode(secure_private_key).slice(0,32) //has to be this length
this.#algo = cipther_algorithm
this.#iv = te.encode(cipher_iv).slice(0, 16) //has to be this length
}
//sql strings must be in single quotes and have an sql single line comment at the end with the name socio - "--socio"
@ -22,13 +31,12 @@ export class Secure{
}
EncryptString(query = '') {
const cipher = createCipheriv(this.algo, Buffer.from(this.key), this.iv)
return (cipher.update(query, 'utf-8', 'base64') + cipher.final('base64')).replace(/\\/g, '\\\\') //escape backslashes to avoid escaping in the js string when this is put back into the souce code
const cipher = createCipheriv(this.#algo, Buffer.from(this.#key), this.#iv)
return (cipher.update(query, 'utf-8', 'base64') + cipher.final('base64')) //Base64 only contains AZ , az , 09 , + , / and =
}
DecryptString(query = '') {
const decipther = createDecipheriv(this.algo, Buffer.from(this.key), this.iv)
query = query.replace(/\\\\/g, '\\') //remove the escaped backslashes to just backslashes
const decipther = createDecipheriv(this.#algo, Buffer.from(this.#key), this.#iv)
return decipther.update(query, 'base64', 'utf-8') + decipther.final('utf-8')
}
}

View file

@ -1,12 +1,12 @@
<html>
<head>
<title>Totum demo page</title>
<title>Socio demonstration - basic</title>
<!-- font -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link
href="https://fonts.googleapis.com/css2?family=Open+Sans:wght@400;700&family=Roboto+Mono:ital,wght@0,300;1,300&display=swap"
href="https://fonts.googleapis.com/css2?family=Josefin+Sans:wght@200;400;700&family=Trispace:wght@100;200&display=swap"
rel="stylesheet">
<script src="./client.js" type="module"></script>
@ -26,7 +26,7 @@
background-color: #16161b;
color: white;
font-family: 'Open Sans', sans-serif;
font-family: 'Josefin Sans', 'Open Sans', sans-serif;
}
main{
height: 100%;
@ -49,20 +49,23 @@
filter: var(--shad);
}
h1{
font-size: 37.5px;
font-size: 48.83px;
font-weight: 700;
}
h3{
font-size: 15.36px;
font-weight: 300;
font-style: italic;
color: #4d4d52;
}
h2{
font-size: 24px;
font-size: 31.25px;
font-weight: 700;
line-height: 1.3;
}
h3{
font-size: 20px;
font-weight: 300;
font-style: italic;
color: #5a5a5f;
}
a{
font-size: 25px;
}
h1, h2{
display: flex;
@ -74,8 +77,8 @@
.status{align-items: baseline;}
.code{
font-family: 'Roboto Mono', monospace;
font-weight: 300;
font-family: 'Trispace', monospace;
font-weight: 100;
font-size: 19.20px;
padding: 8px;
border-radius: 4px;
@ -84,7 +87,7 @@
}
.num{
font-weight: 700;
font-size: 37.5px;
font-size: 48.83px;
}
button{
font-weight: 700;
@ -111,15 +114,15 @@
background-clip: text;
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
background-position: 50% 0px;
background-size: 150%;
background-position: 30% 0px;
background-size: 130%;
transition: var(--trans);
}
.grad_clip:hover{
background-position: 0px 0px;
}
.status.ready{color: #5fe757;}
/* .status.ready{color: #5fe757;} */
</style>
<body>

View file

@ -1,16 +1,18 @@
{
"name": "demo",
"name": "basic",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "demo",
"name": "basic",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"@rolands/log": "^1.1.0",
"express": "^4.18.2",
"sequelize": "^6.25.3",
"socio": "^0.0.1",
"sqlite3": "^5.1.2"
}
},
@ -62,6 +64,11 @@
"node": ">=10"
}
},
"node_modules/@rolands/log": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@rolands/log/-/log-1.1.1.tgz",
"integrity": "sha512-j8jZxm0tF+7ke6V+qtdoCR2KlOba3Mog39QyxU+3pbmgJ/wuIfF7QuIqTSLqrtPQY5FzQjCwlJcvIizp33UYxg=="
},
"node_modules/@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@ -1635,6 +1642,15 @@
"npm": ">= 3.0.0"
}
},
"node_modules/socio": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/socio/-/socio-0.0.1.tgz",
"integrity": "sha512-YjOk596DV092CL1mIsS3moKUQ0W7Ge4RM5L2NT/PbimcuuWYQy3ZcjIlaAIMIcxlwA7Dm9nwyXD26wadKvNrWA==",
"dependencies": {
"@rolands/log": "^1.0.1",
"ws": "^8.9.0"
}
},
"node_modules/socks": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
@ -1919,6 +1935,26 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/ws": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.10.0.tgz",
"integrity": "sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
@ -1968,6 +2004,11 @@
"rimraf": "^3.0.2"
}
},
"@rolands/log": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@rolands/log/-/log-1.1.1.tgz",
"integrity": "sha512-j8jZxm0tF+7ke6V+qtdoCR2KlOba3Mog39QyxU+3pbmgJ/wuIfF7QuIqTSLqrtPQY5FzQjCwlJcvIizp33UYxg=="
},
"@tootallnate/once": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
@ -3148,6 +3189,15 @@
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"optional": true
},
"socio": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/socio/-/socio-0.0.1.tgz",
"integrity": "sha512-YjOk596DV092CL1mIsS3moKUQ0W7Ge4RM5L2NT/PbimcuuWYQy3ZcjIlaAIMIcxlwA7Dm9nwyXD26wadKvNrWA==",
"requires": {
"@rolands/log": "^1.0.1",
"ws": "^8.9.0"
}
},
"socks": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz",
@ -3366,6 +3416,12 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"ws": {
"version": "8.10.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.10.0.tgz",
"integrity": "sha512-+s49uSmZpvtAsd2h37vIPy1RBusaLawVe8of+GyEPsaJTCMpj/2v8NpeK1SHXjBlQ95lQTmQofOJnFiLoaN3yw==",
"requires": {}
},
"yallist": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",

View file

@ -11,8 +11,10 @@
"author": "",
"license": "ISC",
"dependencies": {
"@rolands/log": "^1.1.1",
"express": "^4.18.2",
"sequelize": "^6.25.3",
"socio": "^0.0.1",
"sqlite3": "^5.1.2"
}
}

View file

@ -1,6 +1,8 @@
import express from 'express'
import {SessionManager} from '../../core/core.js'
// import {SessionManager} from 'socio'
import { Sequelize } from 'sequelize';
import { log, info, setPrefix, setShowTime } from '@rolands/log'; setPrefix('EXPRESS'); setShowTime(false);
//constants
const server_port = 5000, ws_port = 3000 //can be set up that the websockets run on the same port as the http server
@ -16,7 +18,7 @@ await sequelize.query('INSERT INTO Users VALUES("John", 69);')
//Either you in a wrapper function or your DB interface lib should do the sql validation and sanitization, as this lib does not!
const QueryWrap = async (sql='', params={}) => (await sequelize.query(sql, { logging: false, raw: true, replacements: params }))[0]
const manager = new SessionManager({ port: ws_port }, QueryWrap, {verbose:true} )
console.log('Created SessionManager on port', ws_port)
info(`Created SessionManager on port`, ws_port)
//init
// const sec = Secure({})
@ -30,5 +32,5 @@ app.use("", express.static(__dirname));
app.use("/", express.static(__dirname + "\\..\\..\\core"));
app.listen(server_port, () => {
console.log(`Express webserver listening on port ${server_port}`, `http://localhost:${server_port}/`)
info(`Express webserver listening on port`, server_port, `http://localhost:${server_port}/`)
})