diff --git a/package.json b/package.json index 841a43b..f370d54 100644 --- a/package.json +++ b/package.json @@ -79,6 +79,7 @@ "redux": "^3.7.1", "redux-saga": "^0.15.4", "reselect": "^3.0.1", + "semantic-ui-css":"^2.2.10", "semantic-ui-react": "^0.70.0", "socket.io-client": "^2.0.3" }, diff --git a/src/ts/@overflow/app/index.tsx b/src/ts/@overflow/app/index.tsx index e821529..10e10c4 100644 --- a/src/ts/@overflow/app/index.tsx +++ b/src/ts/@overflow/app/index.tsx @@ -4,7 +4,6 @@ import { fork } from 'redux-saga/effects'; import { Provider } from 'react-redux'; import { ConnectedRouter } from 'react-router-redux'; -import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider'; import * as injectTapEventPlugin from 'react-tap-event-plugin'; @@ -20,8 +19,6 @@ injectTapEventPlugin(); function* app(): any { const appContainer: HTMLElement = yield Platform.getAppContainer('react-placeholder'); - - ReactDOM.render(
- - - {routes} - - + + {routes} + , appContainer, ); } sagaMiddleware.run(app); + diff --git a/src/ts/@overflow/commons/websocket/WebSocketRPC.ts b/src/ts/@overflow/commons/websocket/WebSocketRPC.ts new file mode 100644 index 0000000..9c2c83e --- /dev/null +++ b/src/ts/@overflow/commons/websocket/WebSocketRPC.ts @@ -0,0 +1,136 @@ +import { + ProtocolNotification, + ProtocolRequest, + ProtocolResponse, +} from './protocol'; + +import { + PROTOCOL_NAME as RPCProtocol, + RPCRequest, + RPCResponse, +} from './protocol/rpc'; + + +export type OnConnectFunc = () => void; +export type OnDisconnectFunc = () => void; +export type OnResponseFunc = (response: any) => void; + +type ID_TYPE = number; + +interface RequestQueue { + resolve: (value?: any) => void; + reject: (reason?: any) => void; +} + +export default class WebSocketRPC { + private url: string; + private conn: WebSocket; + private isReady: boolean; + private requestID: ID_TYPE = 0; + + private onConnectListeners: OnConnectFunc[] = []; + private onDisconnectListeners: OnDisconnectFunc[] = []; + private onResponseListeners: Map; + + private requestQueue: Map; + /** + * name + */ + public constructor(url: string) { + this.isReady = false; + this.url = url; + this.onResponseListeners = new Map(); + this.requestQueue = new Map(); + + this.initialize(); + } + + public Call(method: string, params: any[]): Promise { + + + return new Promise((resolve, reject) => { + const requestID = this.getRequestID(); + let request = new ProtocolRequest(RPCProtocol, requestID); + let req = new RPCRequest(method, params); + request.setBody(req.toJSON()); + this.conn.send(request.toJSON()); + this.requestQueue.set(requestID, {resolve: resolve, reject: reject}); + }); + } + + + public OnConnect(cb: OnConnectFunc): void { + if (this.isReady) { + cb(); + } + this.onConnectListeners.push(cb); + } + + public OnDisconnect(cb: OnDisconnectFunc): void { + this.onDisconnectListeners.push(cb); + } + + private initialize(): void { + this.conn = new WebSocket(this.url); + this.conn.onopen = (e: Event): any => { + this.fireOnConnect(); + this.isReady = true; + return null; + }; + + this.conn.onclose = (e: CloseEvent): any => { + this.fireOnDisconnect(); + return null; + }; + + this.conn.onmessage = (e: MessageEvent): any => { + let response: ProtocolResponse = JSON.parse(e.data); + let res: RPCResponse = JSON.parse(response.getBody()); + const requestID = response.getID(); + const error = response.getError(); + const result = res.getResult(); + + if (this.requestQueue.has(requestID)) { + let promise = this.requestQueue.get(requestID); + this.requestQueue.delete(requestID); + if (null != result) { + promise.resolve(result); + } else if (null != error) { + promise.reject(error); + } else { + console.log('??????'); + } + } else { + // perhaps sever side send message + } + + this.fireOnMessage(e); + }; + + } + + private fireOnConnect(): void { + for (let i = 0; i < this.onConnectListeners.length; i++) { + this.onConnectListeners[i](); + } + } + + private fireOnDisconnect(): void { + for (let i = 0; i < this.onDisconnectListeners.length; i++) { + this.onDisconnectListeners[i](); + } + } + + private fireOnMessage(e: MessageEvent): void { + + + for (let i = 0; i < this.onDisconnectListeners.length; i++) { + this.onDisconnectListeners[i](); + } + } + + private getRequestID(): number { + return ++this.requestID; + } + +} diff --git a/src/ts/@overflow/commons/websocket/protocol/ProtocolError.ts b/src/ts/@overflow/commons/websocket/protocol/ProtocolError.ts new file mode 100644 index 0000000..69568c1 --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/ProtocolError.ts @@ -0,0 +1,46 @@ +export const enum ErrorCode { + E_PARSE = -32700, + E_INVALID_REQ = -32600, + E_NO_METHOD = -32601, + E_BAD_PARAMS = -32602, + E_INTERNAL = -32603, + E_SERVER = -32000, + +} + +export class ProtocolError { + private code: ErrorCode; + private message: string; + private data: any; + + public constructor(code: ErrorCode, message: string, data: any) { + this.code = code; + this.message = message; + this.data = data; + } + + /** + * getID + */ + public getCode(): ErrorCode { + return this.code; + } + + /** + * getBody + */ + public getMessage(): string { + return this.message; + } + + /** + * getError + */ + public getData(): any { + return this.data; + } + + public static newError(json: string): ProtocolError { + return JSON.parse(json); + } +} diff --git a/src/ts/@overflow/commons/websocket/protocol/ProtocolHeader.ts b/src/ts/@overflow/commons/websocket/protocol/ProtocolHeader.ts new file mode 100644 index 0000000..059cd2b --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/ProtocolHeader.ts @@ -0,0 +1,44 @@ +export class ProtocolHeader { + private readonly protocol: string; + private readonly id: ID; + private body: string; + + public constructor(protocol: string, id: ID) { + this.protocol = protocol; + this.id = id; + } + + /** + * getProtocol + */ + public getProtocol(): string { + return this.protocol; + } + + /** + * getID + */ + public getID(): ID { + return this.id; + } + + /** + * setID + */ + public setBody(body: string): void { + this.body = body; + } + /** + * getID + */ + public getBody(): string { + return this.body; + } + + /** + * toJSON + */ + public toJSON(): string { + return JSON.stringify(this); + } +} diff --git a/src/ts/@overflow/commons/websocket/protocol/ProtocolNotification.ts b/src/ts/@overflow/commons/websocket/protocol/ProtocolNotification.ts new file mode 100644 index 0000000..619025b --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/ProtocolNotification.ts @@ -0,0 +1,35 @@ +export class ProtocolNotification { + private readonly protocol: string; + private body: string; + + public constructor(protocol: string) { + this.protocol = protocol; + } + + /** + * getProtocol + */ + public getProtocol(): string { + return this.protocol; + } + + /** + * setBody + */ + public setBody(body: string): void { + this.body = body; + } + /** + * getBody + */ + public getBody(): string { + return this.body; + } + + /** + * toJSON + */ + public toJSON(): string { + return JSON.stringify(this); + } +} diff --git a/src/ts/@overflow/commons/websocket/protocol/ProtocolRequest.ts b/src/ts/@overflow/commons/websocket/protocol/ProtocolRequest.ts new file mode 100644 index 0000000..1339d21 --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/ProtocolRequest.ts @@ -0,0 +1,7 @@ +import { ProtocolHeader } from './ProtocolHeader'; + +export class ProtocolRequest extends ProtocolHeader { + public constructor(protocol: string, id: ID) { + super(protocol, id); + } +} diff --git a/src/ts/@overflow/commons/websocket/protocol/ProtocolResponse.ts b/src/ts/@overflow/commons/websocket/protocol/ProtocolResponse.ts new file mode 100644 index 0000000..551ee5e --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/ProtocolResponse.ts @@ -0,0 +1,23 @@ +import { ProtocolHeader } from './ProtocolHeader'; +import { ProtocolError } from './ProtocolError'; + +export class ProtocolResponse extends ProtocolHeader { + private error: ProtocolError; + + public constructor(protocol: string, id: ID) { + super(protocol, id); + } + + /** + * setError + */ + public setError(error: ProtocolError): void { + this.error = error; + } + /** + * getError + */ + public getError(): ProtocolError { + return this.error; + } +} diff --git a/src/ts/@overflow/commons/websocket/protocol/ProtocolSub.ts b/src/ts/@overflow/commons/websocket/protocol/ProtocolSub.ts new file mode 100644 index 0000000..9149392 --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/ProtocolSub.ts @@ -0,0 +1,6 @@ +export abstract class ProtocolSub { + /** + * toJSON + */ + public abstract toJSON(): string; +} diff --git a/src/ts/@overflow/commons/websocket/protocol/index.ts b/src/ts/@overflow/commons/websocket/protocol/index.ts new file mode 100644 index 0000000..afdd54d --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/index.ts @@ -0,0 +1,6 @@ +export * from './ProtocolError'; +export * from './ProtocolHeader'; +export * from './ProtocolNotification'; +export * from './ProtocolRequest'; +export * from './ProtocolResponse'; +export * from './ProtocolSub'; diff --git a/src/ts/@overflow/commons/websocket/protocol/rpc/RPCRequest.ts b/src/ts/@overflow/commons/websocket/protocol/rpc/RPCRequest.ts new file mode 100644 index 0000000..72866a2 --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/rpc/RPCRequest.ts @@ -0,0 +1,33 @@ +import { ProtocolSub } from '../ProtocolSub'; + +export class RPCRequest extends ProtocolSub { + private readonly method: string; + private readonly params: any[]; + + public constructor(method: string, params: any[]) { + super(); + this.method = method; + this.params = params; + } + + /** + * getMethod + */ + public getMethod(): string { + return this.method; + } + + /** + * getParams + */ + public getParams(): any[] { + return this.params; + } + + /** + * toJSON + */ + public toJSON(): string { + return JSON.stringify(this); + } +} diff --git a/src/ts/@overflow/commons/websocket/protocol/rpc/RPCResponse.ts b/src/ts/@overflow/commons/websocket/protocol/rpc/RPCResponse.ts new file mode 100644 index 0000000..af7ebcc --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/rpc/RPCResponse.ts @@ -0,0 +1,24 @@ +import { ProtocolSub } from '../ProtocolSub'; + +export class RPCResponse extends ProtocolSub { + private readonly result: any; + + public constructor(result: any) { + super(); + this.result = result; + } + + /** + * getResult + */ + public getResult(): any { + return this.result; + } + + /** + * toJSON + */ + public toJSON(): string { + return JSON.stringify(this); + } +} diff --git a/src/ts/@overflow/commons/websocket/protocol/rpc/index.ts b/src/ts/@overflow/commons/websocket/protocol/rpc/index.ts new file mode 100644 index 0000000..f51d676 --- /dev/null +++ b/src/ts/@overflow/commons/websocket/protocol/rpc/index.ts @@ -0,0 +1,5 @@ +export * from './RPCRequest'; +export * from './RPCResponse'; + +export const PROTOCOL_NAME = 'jsonrpc'; + diff --git a/src/ts/@overflow/member/api/service/MemberService.ts b/src/ts/@overflow/member/api/service/MemberService.ts index 0a20dbc..562c509 100644 --- a/src/ts/@overflow/member/api/service/MemberService.ts +++ b/src/ts/@overflow/member/api/service/MemberService.ts @@ -1,6 +1,7 @@ import Service from '@overflow/commons/api/Service'; import Member from '../model/Member'; +@ServiceClass export class MemberService extends Service { public constructor() { diff --git a/tsconfig.json b/tsconfig.json index 1dac4cf..c9017b0 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "allowSyntheticDefaultImports": true, - "baseUrl": "src/ts", + "baseUrl": ".", "declaration": true, "emitDecoratorMetadata": true, "experimentalDecorators": true, @@ -11,7 +11,7 @@ "es5", "es6" ], - "module": "esnext", + "module": "umd", "moduleResolution": "node", "newLine": "LF", "noImplicitAny": false, @@ -19,6 +19,12 @@ "outDir": "dist/ts/", "preserveConstEnums": true, "pretty": true, + "paths": { + "*": [ + "./src/ts/*", + "./types/*" + ] + }, "removeComments": true, "sourceMap": true, "target": "es5", @@ -34,6 +40,7 @@ "build", "config", "node_modules", - "public" + "public", + "types" ] }