oox 0.1.0 → 0.3.0-beta2

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.
Files changed (45) hide show
  1. package/README.md +4 -1
  2. package/app.js +142 -0
  3. package/bin/argv.js +59 -84
  4. package/bin/cli.js +39 -54
  5. package/bin/configurer.js +37 -66
  6. package/bin/proxyer.js +54 -88
  7. package/bin/register.js +45 -95
  8. package/bin/starter.js +70 -129
  9. package/index.js +144 -6
  10. package/index.mjs +4 -0
  11. package/modules/http/index.js +180 -0
  12. package/modules/http/utils.js +73 -0
  13. package/modules/index.js +68 -0
  14. package/modules/module.js +16 -0
  15. package/package.json +34 -16
  16. package/types/app.d.ts +37 -0
  17. package/types/bin/argv.d.ts +8 -0
  18. package/types/bin/cli.d.ts +2 -0
  19. package/types/bin/configurer.d.ts +1 -0
  20. package/types/bin/proxyer.d.ts +1 -0
  21. package/types/bin/register.d.ts +1 -0
  22. package/types/bin/starter.d.ts +1 -0
  23. package/types/index.d.ts +70 -0
  24. package/types/modules/http/index.d.ts +47 -0
  25. package/types/modules/http/utils.d.ts +17 -0
  26. package/types/modules/index.d.ts +21 -0
  27. package/types/modules/module.d.ts +13 -0
  28. package/types/utils.d.ts +6 -0
  29. package/utils.js +63 -0
  30. package/.gitattributes +0 -2
  31. package/global.js +0 -143
  32. package/middleware.js +0 -167
  33. package/rpc/config.class.js +0 -48
  34. package/rpc/context.class.js +0 -15
  35. package/rpc/http.class.js +0 -327
  36. package/rpc/rpc.class.js +0 -128
  37. package/rpc/rpc.interface.class.js +0 -119
  38. package/rpc/socketio.class.js +0 -231
  39. package/service/service.class.js +0 -82
  40. package/service/socketio.class.js +0 -145
  41. package/setMap.class.js +0 -67
  42. package/socketio/client.class.js +0 -190
  43. package/socketio/server.class.js +0 -222
  44. package/socketio/socket.class.js +0 -23
  45. package/util.js +0 -373
