@push.rocks/smartsocket 2.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist_bundle/bundle.js +10311 -0
- package/dist_bundle/bundle.js.map +7 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +7 -0
- package/dist_ts/interfaces/connection.d.ts +4 -0
- package/dist_ts/interfaces/connection.js +2 -0
- package/dist_ts/interfaces/index.d.ts +2 -0
- package/dist_ts/interfaces/index.js +3 -0
- package/dist_ts/interfaces/tag.d.ts +7 -0
- package/dist_ts/interfaces/tag.js +2 -0
- package/dist_ts/smartsocket.classes.smartsocket.d.ts +43 -0
- package/dist_ts/smartsocket.classes.smartsocket.js +102 -0
- package/dist_ts/smartsocket.classes.smartsocketclient.d.ts +64 -0
- package/dist_ts/smartsocket.classes.smartsocketclient.js +217 -0
- package/dist_ts/smartsocket.classes.socketconnection.d.ts +65 -0
- package/dist_ts/smartsocket.classes.socketconnection.js +169 -0
- package/dist_ts/smartsocket.classes.socketfunction.d.ts +45 -0
- package/dist_ts/smartsocket.classes.socketfunction.js +40 -0
- package/dist_ts/smartsocket.classes.socketrequest.d.ts +47 -0
- package/dist_ts/smartsocket.classes.socketrequest.js +72 -0
- package/dist_ts/smartsocket.classes.socketserver.d.ts +35 -0
- package/dist_ts/smartsocket.classes.socketserver.js +78 -0
- package/dist_ts/smartsocket.logging.d.ts +2 -0
- package/dist_ts/smartsocket.logging.js +3 -0
- package/dist_ts/smartsocket.plugins.d.ts +13 -0
- package/dist_ts/smartsocket.plugins.js +16 -0
- package/dist_ts/smartsocket.pluginstyped.d.ts +15 -0
- package/dist_ts/smartsocket.pluginstyped.js +2 -0
- package/npmextra.json +18 -0
- package/package.json +64 -0
- package/readme.md +120 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/index.ts +7 -0
- package/ts/interfaces/connection.ts +11 -0
- package/ts/interfaces/index.ts +2 -0
- package/ts/interfaces/tag.ts +6 -0
- package/ts/smartsocket.classes.smartsocket.ts +137 -0
- package/ts/smartsocket.classes.smartsocketclient.ts +266 -0
- package/ts/smartsocket.classes.socketconnection.ts +224 -0
- package/ts/smartsocket.classes.socketfunction.ts +93 -0
- package/ts/smartsocket.classes.socketrequest.ts +126 -0
- package/ts/smartsocket.classes.socketserver.ts +94 -0
- package/ts/smartsocket.logging.ts +3 -0
- package/ts/smartsocket.plugins.ts +29 -0
- package/ts/smartsocket.pluginstyped.ts +23 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
import * as plugins from './smartsocket.plugins.js';
|
|
2
|
+
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
|
3
|
+
import * as interfaces from './interfaces/index.js';
|
|
4
|
+
|
|
5
|
+
// import classes
|
|
6
|
+
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
|
7
|
+
import { SocketFunction } from './smartsocket.classes.socketfunction.js';
|
|
8
|
+
import { SocketRequest, ISocketRequestDataObject } from './smartsocket.classes.socketrequest.js';
|
|
9
|
+
|
|
10
|
+
// socket.io
|
|
11
|
+
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
|
12
|
+
import { logger } from './smartsocket.logging.js';
|
|
13
|
+
|
|
14
|
+
// export interfaces
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* defines is a SocketConnection is server or client side. Important for mesh setups.
|
|
18
|
+
*/
|
|
19
|
+
export type TSocketConnectionSide = 'server' | 'client';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* interface for constructor of class SocketConnection
|
|
23
|
+
*/
|
|
24
|
+
export interface ISocketConnectionConstructorOptions {
|
|
25
|
+
alias: string;
|
|
26
|
+
authenticated: boolean;
|
|
27
|
+
side: TSocketConnectionSide;
|
|
28
|
+
smartsocketHost: Smartsocket | SmartsocketClient;
|
|
29
|
+
socket: pluginsTyped.socketIo.Socket | pluginsTyped.socketIoClient.Socket;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* interface for authentication data
|
|
34
|
+
*/
|
|
35
|
+
export interface ISocketConnectionAuthenticationObject {
|
|
36
|
+
alias: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// export classes
|
|
40
|
+
export let allSocketConnections = new plugins.lik.ObjectMap<SocketConnection>();
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* class SocketConnection represents a websocket connection
|
|
44
|
+
*/
|
|
45
|
+
export class SocketConnection {
|
|
46
|
+
public alias: string;
|
|
47
|
+
public side: TSocketConnectionSide;
|
|
48
|
+
public authenticated: boolean = false;
|
|
49
|
+
public smartsocketRef: Smartsocket | SmartsocketClient;
|
|
50
|
+
public socket: pluginsTyped.socketIo.Socket | pluginsTyped.socketIoClient.Socket;
|
|
51
|
+
|
|
52
|
+
public eventSubject = new plugins.smartrx.rxjs.Subject<interfaces.TConnectionStatus>();
|
|
53
|
+
public eventStatus: interfaces.TConnectionStatus = 'new';
|
|
54
|
+
|
|
55
|
+
private tagStore: interfaces.TTagStore = {};
|
|
56
|
+
public tagStoreObservable = new plugins.smartrx.rxjs.Subject<interfaces.TTagStore>();
|
|
57
|
+
public remoteTagStoreObservable = new plugins.smartrx.rxjs.Subject<interfaces.TTagStore>();
|
|
58
|
+
|
|
59
|
+
constructor(optionsArg: ISocketConnectionConstructorOptions) {
|
|
60
|
+
this.alias = optionsArg.alias;
|
|
61
|
+
this.authenticated = optionsArg.authenticated;
|
|
62
|
+
this.side = optionsArg.side;
|
|
63
|
+
this.smartsocketRef = optionsArg.smartsocketHost;
|
|
64
|
+
this.socket = optionsArg.socket;
|
|
65
|
+
|
|
66
|
+
// standard behaviour that is always true
|
|
67
|
+
allSocketConnections.add(this);
|
|
68
|
+
|
|
69
|
+
// handle connection
|
|
70
|
+
this.socket.on('connect', async () => {
|
|
71
|
+
this.updateStatus('connected');
|
|
72
|
+
});
|
|
73
|
+
this.socket.on('disconnect', async () => {
|
|
74
|
+
logger.log(
|
|
75
|
+
'info',
|
|
76
|
+
`SocketConnection with >alias ${this.alias} on >side ${this.side} disconnected`
|
|
77
|
+
);
|
|
78
|
+
await this.disconnect();
|
|
79
|
+
allSocketConnections.remove(this);
|
|
80
|
+
this.eventSubject.next('disconnected');
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* adds a tag to a connection
|
|
86
|
+
*/
|
|
87
|
+
public async addTag(tagArg: interfaces.ITag) {
|
|
88
|
+
const done = plugins.smartpromise.defer();
|
|
89
|
+
this.tagStore[tagArg.id] = tagArg;
|
|
90
|
+
this.tagStoreObservable.next(this.tagStore);
|
|
91
|
+
const remoteSubscription = this.remoteTagStoreObservable.subscribe((remoteTagStore) => {
|
|
92
|
+
if (!remoteTagStore[tagArg.id]) {
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
const localTagString = plugins.smartjson.stringify(tagArg);
|
|
96
|
+
const remoteTagString = plugins.smartjson.stringify(remoteTagStore[tagArg.id]);
|
|
97
|
+
if (localTagString === remoteTagString) {
|
|
98
|
+
remoteSubscription.unsubscribe();
|
|
99
|
+
done.resolve();
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
this.socket.emit('updateTagStore', this.tagStore);
|
|
103
|
+
await done.promise;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* gets a tag by id
|
|
108
|
+
* @param tagIdArg
|
|
109
|
+
*/
|
|
110
|
+
public async getTagById(tagIdArg: interfaces.ITag['id']) {
|
|
111
|
+
return this.tagStore[tagIdArg];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* removes a tag from a connection
|
|
116
|
+
*/
|
|
117
|
+
public async removeTagById(tagIdArg: interfaces.ITag['id']) {
|
|
118
|
+
delete this.tagStore[tagIdArg];
|
|
119
|
+
this.tagStoreObservable.next(this.tagStore);
|
|
120
|
+
this.socket.emit('updateTagStore', this.tagStore);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// authenticating --------------------------
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* authenticate the socket
|
|
127
|
+
*/
|
|
128
|
+
public authenticate() {
|
|
129
|
+
const done = plugins.smartpromise.defer();
|
|
130
|
+
this.socket.on('dataAuth', async (dataArg: ISocketConnectionAuthenticationObject) => {
|
|
131
|
+
logger.log('info', 'received authentication data...');
|
|
132
|
+
this.socket.removeAllListeners('dataAuth');
|
|
133
|
+
if (dataArg.alias) {
|
|
134
|
+
// TODO: authenticate password
|
|
135
|
+
this.alias = dataArg.alias;
|
|
136
|
+
this.authenticated = true;
|
|
137
|
+
this.socket.emit('authenticated');
|
|
138
|
+
logger.log('ok', `socket with >>alias ${this.alias} is authenticated!`);
|
|
139
|
+
done.resolve(this);
|
|
140
|
+
} else {
|
|
141
|
+
this.authenticated = false;
|
|
142
|
+
await this.disconnect();
|
|
143
|
+
done.reject('a socket tried to connect, but could not authenticated.');
|
|
144
|
+
}
|
|
145
|
+
});
|
|
146
|
+
const requestAuthPayload: interfaces.IRequestAuthPayload = {
|
|
147
|
+
serverAlias: this.smartsocketRef.alias,
|
|
148
|
+
};
|
|
149
|
+
this.socket.emit('requestAuth', requestAuthPayload);
|
|
150
|
+
return done.promise;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// listening -------------------------------
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* listen to function requests
|
|
157
|
+
*/
|
|
158
|
+
public listenToFunctionRequests() {
|
|
159
|
+
const done = plugins.smartpromise.defer();
|
|
160
|
+
if (this.authenticated) {
|
|
161
|
+
this.socket.on('function', (dataArg: ISocketRequestDataObject<any>) => {
|
|
162
|
+
// check if requested function is available to the socket's scope
|
|
163
|
+
// logger.log('info', 'function request received');
|
|
164
|
+
const referencedFunction: SocketFunction<any> =
|
|
165
|
+
this.smartsocketRef.socketFunctions.findSync((socketFunctionArg) => {
|
|
166
|
+
return socketFunctionArg.name === dataArg.funcCallData.funcName;
|
|
167
|
+
});
|
|
168
|
+
if (referencedFunction) {
|
|
169
|
+
// logger.log('ok', 'function in access scope');
|
|
170
|
+
const localSocketRequest = new SocketRequest(this.smartsocketRef, {
|
|
171
|
+
side: 'responding',
|
|
172
|
+
originSocketConnection: this,
|
|
173
|
+
shortId: dataArg.shortId,
|
|
174
|
+
funcCallData: dataArg.funcCallData,
|
|
175
|
+
});
|
|
176
|
+
localSocketRequest.createResponse(); // takes care of creating response and sending it back
|
|
177
|
+
} else {
|
|
178
|
+
logger.log('warn', 'function not existent or out of access scope');
|
|
179
|
+
}
|
|
180
|
+
});
|
|
181
|
+
this.socket.on('functionResponse', (dataArg: ISocketRequestDataObject<any>) => {
|
|
182
|
+
// logger.log('info', `received response for request with id ${dataArg.shortId}`);
|
|
183
|
+
const targetSocketRequest = SocketRequest.getSocketRequestById(
|
|
184
|
+
this.smartsocketRef,
|
|
185
|
+
dataArg.shortId
|
|
186
|
+
);
|
|
187
|
+
targetSocketRequest.handleResponse(dataArg);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
this.socket.on('updateTagStore', async (tagStoreArg: interfaces.TTagStore) => {
|
|
191
|
+
if (!plugins.smartjson.deepEqualObjects(this.tagStore, tagStoreArg)) {
|
|
192
|
+
this.tagStore = tagStoreArg;
|
|
193
|
+
this.socket.emit('updateTagStore', this.tagStore);
|
|
194
|
+
this.tagStoreObservable.next(this.tagStore);
|
|
195
|
+
}
|
|
196
|
+
this.remoteTagStoreObservable.next(tagStoreArg);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
logger.log(
|
|
200
|
+
'info',
|
|
201
|
+
`now listening to function requests for ${this.alias} on side ${this.side}`
|
|
202
|
+
);
|
|
203
|
+
done.resolve(this);
|
|
204
|
+
} else {
|
|
205
|
+
const errMessage = 'socket needs to be authenticated first';
|
|
206
|
+
logger.log('error', errMessage);
|
|
207
|
+
done.reject(errMessage);
|
|
208
|
+
}
|
|
209
|
+
return done.promise;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// disconnecting ----------------------
|
|
213
|
+
public async disconnect() {
|
|
214
|
+
this.socket.disconnect(true);
|
|
215
|
+
this.updateStatus('disconnected');
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private updateStatus(statusArg: interfaces.TConnectionStatus) {
|
|
219
|
+
if (this.eventStatus !== statusArg) {
|
|
220
|
+
this.eventSubject.next(statusArg);
|
|
221
|
+
}
|
|
222
|
+
this.eventStatus = statusArg;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import * as plugins from './smartsocket.plugins.js';
|
|
2
|
+
|
|
3
|
+
// import classes
|
|
4
|
+
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
|
5
|
+
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
|
6
|
+
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
|
7
|
+
|
|
8
|
+
// export interfaces
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* interface of the contructor options of class SocketFunction
|
|
12
|
+
*/
|
|
13
|
+
export interface ISocketFunctionConstructorOptions<
|
|
14
|
+
T extends plugins.typedrequestInterfaces.ITypedRequest
|
|
15
|
+
> {
|
|
16
|
+
funcName: T['method'];
|
|
17
|
+
funcDef: TFuncDef<T>;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* interface of the Socket Function call, in other words the object that routes a call to a function
|
|
22
|
+
*/
|
|
23
|
+
export interface ISocketFunctionCallDataRequest<
|
|
24
|
+
T extends plugins.typedrequestInterfaces.ITypedRequest
|
|
25
|
+
> {
|
|
26
|
+
funcName: T['method'];
|
|
27
|
+
funcDataArg: T['request'];
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* interface of the Socket Function call, in other words the object that routes a call to a function
|
|
32
|
+
*/
|
|
33
|
+
export interface ISocketFunctionCallDataResponse<
|
|
34
|
+
T extends plugins.typedrequestInterfaces.ITypedRequest
|
|
35
|
+
> {
|
|
36
|
+
funcName: T['method'];
|
|
37
|
+
funcDataArg: T['response'];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* interface for function definition of SocketFunction
|
|
42
|
+
*/
|
|
43
|
+
export type TFuncDef<T extends plugins.typedrequestInterfaces.ITypedRequest> = (
|
|
44
|
+
dataArg: T['request'],
|
|
45
|
+
connectionArg: SocketConnection
|
|
46
|
+
) => PromiseLike<T['response']>;
|
|
47
|
+
|
|
48
|
+
// export classes
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* class that respresents a function that can be transparently called using a SocketConnection
|
|
52
|
+
*/
|
|
53
|
+
export class SocketFunction<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
|
54
|
+
// STATIC
|
|
55
|
+
public static getSocketFunctionByName<Q extends plugins.typedrequestInterfaces.ITypedRequest>(
|
|
56
|
+
smartsocketRefArg: Smartsocket | SmartsocketClient,
|
|
57
|
+
functionNameArg: string
|
|
58
|
+
): SocketFunction<Q> {
|
|
59
|
+
return smartsocketRefArg.socketFunctions.findSync((socketFunctionArg) => {
|
|
60
|
+
return socketFunctionArg.name === functionNameArg;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// INSTANCE
|
|
65
|
+
public name: string;
|
|
66
|
+
public funcDef: TFuncDef<T>;
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* the constructor for SocketFunction
|
|
70
|
+
*/
|
|
71
|
+
constructor(optionsArg: ISocketFunctionConstructorOptions<T>) {
|
|
72
|
+
this.name = optionsArg.funcName;
|
|
73
|
+
this.funcDef = optionsArg.funcDef;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* invokes the function of this SocketFunction
|
|
78
|
+
*/
|
|
79
|
+
public async invoke(
|
|
80
|
+
dataArg: ISocketFunctionCallDataRequest<T>,
|
|
81
|
+
socketConnectionArg: SocketConnection
|
|
82
|
+
): Promise<ISocketFunctionCallDataResponse<T>> {
|
|
83
|
+
if (dataArg.funcName === this.name) {
|
|
84
|
+
const funcResponseData: ISocketFunctionCallDataResponse<T> = {
|
|
85
|
+
funcName: this.name,
|
|
86
|
+
funcDataArg: await this.funcDef(dataArg.funcDataArg, socketConnectionArg),
|
|
87
|
+
};
|
|
88
|
+
return funcResponseData;
|
|
89
|
+
} else {
|
|
90
|
+
throw new Error("SocketFunction.name does not match the data argument's .name!");
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import * as plugins from './smartsocket.plugins.js';
|
|
2
|
+
|
|
3
|
+
// import interfaces
|
|
4
|
+
import {
|
|
5
|
+
SocketFunction,
|
|
6
|
+
ISocketFunctionCallDataRequest,
|
|
7
|
+
ISocketFunctionCallDataResponse,
|
|
8
|
+
} from './smartsocket.classes.socketfunction.js';
|
|
9
|
+
|
|
10
|
+
// import classes
|
|
11
|
+
import { SocketConnection } from './smartsocket.classes.socketconnection.js';
|
|
12
|
+
import { logger } from './smartsocket.logging.js';
|
|
13
|
+
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
|
14
|
+
import { SmartsocketClient } from './smartsocket.classes.smartsocketclient.js';
|
|
15
|
+
|
|
16
|
+
// export interfaces
|
|
17
|
+
export type TSocketRequestStatus = 'new' | 'pending' | 'finished';
|
|
18
|
+
export type TSocketRequestSide = 'requesting' | 'responding';
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* interface of constructor of class SocketRequest
|
|
22
|
+
*/
|
|
23
|
+
export interface ISocketRequestConstructorOptions<
|
|
24
|
+
T extends plugins.typedrequestInterfaces.ITypedRequest
|
|
25
|
+
> {
|
|
26
|
+
side: TSocketRequestSide;
|
|
27
|
+
originSocketConnection: SocketConnection;
|
|
28
|
+
shortId: string;
|
|
29
|
+
funcCallData?: ISocketFunctionCallDataRequest<T>;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* request object that is sent initially and may or may not receive a response
|
|
34
|
+
*/
|
|
35
|
+
export interface ISocketRequestDataObject<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
|
36
|
+
funcCallData: ISocketFunctionCallDataRequest<T> | ISocketFunctionCallDataResponse<T>;
|
|
37
|
+
shortId: string;
|
|
38
|
+
responseTimeout?: number;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// export classes
|
|
42
|
+
export class SocketRequest<T extends plugins.typedrequestInterfaces.ITypedRequest> {
|
|
43
|
+
// STATIC
|
|
44
|
+
public static getSocketRequestById(
|
|
45
|
+
smartsocketRef: Smartsocket | SmartsocketClient,
|
|
46
|
+
shortIdArg: string
|
|
47
|
+
): SocketRequest<any> {
|
|
48
|
+
return smartsocketRef.socketRequests.findSync((socketRequestArg) => {
|
|
49
|
+
return socketRequestArg.shortid === shortIdArg;
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// INSTANCE
|
|
54
|
+
public status: TSocketRequestStatus = 'new';
|
|
55
|
+
public side: TSocketRequestSide;
|
|
56
|
+
public shortid: string;
|
|
57
|
+
public originSocketConnection: SocketConnection;
|
|
58
|
+
public funcCallData: ISocketFunctionCallDataRequest<T>;
|
|
59
|
+
public done = plugins.smartpromise.defer<ISocketFunctionCallDataResponse<T>>();
|
|
60
|
+
|
|
61
|
+
public smartsocketRef: Smartsocket | SmartsocketClient;
|
|
62
|
+
|
|
63
|
+
constructor(
|
|
64
|
+
smartsocketRefArg: Smartsocket | SmartsocketClient,
|
|
65
|
+
optionsArg: ISocketRequestConstructorOptions<T>
|
|
66
|
+
) {
|
|
67
|
+
this.smartsocketRef = smartsocketRefArg;
|
|
68
|
+
this.side = optionsArg.side;
|
|
69
|
+
this.shortid = optionsArg.shortId;
|
|
70
|
+
this.funcCallData = optionsArg.funcCallData;
|
|
71
|
+
this.originSocketConnection = optionsArg.originSocketConnection;
|
|
72
|
+
this.smartsocketRef.socketRequests.add(this);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// requesting --------------------------
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* dispatches a socketrequest from the requesting to the receiving side
|
|
79
|
+
*/
|
|
80
|
+
public dispatch(): Promise<ISocketFunctionCallDataResponse<T>> {
|
|
81
|
+
const requestData: ISocketRequestDataObject<T> = {
|
|
82
|
+
funcCallData: this.funcCallData,
|
|
83
|
+
shortId: this.shortid,
|
|
84
|
+
};
|
|
85
|
+
this.originSocketConnection.socket.emit('function', requestData);
|
|
86
|
+
return this.done.promise;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* handles the response that is received by the requesting side
|
|
91
|
+
*/
|
|
92
|
+
public async handleResponse(responseDataArg: ISocketRequestDataObject<T>) {
|
|
93
|
+
// logger.log('info', 'handling response!');
|
|
94
|
+
this.done.resolve(responseDataArg.funcCallData);
|
|
95
|
+
this.smartsocketRef.socketRequests.remove(this);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// responding --------------------------
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* creates the response on the responding side
|
|
102
|
+
*/
|
|
103
|
+
public async createResponse(): Promise<void> {
|
|
104
|
+
const targetSocketFunction: SocketFunction<T> = SocketFunction.getSocketFunctionByName(
|
|
105
|
+
this.smartsocketRef,
|
|
106
|
+
this.funcCallData.funcName
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
if (!targetSocketFunction) {
|
|
110
|
+
logger.log('error', `There is no SocketFunction defined for ${this.funcCallData.funcName}`);
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
// logger.log('info', `invoking ${targetSocketFunction.name}`);
|
|
114
|
+
targetSocketFunction
|
|
115
|
+
.invoke(this.funcCallData, this.originSocketConnection)
|
|
116
|
+
.then((resultData) => {
|
|
117
|
+
// logger.log('info', 'got resultData. Sending it to requesting party.');
|
|
118
|
+
const responseData: ISocketRequestDataObject<T> = {
|
|
119
|
+
funcCallData: resultData,
|
|
120
|
+
shortId: this.shortid,
|
|
121
|
+
};
|
|
122
|
+
this.originSocketConnection.socket.emit('functionResponse', responseData);
|
|
123
|
+
this.smartsocketRef.socketRequests.remove(this);
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import * as plugins from './smartsocket.plugins.js';
|
|
2
|
+
import * as pluginsTyped from './smartsocket.pluginstyped.js';
|
|
3
|
+
|
|
4
|
+
// used in case no other server is supplied
|
|
5
|
+
import { Smartsocket } from './smartsocket.classes.smartsocket.js';
|
|
6
|
+
import { logger } from './smartsocket.logging.js';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* class socketServer
|
|
10
|
+
* handles the attachment of socketIo to whatever server is in play
|
|
11
|
+
*/
|
|
12
|
+
export class SocketServer {
|
|
13
|
+
private smartsocket: Smartsocket;
|
|
14
|
+
private httpServerDeferred: plugins.smartpromise.Deferred<any>;
|
|
15
|
+
private httpServer: pluginsTyped.http.Server | pluginsTyped.https.Server;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* wether httpServer is standalone
|
|
19
|
+
*/
|
|
20
|
+
private standaloneServer = false;
|
|
21
|
+
|
|
22
|
+
constructor(smartSocketInstance: Smartsocket) {
|
|
23
|
+
this.smartsocket = smartSocketInstance;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* starts the server with another server
|
|
28
|
+
* also works with an express style server
|
|
29
|
+
*/
|
|
30
|
+
public async setExternalServer(
|
|
31
|
+
serverType: 'smartexpress',
|
|
32
|
+
serverArg: pluginsTyped.smartexpress.Server
|
|
33
|
+
) {
|
|
34
|
+
this.httpServerDeferred = plugins.smartpromise.defer();
|
|
35
|
+
await serverArg.startedPromise;
|
|
36
|
+
this.httpServer = serverArg.httpServer;
|
|
37
|
+
this.httpServerDeferred.resolve();
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* gets the server for socket.io
|
|
42
|
+
*/
|
|
43
|
+
public async getServerForSocketIo() {
|
|
44
|
+
if (this.httpServerDeferred) {
|
|
45
|
+
await this.httpServerDeferred.promise;
|
|
46
|
+
}
|
|
47
|
+
if (this.httpServer) {
|
|
48
|
+
return this.httpServer;
|
|
49
|
+
} else {
|
|
50
|
+
const httpModule = await this.smartsocket.smartenv.getSafeNodeModule('http');
|
|
51
|
+
this.httpServer = new httpModule.Server();
|
|
52
|
+
this.standaloneServer = true;
|
|
53
|
+
return this.httpServer;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* starts listening to incoming sockets:
|
|
59
|
+
*/
|
|
60
|
+
public async start() {
|
|
61
|
+
const done = plugins.smartpromise.defer();
|
|
62
|
+
|
|
63
|
+
// handle http servers
|
|
64
|
+
// in case an external server has been set "this.standaloneServer" should be false
|
|
65
|
+
if (this.httpServer && this.standaloneServer) {
|
|
66
|
+
if (!this.smartsocket.options.port) {
|
|
67
|
+
logger.log('error', 'there should be a port specifed for smartsocket!');
|
|
68
|
+
throw new Error('there should be a port specified for smartsocket');
|
|
69
|
+
}
|
|
70
|
+
this.httpServer.listen(this.smartsocket.options.port, () => {
|
|
71
|
+
logger.log(
|
|
72
|
+
'success',
|
|
73
|
+
`Server started in standalone mode on ${this.smartsocket.options.port}`
|
|
74
|
+
);
|
|
75
|
+
done.resolve();
|
|
76
|
+
});
|
|
77
|
+
} else {
|
|
78
|
+
done.resolve();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// nothing else to do if express server is set
|
|
82
|
+
await done.promise;
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* closes the server
|
|
88
|
+
*/
|
|
89
|
+
public async stop() {
|
|
90
|
+
if (this.httpServer) {
|
|
91
|
+
this.httpServer.close();
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// apiglobal scope
|
|
2
|
+
import * as typedrequestInterfaces from '@apiglobal/typedrequest-interfaces';
|
|
3
|
+
|
|
4
|
+
export { typedrequestInterfaces };
|
|
5
|
+
|
|
6
|
+
// pushrocks scope
|
|
7
|
+
import * as isohash from '@pushrocks/isohash';
|
|
8
|
+
import * as isounique from '@pushrocks/isounique';
|
|
9
|
+
import * as lik from '@pushrocks/lik';
|
|
10
|
+
import * as smartenv from '@pushrocks/smartenv';
|
|
11
|
+
import * as smartjson from '@pushrocks/smartjson';
|
|
12
|
+
import * as smartlog from '@pushrocks/smartlog';
|
|
13
|
+
import * as smartdelay from '@pushrocks/smartdelay';
|
|
14
|
+
import * as smartpromise from '@pushrocks/smartpromise';
|
|
15
|
+
import * as smarttime from '@pushrocks/smarttime';
|
|
16
|
+
import * as smartrx from '@pushrocks/smartrx';
|
|
17
|
+
|
|
18
|
+
export {
|
|
19
|
+
isohash,
|
|
20
|
+
isounique,
|
|
21
|
+
lik,
|
|
22
|
+
smartenv,
|
|
23
|
+
smartjson,
|
|
24
|
+
smartlog,
|
|
25
|
+
smartdelay,
|
|
26
|
+
smartpromise,
|
|
27
|
+
smarttime,
|
|
28
|
+
smartrx,
|
|
29
|
+
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// node native
|
|
2
|
+
import type * as http from 'http';
|
|
3
|
+
import type * as https from 'https';
|
|
4
|
+
|
|
5
|
+
export { http, https };
|
|
6
|
+
|
|
7
|
+
// pushrocks scope
|
|
8
|
+
import type * as smartexpress from '@pushrocks/smartexpress';
|
|
9
|
+
|
|
10
|
+
export { smartexpress };
|
|
11
|
+
|
|
12
|
+
// third party scope
|
|
13
|
+
import type { Socket as ServerSocket, Server as ServerServer } from 'socket.io';
|
|
14
|
+
import type { Socket as ClientSocket, connect as ClientIo } from 'socket.io-client';
|
|
15
|
+
|
|
16
|
+
export namespace socketIo {
|
|
17
|
+
export type Socket = ServerSocket;
|
|
18
|
+
export type Server = ServerServer;
|
|
19
|
+
}
|
|
20
|
+
export namespace socketIoClient {
|
|
21
|
+
export type Socket = ClientSocket;
|
|
22
|
+
export type connect = typeof ClientIo;
|
|
23
|
+
}
|