[refactor]: move rtmt to core package

This commit is contained in:
Halit Aksoy 2024-06-17 17:25:40 +03:00
parent 597bb708f1
commit f371414f98
21 changed files with 74 additions and 137 deletions

View File

@ -1,14 +0,0 @@
import { Bytes } from "./rtmt"
var util= require('util');
const textEncoder = new util.TextEncoder()
const textDecoder = new util.TextDecoder("utf-8")
export function encodeText(text : string) {
const bytes = textEncoder.encode(text)
return bytes
}
export function decodeText(bytes : Bytes) {
return textDecoder.decode(bytes)
}

View File

@ -1,16 +1,8 @@
import { decodeText, encodeText } from "./byte_util";
import { Bytes } from "./rtmt";
const headerLenght = 4
export type Message = { export type Message = {
channel: string, channel: string,
message: Object, message: Object,
} }
//
// channel is string, message is byte array
//
export function encode(message: Message) { export function encode(message: Message) {
return JSON.stringify({ return JSON.stringify({
channel : message.channel, channel : message.channel,
@ -18,9 +10,6 @@ export function encode(message: Message) {
}); });
} }
//
// return { channel : string, message : byte array}
//
export function decode(bytes: string): Message { export function decode(bytes: string): Message {
return JSON.parse(bytes); return JSON.parse(bytes);
} }

View File

@ -1,4 +1,3 @@
export type Bytes = Buffer
export type OnMessage = (clientID: string, message: Object) => any export type OnMessage = (clientID: string, message: Object) => any
export type OnClientConnectionChange = (clientID: string, isOnline : boolean) => any export type OnClientConnectionChange = (clientID: string, isOnline : boolean) => any

View File

@ -1,10 +1,10 @@
import { decode, encode } from "./encode_decode_message" import { OnClientConnectionChange, OnMessage, RTMT } from "./rtmt"
import { Bytes, OnClientConnectionChange, OnMessage, RTMT } from "./rtmt"
import WebSocket from "ws" import WebSocket from "ws"
import * as http from 'http'; import * as http from 'http';
import { channel_ping, channel_pong } from "@mancala/core"; import { channel_ping, channel_pong } from "@mancala/core";
import { RTMT_WS_PING_INTERVAL } from "../consts/config"; import { RTMT_WS_PING_INTERVAL } from "../consts/config";
import { decode, encode } from "./encode_decode_message";
export class RTMTWS implements RTMT { export class RTMTWS implements RTMT {

View File

@ -15,7 +15,8 @@
"author": "Halit Aksoy", "author": "Halit Aksoy",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"mancala.js": "^0.0.2-beta.3" "mancala.js": "^0.0.2-beta.3",
"tiny-emitter": "^2.1.0"
}, },
"devDependencies": { "devDependencies": {
"@types/jest": "^27.4.1", "@types/jest": "^27.4.1",
@ -42,4 +43,4 @@
"url": "https://github.com/jhalitaksoy/mancala/issues" "url": "https://github.com/jhalitaksoy/mancala/issues"
}, },
"homepage": "https://github.com/jhalitaksoy/mancala#readme" "homepage": "https://github.com/jhalitaksoy/mancala#readme"
} }

View File

@ -1,2 +1,2 @@
export * from './rtmt/channel_names' export * from './models/index'
export * from './models/index' export * from './rtmt/index'

View File