@@ -1,222 +0,0 @@
1
-
2
- const { getIPAddress } = require ( '../util' )
3
-
4
- const http = require ( 'http' )
5
-
6
- const SocketIO = require ( 'socket.io' )
7
-
8
- const Socket = require ( './socket.class' )
9
-
10
- const Global = require ( '../global' )
11
-
12
-
13
-
14
- module.exports = class SocketIOServer {
15
-
16
-
17
-
18
- /**
19
- * service name
20
- */
21
- name = ''
22
-
23
-
24
-
25
- /**
26
- * service host ip
27
- */
28
- host = getIPAddress ( 4 ) [ 0 ]
29
-
30
-
31
-
32
- /**
33
- * listen port
34
- */
35
- port = 0
36
-
37
-
38
-
39
- /**
40
- * socket.io service path
41
- */
42
- path = '/socket.io'
43
-
44
-
45
-
46
- /**
47
- * means this.server created by myself<SocketIOServer>
48
- */
49
- #isSelfServer = false
50
-
51
-
52
-
53
- /**
54
- * @type {http.Server}
55
- */
56
- server = null
57
-
58
-
59
-
60
- /**
61
- * @type {SocketIO.Server}
62
- */
63
- socketServer = null
64
-
65
-
66
-
67
- constructor ( name ) {
68
-
69
- this.name = name
70
-
71
- Global.socketIOServers.push ( this )
72
- }
73
-
74
-
75
-
76
- async serve ( ) {
77
-
78
- await this.stop ( )
79
-
80
- const port = this.port
81
-
82
- const isRndPort = 'number' !== typeof port || port === 0
83
-
84
- const isSelfServer = this.#isSelfServer = this.server ? true : false
85
-
86
- const server = this.server = isSelfServer ? this.server :
87
- http.createServer ( ( request, response ) => response.end ( 'No HTTP Gateway' ) )
88
-
89
- if ( !server.listening ) server.listen ( isRndPort ? 0 : port )
90
-
91
- this.port = server.address ( ).port
92
-
93
- this.createSocketIOServer ( )
94
- }
95
-
96
-
97
-
98
- async stop ( ) {
99
-
100
- if ( this.socketServer )
101
- await new Promise ( ( resolve, reject ) =>
102
- this.socketServer.close ( error => error ? reject ( error ) : resolve ( ) ) )
103
-
104
- if ( this.#isSelfServer )
105
- await new Promise ( ( resolve, reject ) => {
106
-
107
- this.server.close ( function ( error ) {
108
-
109
- if ( error ) reject ( error )
110
- else resolve ( )
111
- } )
112
- } )
113
- }
114
-
115
-
116
-
117
- genOptions ( ) {
118
-
119
- return {
120
- /**
121
- * name of the path to capture
122
- * @default "/socket.io"
123
- */
124
- path: this.path,
125
- /**
126
- * how many ms before a client without namespace is closed
127
- * @default 45000
128
- */
129
- connectTimeout: 5000,
130
- /**
131
- * how many ms without a pong packet to consider the connection closed
132
- * @default 5000
133
- */
134
- pingTimeout: 2000,
135
- /**
136
- * how many ms before sending a new ping packet
137
- * @default 25000
138
- */
139
- pingInterval: 10000,
140
- /**
141
- * how many bytes or characters a message can be, before closing the session (to avoid DoS).
142
- * @default 1e5 (100 KB)
143
- */
144
- maxHttpBufferSize: 1e5
145
- }
146
- }
147
-
148
-
149
-
150
- createSocketIOServer ( ) {
151
-
152
- const socketServer = this.socketServer = new SocketIO.Server ( this.server, this.genOptions ( ) )
153
-
154
- socketServer.on ( 'connection', async socket => {
155
-
156
- try {
157
-
158
- await this.onSocketConnection ( socket )
159
- } catch ( error ) {
160
-
161
- socket.send ( error.message ).disconnect ( true )
162
- }
163
- } )
164
- }
165
-
166
-
167
-
168
- /**
169
- * 服务端Socket连接事件
170
- * @param {Socket} socket
171
- */
172
- onSocketConnection ( socket ) {
173
-
174
- const headers = socket.handshake.headers
175
-
176
- const callerId = headers [ 'x-caller-id' ] || socket.id
177
-
178
- // 已经存在相同的连接
179
- if ( Global.sockets.has ( callerId ) ) throw new Error ( 'Connection Exists' )
180
-
181
- // client ip or caller service ip
182
- const ip = headers [ 'x-real-ip' ] || headers [ 'x-ip' ] || socket.handshake.address
183
-
184
- // service name
185
- const caller = headers [ 'x-caller' ] || 'anonymous'
186
-
187
- socket.data = { connected: true, host: ip, name: caller, id: callerId, owner: this.name }
188
-
189
- // 保存 callerId 与 socket 对应关系
190
- Global.sockets.set ( callerId, socket )
191
-
192
- socket.on ( 'disconnect', reason => this.onSocketDisconnect ( socket, new Error ( `SocketIO name[${caller}] id[${callerId}] ${reason}` ) ) )
193
-
194
- socket.emit ( 'oox_connected', { name: this.name } )
195
-
196
- this.onConnection ( socket )
197
- }
198
-
199
-
200
-
201
- onConnection ( socket ) { }
202
-
203
-
204
-
205
- /**
206
- * 服务端Socket断开事件
207
- * @param {Socket} socket
208
- * @param {Error} reason
209
- */
210
- onSocketDisconnect ( socket, reason ) {
211
-
212
- socket.data.connected = false
213
-
214
- Global.sockets.delete ( socket.data.id )
215
-
216
- this.onDisconnect ( socket, reason )
217
- }
218
-
219
-
220
-
221
- onDisconnect ( socket, reason ) { }
222
- }
@@ -1,23 +0,0 @@
1
-
2
- const SocketIO = require ( 'socket.io' )
3
-
4
- module.exports = class Socket extends SocketIO.Socket {
5
-
6
-
7
-
8
- static Data = {
9
- connected: false,
10
- host: '',
11
- name: '',
12
- id: '',
13
- owner: ''
14
- }
15
-
16
-
17
-
18
- /**
19
- * Socket 扩展连接信息
20
- * @type {Socket.Data}
21
- */
22
- data = Object.assign ( { }, Socket.Data )
23
- }
package/util.js DELETED
@@ -1,373 +0,0 @@
1
-
2
- const os = require ( 'os' )
3
-
4
- const http = require ( 'http' )
5
-
6
- const https = require ( 'https' )
7
-
8
- const querystring = require('querystring')
9
-
10
- const Context = require ( './rpc/context.class' )
11
-
12
- const Middleware = require ( './middleware' )
13
-
14
-
15
-
16
- exports.getIPAddress = function ( version = 4 ) {
17
-
18
- const interfaces = os.networkInterfaces ( )
19
-
20
- const ip = [ ]
21
-
22
- for ( const name of Object.keys ( interfaces ) )
23
- for ( const intf of interfaces [ name ] )
24
- if ( intf.mac !== '00:00:00:00:00:00' )
25
- if ( ( version !== 4 && version !== 6 ) || 'IPv' + version === intf.family )
26
- ip.push ( intf.address )
27
-
28
- if ( !ip.length ) {
29
- if ( version !== 6 ) ip.push ( '127.0.0.1' )
30
- if ( version !== 4 ) ip.push ( '::1' )
31
- }
32
-
33
- return ip
34
- }
35
-
36
-
37
-
38
- /**
39
- * String => Buffer
40
- * @param {*} stream
41
- * @param {*} totalLength
42
- * @returns {Promise<Buffer>}
43
- */
44
- exports.stream2buffer = function ( stream, totalLength=0 ) {
45
-
46
- return new Promise ( function ( resolve, reject ) {
47
-
48
- let buffers = [ ]
49
-
50
- stream.on ( 'error', reject )
51
-
52
- if ( totalLength ) {
53
-
54
- stream.on ( 'data', function ( data ) { buffers.push ( data ) } )
55
- } else {
56
-
57
- stream.on ( 'data', function ( data ) {
58
- buffers.push ( data )
59
- totalLength += data.length
60
- } )
61
- }
62
-
63
- stream.on ( 'end', function ( ) { resolve ( Buffer.concat ( buffers, totalLength ) ) } )
64
- } )
65
- }
66
-
67
-
68
-
69
- /**
70
- * Request => JSONObject
71
- * @param {http.IncomingMessage} request
72
- */
73
- exports.parseHTTPBody = async function ( request ) {
74
-
75
- if ( request.method === 'GET' ) return null
76
-
77
- let contentType = request.headers [ 'content-type' ]
78
-
79
- // application/json; charset=utf-8
80
- if ( contentType ) contentType = contentType.split ( ';' ) [ 0 ].trim ( )
81
-
82
- const contentSize = request.headers [ 'content-length' ]
83
-
84
- const buffer = await exports.stream2buffer ( request, +contentSize || 0 )
85
-
86
- if ( contentSize && buffer.length !== +contentSize ) throw new Error ( 'Content-Length Incorrect' )
87
-
88
- const bodyString = buffer.toString ( )
89
-
90
- /*
91
- if ( 'application/x-www-form-urlencoded' === contentType )
92
- return querystring.parse ( bodyString )
93
- */
94
-
95
- try {
96
-
97
- return JSON.parse ( bodyString )
98
- } catch ( error ) {
99
-
100
- return bodyString
101
- }
102
- }
103
-
104
-
105
-
106
- /**
107
- * http request
108
- * @param {URL|String|http.RequestOptions} url
109
- * @param {http.RequestOptions|String} options
110
- * @param {String} body
111
- */
112
- exports.httpRequest = function ( url, options, body ) {
113
-
114
- if ( 'string' === typeof options ) {
115
-
116
- body = options
117
- options = { }
118
- }
119
-
120
- return new Promise ( function ( resolve, reject ) {
121
-
122
- const request = http.request ( url, options, async function ( response ) {
123
-
124
- try {
125
-
126
- const result = await exports.parseHTTPBody ( response )
127
-
128
- resolve ( result )
129
- } catch ( error ) {
130
-
131
- const decoration = new Error ( `${response.statusCode} - ${error.message}` )
132
-
133
- reject ( decoration )
134
- }
135
- } )
136
-
137
- request.on ( 'error', reject )
138
-
139
- if ( body ) {
140
-
141
- request.method = 'POST'
142
-
143
- request.setHeader ( 'Content-Type', 'application/json' )
144
-
145
- request.setHeader ( 'Content-Length', Buffer.byteLength ( body ) )
146
-
147
- request.write ( body )
148
- }
149
-
150
- request.end ( )
151
- } )
152
- }
153
-
154
-
155
-
156
- exports.getAllCallablePropertyNames = function ( obj ) {
157
-
158
- if ( !obj ) return [ ]
159
-
160
- let props = [ ], tmpProps = [ ], index = 0, size = 0, tmpProp = ''
161
-
162
- const bans = [ "constructor", "__defineGetter__", "__defineSetter__"
163
- , "hasOwnProperty", "__lookupGetter__", "__lookupSetter__"
164
- , "isPrototypeOf", "propertyIsEnumerable", "toString"
165
- , "valueOf", "__proto__", "toLocaleString" ]
166
-
167
- do {
168
-
169
- tmpProps = Object.getOwnPropertyNames ( obj )
170
-
171
- index = -1, size = tmpProps.length
172
-
173
- while ( ++index < size ) {
174
-
175
- tmpProp = tmpProps [ index ]
176
-
177
- if ( !props.includes ( tmpProp ) && !bans.includes ( tmpProp ) ) {
178
-
179
- props.push ( tmpProp )
180
- }
181
- }
182
-
183
- } while ( obj = Object.getPrototypeOf ( obj ) )
184
-
185
- return props
186
- }
187
-
188
-
189
-
190
- /**
191
- *
192
- * @param {Object} methods
193
- * @param {Map<String,Function>} kvMethods
194
- * @param {Array<String>} nameStack
195
- */
196
- exports.genKVMethods = function ( methods, kvMethods=new Map(), nameStack=[] ) {
197
-
198
- let keys = exports.getAllCallablePropertyNames ( methods )
199
-
200
- let index = -1, size = keys.length
201
-
202
- while ( ++index < size ) {
203
-
204
- let key = keys [ index ]
205
-
206
- /**
207
- * @type {Function}
208
- */
209
- let val = methods [ key ]
210
-
211
- if ( 'function' === typeof val ) {
212
-
213
- const action = nameStack.concat ( key ).join ( '.' )
214
-
215
- // 中間件函數脫殼綁定
216
- Middleware.wrappedActions.set ( action, val )
217
-
218
- kvMethods.set ( action, val.bind ( methods ) )
219
- } else {
220
-
221
- exports.genKVMethods ( val, kvMethods, nameStack.concat ( key ) )
222
- }
223
- }
224
-
225
- return kvMethods
226
- }
227
-
228
-
229
-
230
- /**
231
- * parse traceId from execution stack
232
- * @param {String} stack
233
- * @returns {String}
234
- */
235
- exports.getTraceIdByStack = function ( stack ) {
236
-
237
- if ( !stack ) {
238
-
239
- let trace = { }
240
-
241
- Error.captureStackTrace ( trace )
242
-
243
- stack = trace.stack
244
- }
245
-
246
- const prefix = 'OOXTrace.<computed>'
247
-
248
- const index = stack.indexOf ( prefix )
249
-
250
- if ( index === -1 ) return null
251
-
252
- return stack.slice ( index ).match ( /(?<=as\s).*?(?=\s|\])/ ) [ 0 ]
253
- }
254
-
255
-
256
-
257
- /**
258
- *
259
- * @param {String} traceId 全局唯一请求ID
260
- * @param {Map<String,Function>} methods 服务函数扁平化列表
261
- */
262
- exports.genOOXTrace = function ( traceId, methods ) {
263
-
264
- const OOXTrace = { /* OOXTrace.<computed> [as traceId] */ }
265
-
266
-
267
-
268
- /**
269
- * trace magic function
270
- * @param {String} action
271
- * @param {Array} params
272
- * @param {Context} context
273
- */
274
- OOXTrace [ traceId ] = async function ( action, params, context ) {
275
-
276
- const __proxy = '__proxy', _proxy = '_proxy'
277
-
278
-
279
-
280
- // 目标函数
281
- const target = methods.get ( action )
282
-
283
- // 目标代理函数
284
- const targetProxy = methods.get ( action + _proxy )
285
-
286
- // 即不存在目标也不存在目标代理时, 报错函数不存在
287
- if ( !target && !targetProxy ) throw new Error ( 'Invalid Action [' + action + ']' )
288
-
289
-
290
-
291
- // 最顶层代理
292
- const topProxy = methods.get ( __proxy )
293
-
294
- if ( topProxy ) {
295
-
296
- const proxyReturns = await topProxy ( action, params, context )
297
-
298
- if ( proxyReturns !== undefined ) return proxyReturns
299
- }
300
-
301
-
302
-
303
- // 'x.y.z' => [ 'x', 'y', 'z' ]
304
- const nameStack = action.split ( '.' ), size = nameStack.length - 1
305
-
306
- let index = -1, proxyPrefix = ''
307
-
308
-
309
-
310
- // 根代理遍历
311
- while ( ++index < size ) {
312
-
313
- // x.
314
- // x.y.
315
- proxyPrefix += nameStack [ index ] + '.'
316
-
317
- // x.__proxy
318
- // x.y.__proxy
319
- const rootProxy = methods.get ( proxyPrefix + __proxy )
320
-
321
- // x.__proxy ( 'y.z', ... )
322
- // x.y.__proxy ( 'z', ... )
323
- if ( rootProxy ) {
324
-
325
- const proxyReturns = await rootProxy ( nameStack.slice ( index ).join ( '.' ), params, context )
326
-
327
- if ( proxyReturns !== undefined ) return proxyReturns
328
- }
329
- }
330
-
331
-
332
-
333
- // 同级代理
334
- const layerProxy = methods.get ( proxyPrefix + _proxy )
335
-
336
- if ( layerProxy ) {
337
-
338
- const proxyReturns = await layerProxy ( nameStack [ index ], params, context )
339
-
340
- if ( proxyReturns !== undefined ) return proxyReturns
341
- }
342
-
343
-
344
-
345
- if ( targetProxy ) {
346
-
347
- const proxyReturns = await targetProxy ( params, context )
348
-
349
- if ( proxyReturns !== undefined ) return proxyReturns
350
- }
351
-
352
-
353
-
354
- // make sure target action execute after all proxies
355
- if ( target ) {
356
-
357
- const sourceMethod = Middleware.wrappedActions.get ( action )
358
-
359
- const middlewareNames = Middleware.actionMiddlewares.get ( sourceMethod )
360
-
361
- if ( middlewareNames && middlewareNames.length ) for ( const name of middlewareNames ) {
362
-
363
- const middleware = Middleware.middlewares.get ( name )
364
-
365
- await middleware ( action, params, context )
366
- }
367
-
368
- return await target ( ...params )
369
- }
370
- }
371
-
372
- return OOXTrace
373
- }