Stage 2 : Finish Alpha, Begin Beta #2
			
				
			
		
		
		
	| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
function Client()
 | 
			
		||||
{
 | 
			
		||||
    /**
 | 
			
		||||
     * @type {string}
 | 
			
		||||
     */
 | 
			
		||||
    this.id = null;
 | 
			
		||||
    /**
 | 
			
		||||
     * @type {import("websocket").connection}
 | 
			
		||||
     */
 | 
			
		||||
    this.socket = null;
 | 
			
		||||
    /**
 | 
			
		||||
     * @type {Date}
 | 
			
		||||
     */
 | 
			
		||||
    this.created_at = null;
 | 
			
		||||
 | 
			
		||||
    this.store = new Map();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
Client.prototype.send = function(obj){
 | 
			
		||||
    this.socket.sendUTF(JSON.stringify(obj));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
exports.Client = Client;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
"use strict";
 | 
			
		||||
 | 
			
		||||
let http = require("http");
 | 
			
		||||
let server = http.createServer();
 | 
			
		||||
server.listen(8282,'0.0.0.0',() => {
 | 
			
		||||
    console.log("HTTP Service Running...");
 | 
			
		||||
});
 | 
			
		||||
exports.http = server;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,47 @@
 | 
			
		|||
let {addService} = require("../WebSocket.js");
 | 
			
		||||
 | 
			
		||||
addService(({
 | 
			
		||||
    global,
 | 
			
		||||
    client,
 | 
			
		||||
    message,
 | 
			
		||||
    end,
 | 
			
		||||
    next,
 | 
			
		||||
    response
 | 
			
		||||
})=>{
 | 
			
		||||
    let {type,username,password} = message;
 | 
			
		||||
    if(type === 'auth/check')
 | 
			
		||||
    {
 | 
			
		||||
        let auth = client.store.has('user');
 | 
			
		||||
        return end({
 | 
			
		||||
            value: auth
 | 
			
		||||
        })
 | 
			
		||||
    };
 | 
			
		||||
    if(type === 'auth/login')
 | 
			
		||||
    {
 | 
			
		||||
        if(username == 'admin' && password == '123456Kc')
 | 
			
		||||
        {
 | 
			
		||||
            return end({
 | 
			
		||||
                status: 'success'
 | 
			
		||||
            })
 | 
			
		||||
        }else{
 | 
			
		||||
            return end({
 | 
			
		||||
                status: 'fail'
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
    if(type === 'auth/logout')
 | 
			
		||||
    {
 | 
			
		||||
        let auth = client.store.has('user');
 | 
			
		||||
        if(auth)
 | 
			
		||||
        {
 | 
			
		||||
            client.store.delete('user');
 | 
			
		||||
            return end({
 | 
			
		||||
                status: 'success'
 | 
			
		||||
            })
 | 
			
		||||
        }else{
 | 
			
		||||
            return end({
 | 
			
		||||
                status: 'fail'
 | 
			
		||||
            })
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,8 @@
 | 
			
		|||
let {addListener} = require("../WebSocket.js");
 | 
			
		||||
 | 
			
		||||
addListener('connect',(global, client)=>{
 | 
			
		||||
    client.send([{
 | 
			
		||||
        type: 'id',
 | 
			
		||||
        value: client.id
 | 
			
		||||
    },'id'])
 | 
			
		||||
});
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,117 @@
 | 
			
		|||
"use strict";
 | 
			
		||||
 | 
			
		||||
let websocket = require("websocket");
 | 
			
		||||
let {http} = require("./HTTPServer");
 | 
			
		||||
let {randomUUID} = require("crypto");
 | 
			
		||||
const { Client } = require("./Client.js");
 | 
			
		||||
 | 
			
		||||
let wsServer = new websocket.server({
 | 
			
		||||
    httpServer: http,
 | 
			
		||||
    autoAcceptConnections: true
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
let global = new Map();
 | 
			
		||||
let clients = new Map();
 | 
			
		||||
wsServer.addListener("connect",(socket) => {
 | 
			
		||||
 | 
			
		||||
    let local = new Client();
 | 
			
		||||
    let id = randomUUID();
 | 
			
		||||
    socket.id = id;
 | 
			
		||||
    local.id = id;
 | 
			
		||||
    local.socket = socket;
 | 
			
		||||
    local.created_at = new Date();
 | 
			
		||||
    clients.set(id, local);
 | 
			
		||||
 | 
			
		||||
    emit("connect", global, local);
 | 
			
		||||
    socket.addListener("close",()=>{
 | 
			
		||||
        emit("disconnect",  global, local);
 | 
			
		||||
        clients.delete(id);
 | 
			
		||||
    });
 | 
			
		||||
    socket.addListener("message",({type,utf8Data}) => {
 | 
			
		||||
        if(type == "utf8")
 | 
			
		||||
        {
 | 
			
		||||
            let json;
 | 
			
		||||
            try{
 | 
			
		||||
                json = JSON.parse(utf8Data);
 | 
			
		||||
                emit('services', global, local, json);
 | 
			
		||||
                let [payload, id, action] = json;
 | 
			
		||||
                if(typeof id === "string")
 | 
			
		||||
                {
 | 
			
		||||
                    action = id;
 | 
			
		||||
                }
 | 
			
		||||
                emitService(global, local, id, payload, action);
 | 
			
		||||
            }catch{
 | 
			
		||||
                emit("messageError", global, local, utf8Data);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @type {Map<string, Function[]>}
 | 
			
		||||
 */
 | 
			
		||||
 let events = new Map();
 | 
			
		||||
 /**
 | 
			
		||||
  * @type {Map<string, Function[]>}
 | 
			
		||||
  */
 | 
			
		||||
 let services = []
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @param {string} event 
 | 
			
		||||
 * @param {(global:Map<string, any>, client:Client, data:any) => any} func 
 | 
			
		||||
 */
 | 
			
		||||
exports.addListener = (event, func) => {
 | 
			
		||||
    if(!events.has(event))
 | 
			
		||||
    {
 | 
			
		||||
        events.set(event,[]);
 | 
			
		||||
    };
 | 
			
		||||
    events.get(event).push(func);
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @param {string} event 
 | 
			
		||||
 * @param {(data:{global:Map<string, any>, client:Client, message:any,response:Function,end:Function,next:Function}) => any} func 
 | 
			
		||||
 */
 | 
			
		||||
exports.addService = (func) => {
 | 
			
		||||
    services.push(func);
 | 
			
		||||
};
 | 
			
		||||
function emit(event,...args)
 | 
			
		||||
{
 | 
			
		||||
    if(events.has(event))
 | 
			
		||||
    {
 | 
			
		||||
        for (const callback of events.get(event)) {
 | 
			
		||||
            callback(...args);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
};
 | 
			
		||||
/**
 | 
			
		||||
 * 
 | 
			
		||||
 * @param {Map} global 
 | 
			
		||||
 * @param {Client} local 
 | 
			
		||||
 * @param {number} id 
 | 
			
		||||
 * @param {{[key:string]:any}} payload 
 | 
			
		||||
 * @param {"R"|"S"} action 
 | 
			
		||||
 */
 | 
			
		||||
async function emitService(global, client, id, payload, action)
 | 
			
		||||
{
 | 
			
		||||
    let willContinue = false;
 | 
			
		||||
    for (const callback of services) {
 | 
			
		||||
        await callback({
 | 
			
		||||
            message: payload,
 | 
			
		||||
            action,
 | 
			
		||||
            client,
 | 
			
		||||
            global,
 | 
			
		||||
            response:(obj)=>{
 | 
			
		||||
                client.send([obj, id, 'C']) // continue
 | 
			
		||||
            },
 | 
			
		||||
            end:(obj)=>{
 | 
			
		||||
                client.send([obj, id, 'E']) // stopped data stream (this channel)
 | 
			
		||||
            },
 | 
			
		||||
            next:function(){
 | 
			
		||||
                willContinue = true;
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        if(willContinue === false) break;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
exports.websocket = wsServer;
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,5 @@
 | 
			
		|||
require("./HTTPServer.js");
 | 
			
		||||
require("./WebSocket.js");
 | 
			
		||||
 | 
			
		||||
require("./Services/YourID.js");
 | 
			
		||||
require("./Services/Auth.js");
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| 
						 | 
				
			
			@ -0,0 +1,26 @@
 | 
			
		|||
{
 | 
			
		||||
  "name": "mwse",
 | 
			
		||||
  "version": "0.1.0",
 | 
			
		||||
  "description": "Mikro WebSocket Engine",
 | 
			
		||||
  "main": "Source/index.js",
 | 
			
		||||
  "scripts": {
 | 
			
		||||
    "test": "echo \"Error: no test specified\" && exit 1"
 | 
			
		||||
  },
 | 
			
		||||
  "repository": {
 | 
			
		||||
    "type": "git",
 | 
			
		||||
    "url": "http://git.saqut.com/saqut/MWSE"
 | 
			
		||||
  },
 | 
			
		||||
  "keywords": [
 | 
			
		||||
    "WebSocket",
 | 
			
		||||
    "server",
 | 
			
		||||
    "microservice",
 | 
			
		||||
    "ws"
 | 
			
		||||
  ],
 | 
			
		||||
  "author": "Abdussamed ULUTAŞ <abdussamedulutas@yandex.com.tr>",
 | 
			
		||||
  "license": "MIT",
 | 
			
		||||
  "dependencies": {
 | 
			
		||||
    "knex": "^2.3.0",
 | 
			
		||||
    "sqlite3": "^5.1.2",
 | 
			
		||||
    "websocket": "^1.0.34"
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,23 @@
 | 
			
		|||
<!DOCTYPE html>
 | 
			
		||||
<html lang="en">
 | 
			
		||||
<head>
 | 
			
		||||
    <meta charset="UTF-8">
 | 
			
		||||
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
 | 
			
		||||
    <title>Document</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body>
 | 
			
		||||
    <script src="./wsjs.js"></script>
 | 
			
		||||
    <script>
 | 
			
		||||
        let ws = new WSJS();
 | 
			
		||||
        ws.connect('ws://localhost:8282');
 | 
			
		||||
        ws.scope(()=>{
 | 
			
		||||
            console.log("Connected ws")
 | 
			
		||||
            ws.authWith("admin","123456Kc");
 | 
			
		||||
        });
 | 
			
		||||
        ws.signal('id',(data)=>{
 | 
			
		||||
            console.log("Your id is ", data.value)
 | 
			
		||||
        });
 | 
			
		||||
    </script>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,133 @@
 | 
			
		|||
function WSJS()
 | 
			
		||||
{
 | 
			
		||||
    this.isActive = false;
 | 
			
		||||
    this.ws = null;
 | 
			
		||||
    this.endpoint = null;
 | 
			
		||||
};
 | 
			
		||||
WSJS.prototype.connect = function(url){
 | 
			
		||||
    this.ws = new WebSocket(url);
 | 
			
		||||
    this.addListeners();
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.addListeners = function(url){
 | 
			
		||||
    this.ws.addEventListener("close", this.closedEvent.bind(this));
 | 
			
		||||
    this.ws.addEventListener("message", this.messageEvent.bind(this));
 | 
			
		||||
    this.ws.addEventListener("open", this.openMessage.bind(this));
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.closedEvent = function(){
 | 
			
		||||
    this.isActive = false;
 | 
			
		||||
    this.ws = null;
 | 
			
		||||
    this.events.dispatchEvent(new Event("close"));
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.openMessage = function(){
 | 
			
		||||
    this.isActive = true;
 | 
			
		||||
    this.events.dispatchEvent(new Event("open"));
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.messageEvent = function({data}){
 | 
			
		||||
    let [payload, id, action] = JSON.parse(data);
 | 
			
		||||
    if(typeof id === 'number')
 | 
			
		||||
    {
 | 
			
		||||
        if(this.requests.has(id))
 | 
			
		||||
        {
 | 
			
		||||
            this.requests.get(id)(payload, action);
 | 
			
		||||
            switch(action)
 | 
			
		||||
            {
 | 
			
		||||
                case 'E':{
 | 
			
		||||
                    this.requests.delete(id);
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
                case 'S':
 | 
			
		||||
                default:{
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }else console.warn("Missing event sended from server");
 | 
			
		||||
    }else{
 | 
			
		||||
        if(this.signals.has(id))
 | 
			
		||||
        {
 | 
			
		||||
            for (const callback of this.signals.get(id)) {
 | 
			
		||||
                callback(payload);
 | 
			
		||||
            }
 | 
			
		||||
        }else console.warn("Missing event sended from server");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.events = new EventTarget();
 | 
			
		||||
WSJS.prototype.scope = function(func){
 | 
			
		||||
    if(this.isActive)
 | 
			
		||||
    {
 | 
			
		||||
        func();
 | 
			
		||||
    }else this.events.addEventListener("open", func);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
WSJS.prototype.sendOnly = function(obj){
 | 
			
		||||
    if(this.isActive)
 | 
			
		||||
    {
 | 
			
		||||
        this.sendRaw([obj,'R']);
 | 
			
		||||
    }else throw new Error(`socket could be a active`);
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.requests = new Map();
 | 
			
		||||
WSJS.prototype.requestCount = 0;
 | 
			
		||||
WSJS.prototype.request = async function(obj){
 | 
			
		||||
    if(this.isActive)
 | 
			
		||||
    {
 | 
			
		||||
        return await new Promise(ok => {
 | 
			
		||||
            let id = ++this.requestCount;
 | 
			
		||||
            this.sendRaw([obj,id,'R']);
 | 
			
		||||
            this.requests.set(id,data => {
 | 
			
		||||
                ok(data);
 | 
			
		||||
            });
 | 
			
		||||
        })
 | 
			
		||||
    }else throw new Error(`socket could be a active`);
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.stream = async function(obj,callback){
 | 
			
		||||
    if(this.isActive)
 | 
			
		||||
    {
 | 
			
		||||
        let id = ++this.requestCount;
 | 
			
		||||
        this.sendRaw([obj, id, 'S']);
 | 
			
		||||
        this.requests.set(id,data => {
 | 
			
		||||
            callback(data);
 | 
			
		||||
        });
 | 
			
		||||
    }else throw new Error(`socket could be a active`);
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.signals = new Map();
 | 
			
		||||
WSJS.prototype.signal = async function(name, callback){
 | 
			
		||||
    if(!this.signals.has(name))
 | 
			
		||||
    {
 | 
			
		||||
        this.signals.set(name, [callback]);
 | 
			
		||||
    }else{
 | 
			
		||||
        this.signals.get(name).push(callback);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.slot = async function(name, obj){
 | 
			
		||||
    if(this.isActive)
 | 
			
		||||
    {
 | 
			
		||||
        if(typeof name == "string")
 | 
			
		||||
        {
 | 
			
		||||
            this.sendOnly([obj,name]);
 | 
			
		||||
        }else{
 | 
			
		||||
            throw new Error(`name could be a string, gived ${typeof name}`);
 | 
			
		||||
        }
 | 
			
		||||
    }else throw new Error(`socket could be a active`);
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.sendRaw = function(obj){
 | 
			
		||||
    if(this.isActive)
 | 
			
		||||
    {
 | 
			
		||||
        this.ws.send(JSON.stringify(obj))
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
WSJS.prototype.checkAuth = async function(username, password){
 | 
			
		||||
    let {value:isAuth} = await this.request({
 | 
			
		||||
        type: 'auth/check'
 | 
			
		||||
    });
 | 
			
		||||
    return isAuth;
 | 
			
		||||
};
 | 
			
		||||
WSJS.prototype.authWith = async function(username, password){
 | 
			
		||||
    if(!await this.checkAuth())
 | 
			
		||||
    {
 | 
			
		||||
        let requets = await this.request({
 | 
			
		||||
            type: 'auth/login',
 | 
			
		||||
            username,
 | 
			
		||||
            password
 | 
			
		||||
        });
 | 
			
		||||
        debugger;
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
		Loading…
	
		Reference in New Issue