@ -1,18 +1,19 @@
import EventEmitter2, { Listener } from "eventemitter2" import { TinyEmitter } from "tiny-emitter"
export type Bytes = Uint8Array export type OnMessage = (message: Object) => any
export type OnMessage = (message : Object) => any
export type ConnectionState = "none" | "connecting" | "error" | "connected" | "closed" | "reconnecting"; export type ConnectionState = "none" | "connecting" | "error" | "connected" | "closed" | "reconnecting";
export type RtmtEventTypes = "open" | "close" | "connected" | "error" | "disconnected" | "message" | "connectionchange"; export type RtmtEventTypes = "open" | "close" | "connected" | "error" | "disconnected" | "message" | "connectionchange";
export interface RTMT extends EventEmitter2 { export const RTMT_WS_PING_INTERVAL = 1000, RTMT_WS_PING_INTERVAL_BUFFER_TIME = 2000;
get connectionState() : ConnectionState;
export interface RTMT extends TinyEmitter {
get connectionState(): ConnectionState;
sendMessage: (channel: string, message: Object) => void; sendMessage: (channel: string, message: Object) => void;
addMessageListener(channel: string, callback: (message: any) => void); addMessageListener(channel: string, callback: (message: any) => void): any;
removeMessageListener(channel: string, callback: (message: any) => void); removeMessageListener(channel: string, callback: (message: any) => void): any;
on(event: RtmtEventTypes, callback: (...value: any[]) => void): Listener | this; on(event: RtmtEventTypes, callback: (...value: any[]) => void): this;
off(event: RtmtEventTypes, callback: (...value: any[]) => void): this; off(event: RtmtEventTypes, callback: (...value: any[]) => void): this;
dispose(); dispose(): any;
} }

View File

@ -1,16 +1,16 @@
import { decode, encode } from "./encode_decode_message"; import { channel_ping, channel_pong } from "../channel_names";
import { channel_ping, channel_pong } from "@mancala/core"; import { decode, encode } from "../encode_decode_message";
import { RTMT_WS_PING_INTERVAL, RTMT_WS_PING_INTERVAL_BUFFER_TIME, server } from "../const/config"; import { ConnectionState, RTMT, RTMT_WS_PING_INTERVAL, RTMT_WS_PING_INTERVAL_BUFFER_TIME, RtmtEventTypes } from "./rtmt";
import EventEmitter2, { Listener } from "eventemitter2"; import { TinyEmitter } from "tiny-emitter";
import { Bytes, ConnectionState, RTMT, RtmtEventTypes } from "./rtmt";
const MESSAGE_CHANNEL_PREFIX = "message_channel"; const MESSAGE_CHANNEL_PREFIX = "message_channel";
export class RTMTWS extends EventEmitter2 implements RTMT { export class RTMTWS extends TinyEmitter implements RTMT {
private webSocket?: WebSocket; private webSocket?: WebSocket;
private pingTimeout?: number = undefined; private pingTimeout?: number = undefined;
private _connectionState: ConnectionState = "none"; private _connectionState: ConnectionState = "none";
private userKey: string; private userKey: string = "";
private url: string = "";
get connectionState(): ConnectionState { get connectionState(): ConnectionState {
return this._connectionState; return this._connectionState;
@ -21,12 +21,11 @@ export class RTMTWS extends EventEmitter2 implements RTMT {
this.emit("connectionchange", this._connectionState); this.emit("connectionchange", this._connectionState);
} }
private createWebSocket() { private createWebSocket(url: string) {
const url = server.wsServerAdress + "?userKey=" + this.userKey;
const webSocket = new WebSocket(url); const webSocket = new WebSocket(url);
webSocket.onopen = () => this.onWebSocketOpen(webSocket); webSocket.onopen = () => this.onWebSocketOpen(webSocket);
webSocket.onclose = () => this.onWebSocketClose(webSocket); webSocket.onclose = () => this.onWebSocketClose(webSocket);
webSocket.onmessage = (event: MessageEvent) => this.onWebSocketMessage(webSocket, event); webSocket.onmessage = (event: any) => this.onWebSocketMessage(webSocket, event);
webSocket.onerror = (error: any) => this.onWebSocketError(webSocket, error); webSocket.onerror = (error: any) => this.onWebSocketError(webSocket, error);
} }
@ -34,21 +33,22 @@ export class RTMTWS extends EventEmitter2 implements RTMT {
if (!this.webSocket) return; if (!this.webSocket) return;
this.webSocket.onopen = () => { }; this.webSocket.onopen = () => { };
this.webSocket.onclose = () => { }; this.webSocket.onclose = () => { };
this.webSocket.onmessage = (event: MessageEvent) => { }; this.webSocket.onmessage = (event: any) => { };
this.webSocket.onerror = (error: any) => { }; this.webSocket.onerror = (error: any) => { };
this.webSocket = undefined; this.webSocket = undefined;
} }
public connectWebSocket(userKey: string) { public connectWebSocket(url: string, userKey: string) {
this.setConnectionState("connecting"); this.setConnectionState("connecting");
this.userKey = userKey; this.userKey = userKey;
this.createWebSocket(); this.url = url;
this.createWebSocket(url);
} }
private reconnectWebSocket() { private reconnectWebSocket() {
this.setConnectionState("reconnecting"); this.setConnectionState("reconnecting");
this.disposeWebSocket(); this.disposeWebSocket();
setTimeout(() => this.createWebSocket(), 1000); setTimeout(() => this.createWebSocket(this.url), 1000);
} }
protected onWebSocketOpen(webSocket: WebSocket) { protected onWebSocketOpen(webSocket: WebSocket) {
@ -59,7 +59,7 @@ export class RTMTWS extends EventEmitter2 implements RTMT {
this.emit("open"); this.emit("open");
} }
protected onWebSocketMessage(webSocket: WebSocket, event: MessageEvent) { protected onWebSocketMessage(webSocket: WebSocket, event: any) {
const { channel, message } = decode(event.data); const { channel, message } = decode(event.data);
this.onMessage(channel, message); this.onMessage(channel, message);
} }
@ -81,6 +81,7 @@ export class RTMTWS extends EventEmitter2 implements RTMT {
private heartbeat() { private heartbeat() {
clearTimeout(this.pingTimeout); clearTimeout(this.pingTimeout);
// @ts-ignore
this.pingTimeout = setTimeout(() => { this.pingTimeout = setTimeout(() => {
if (!this.webSocket) return; if (!this.webSocket) return;
console.log("(RTMT) WebSocket self closed"); console.log("(RTMT) WebSocket self closed");
@ -94,11 +95,11 @@ export class RTMTWS extends EventEmitter2 implements RTMT {
console.error("(RTMT) WebSocket is undefined"); console.error("(RTMT) WebSocket is undefined");
return; return;
} }
const data = encode(channel, message); const data = encode({channel, message});
this.webSocket.send(data); this.webSocket.send(data);
} }
private onMessage(channel: string, message: Bytes) { private onMessage(channel: string, message: Object) {
if (channel === channel_ping) { if (channel === channel_ping) {
this.heartbeat(); this.heartbeat();
this.sendMessage(channel_pong, {}); this.sendMessage(channel_pong, {});
@ -108,7 +109,7 @@ export class RTMTWS extends EventEmitter2 implements RTMT {
this.emit(MESSAGE_CHANNEL_PREFIX + channel, message); this.emit(MESSAGE_CHANNEL_PREFIX + channel, message);
} }
public on(event: RtmtEventTypes, callback: (...value: any[]) => void): Listener | this { public on(event: RtmtEventTypes, callback: (...value: any[]) => void): this {
return super.on(event, callback); return super.on(event, callback);
} }
@ -126,6 +127,7 @@ export class RTMTWS extends EventEmitter2 implements RTMT {
public dispose() { public dispose() {
this.disposeWebSocket(); this.disposeWebSocket();
this.removeAllListeners(); // TODO
//this.removeAllListeners();
} }
} }

View File

@ -0,0 +1,15 @@
export type Message = {
channel: string,
message: Object,
}
export function encode(message: Message) {
return JSON.stringify({
channel : message.channel,
message : message.message
});
}
export function decode(bytes: string): Message {
return JSON.parse(bytes);
}

3
core/src/rtmt/index.ts Normal file
View File

@ -0,0 +1,3 @@
export * from './client/rtmt'
export * from './client/rtmt_websocket'
export * from './channel_names'

View File

@ -2842,6 +2842,11 @@ throat@^6.0.1:
resolved "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz" resolved "https://registry.npmjs.org/throat/-/throat-6.0.1.tgz"
integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w== integrity sha512-8hmiGIJMDlwjg7dlJ4yKGLK8EsYqKgPWbG3b4wjJddKNwc7N7Dpn08Df4szr/sZdMVeOstrdYSsqzX6BYbcB+w==
tiny-emitter@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/tiny-emitter/-/tiny-emitter-2.1.0.tgz#1d1a56edfc51c43e863cbb5382a72330e3555423"
integrity sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==
tmpl@1.0.5: tmpl@1.0.5:
version "1.0.5" version "1.0.5"
resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz" resolved "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz"

View File

@ -10,14 +10,14 @@ import GamePage from './routes/GamePage';
import Home from './routes/Home'; import Home from './routes/Home';
import { initContext } from './context/context'; import { initContext } from './context/context';
import { RTMTWS } from './rtmt/rtmt_websocket'; import { RTMTWS, ConnectionState } from '@mancala/core';
import { getColorByBrightness } from './util/ColorUtil'; import { getColorByBrightness } from './util/ColorUtil';
import { Theme } from './theme/Theme'; import { Theme } from './theme/Theme';
import LobyPage from './routes/LobyPage'; import LobyPage from './routes/LobyPage';
import PrivacyPage from './routes/PrivacyPage'; import PrivacyPage from './routes/PrivacyPage';
import swal from 'sweetalert'; import swal from 'sweetalert';
import { ConnectionState } from './rtmt/rtmt';
import Util from './util/Util'; import Util from './util/Util';
import { server } from './const/config';
const context = initContext(); const context = initContext();
@ -39,7 +39,8 @@ const MancalaApp: FunctionComponent = () => {
const rtmt = context.rtmt as RTMTWS; const rtmt = context.rtmt as RTMTWS;
rtmt.on("error", onConnectionError); rtmt.on("error", onConnectionError);
rtmt.on("connectionchange", onConnectionChange) rtmt.on("connectionchange", onConnectionChange)
rtmt.connectWebSocket(userKey) const url = server.wsServerAdress + "?userKey=" + userKey;
rtmt.connectWebSocket(url, userKey)
return rtmt; return rtmt;
} }

View File

@ -1,7 +1,6 @@
import { server } from "../const/config"; import { server } from "../const/config";
import { Texts, TrTr } from "../const/texts"; import { Texts, TrTr } from "../const/texts";
import { RTMT } from "../rtmt/rtmt"; import { RTMT, RTMTWS } from "@mancala/core";
import { RTMTWS } from "../rtmt/rtmt_websocket";
import { HttpServiceImpl } from "../service/HttpService"; import { HttpServiceImpl } from "../service/HttpService";
import { GameStore, GameStoreImpl } from "../store/GameStore"; import { GameStore, GameStoreImpl } from "../store/GameStore";
import { UserKeyStore, UserKeyStoreImpl } from "../store/KeyStore"; import { UserKeyStore, UserKeyStoreImpl } from "../store/KeyStore";

View File

@ -1,12 +0,0 @@
import { Bytes } from "./rtmt"
const textEncoder = new TextEncoder()
const textDecoder = new TextDecoder("utf-8")
export function encodeText(text : string) {
const bytes = textEncoder.encode(text)
return bytes
}
export function decodeText(bytes : Bytes) {
return textDecoder.decode(bytes)
}

View File

@ -1,20 +0,0 @@
import { decodeText, encodeText } from "./byte_util";
import { Bytes } from "./rtmt";
const headerLenght = 4
//
// channel is string, message is byte array
//
export function encode(channel : string, message : Object) {
return JSON.stringify({
channel,
message
})
}
//
// return { channel : string, message : byte array}
//
export function decode(bytes : string) {
return JSON.parse(bytes);
}

View File

@ -7,8 +7,7 @@ import { HomeScreen } from './screens/HomeScreen';
import LobyScreen from './screens/LobyScreen'; import LobyScreen from './screens/LobyScreen';
import { Context, initContext } from './context/context'; import { Context, initContext } from './context/context';
import { GameScreen } from './screens/GameScreen'; import { GameScreen } from './screens/GameScreen';
import { RTMTWS } from './rtmt/rtmt_websocket'; import { RTMTWS, ConnectionState } from '@mancala/core';
import { ConnectionState } from './rtmt/rtmt';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import Snackbar from 'react-native-snackbar'; import Snackbar from 'react-native-snackbar';
import { NativeModules, I18nManager, Platform } from 'react-native' import { NativeModules, I18nManager, Platform } from 'react-native'
@ -17,6 +16,7 @@ import { NativeModules, I18nManager, Platform } from 'react-native'
import 'react-native-get-random-values'; import 'react-native-get-random-values';
import HelpScreen from './screens/HelpScreen'; import HelpScreen from './screens/HelpScreen';
import { getColorByBrightness } from './util/ColorUtil'; import { getColorByBrightness } from './util/ColorUtil';
import { server } from './const/config';
const Stack = createNativeStackNavigator<RootStackParamList>(); const Stack = createNativeStackNavigator<RootStackParamList>();
@ -57,7 +57,8 @@ function App() {
const rtmt = context.rtmt as RTMTWS; const rtmt = context.rtmt as RTMTWS;
rtmt.on("error", onConnectionError); rtmt.on("error", onConnectionError);
rtmt.on("connectionchange", onConnectionChange) rtmt.on("connectionchange", onConnectionChange)
rtmt.connectWebSocket(userKey) const url = server.wsServerAdress + "?userKey=" + userKey;
rtmt.connectWebSocket(url, userKey)
return rtmt; return rtmt;
} }
const getTextByConnectionState = (context: Context, connectionState: ConnectionState): string => { const getTextByConnectionState = (context: Context, connectionState: ConnectionState): string => {

View File

@ -14,8 +14,6 @@ export const server: Server = useLocalServer ? {
wsServerAdress: "wss://mancala.segin.one", wsServerAdress: "wss://mancala.segin.one",
}; };
export const RTMT_WS_PING_INTERVAL = 1000, RTMT_WS_PING_INTERVAL_BUFFER_TIME = 2000;
export const WEB_APP_URL = "https://playmancala.app"; export const WEB_APP_URL = "https://playmancala.app";
export const PRIVAcY_URL = "https://playmancala.app/privacy"; export const PRIVAcY_URL = "https://playmancala.app/privacy";

View File

@ -1,6 +1,5 @@
import { server } from "../const/config"; import { server } from "../const/config";
import { RTMT } from "../rtmt/rtmt"; import { RTMT, RTMTWS } from "@mancala/core";
import { RTMTWS } from "../rtmt/rtmt_websocket";
import { HttpServiceImpl } from "../service/HttpService"; import { HttpServiceImpl } from "../service/HttpService";
import { GameStore, GameStoreImpl } from "../store/GameStore"; import { GameStore, GameStoreImpl } from "../store/GameStore";
import { UserKeyStore, UserKeyStoreImpl } from "../store/KeyStore"; import { UserKeyStore, UserKeyStoreImpl } from "../store/KeyStore";

View File

@ -1,12 +0,0 @@
import { Bytes } from "./rtmt"
const textEncoder = new TextEncoder()
const textDecoder = new TextDecoder("utf-8")
export function encodeText(text : string) {
const bytes = textEncoder.encode(text)
return bytes
}
export function decodeText(bytes : Bytes) {
return textDecoder.decode(bytes)
}

View File

@ -1,20 +0,0 @@
import { decodeText, encodeText } from "./byte_util";
import { Bytes } from "./rtmt";
const headerLenght = 4
//
// channel is string, message is byte array
//
export function encode(channel : string, message : Object) {
return JSON.stringify({
channel,
message
})
}
//
// return { channel : string, message : byte array}
//
export function decode(bytes : string) {
return JSON.parse(bytes);
}

View File

@ -7,6 +7,8 @@ export type ConnectionState = "none" | "connecting" | "error" | "connected" | "c
export type RtmtEventTypes = "open" | "close" | "connected" | "error" | "disconnected" | "message" | "connectionchange"; export type RtmtEventTypes = "open" | "close" | "connected" | "error" | "disconnected" | "message" | "connectionchange";
export const RTMT_WS_PING_INTERVAL = 1000, RTMT_WS_PING_INTERVAL_BUFFER_TIME = 2000;
export interface RTMT extends TinyEmitter { export interface RTMT extends TinyEmitter {
get connectionState(): ConnectionState; get connectionState(): ConnectionState;
sendMessage: (channel: string, message: Object) => void; sendMessage: (channel: string, message: Object) => void;