oox 0.0.7 → 0.2.0

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/util.js CHANGED
@@ -1,352 +1,224 @@
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
-
13
-
14
- exports.getIPAddress = function ( version = 4 ) {
15
-
16
- const interfaces = os.networkInterfaces ( )
17
-
18
- const ip = [ ]
19
-
20
- for ( const name of Object.keys ( interfaces ) )
21
- for ( const intf of interfaces [ name ] )
22
- if ( intf.mac !== '00:00:00:00:00:00' )
23
- if ( ( version !== 4 && version !== 6 ) || 'IPv' + version === intf.family )
24
- ip.push ( intf.address )
25
-
26
- if ( !ip.length ) {
27
- if ( version !== 6 ) ip.push ( '127.0.0.1' )
28
- if ( version !== 4 ) ip.push ( '::1' )
29
- }
30
-
31
- return ip
32
- }
33
-
34
-
35
-
36
- /**
37
- * String => Buffer
38
- * @param {*} stream
39
- * @param {*} totalLength
40
- * @returns {Promise<Buffer>}
41
- */
42
- exports.stream2buffer = function ( stream, totalLength=0 ) {
43
-
44
- return new Promise ( function ( resolve, reject ) {
45
-
46
- let buffers = [ ]
47
-
48
- stream.on ( 'error', reject )
49
-
50
- if ( totalLength ) {
51
-
52
- stream.on ( 'data', function ( data ) { buffers.push ( data ) } )
53
- } else {
54
-
55
- stream.on ( 'data', function ( data ) {
56
- buffers.push ( data )
57
- totalLength += data.length
58
- } )
59
- }
60
-
61
- stream.on ( 'end', function ( ) { resolve ( Buffer.concat ( buffers, totalLength ) ) } )
62
- } )
63
- }
64
-
65
-
66
-
67
- /**
68
- * Request => JSONObject
69
- * @param {http.IncomingMessage} request
70
- */
71
- exports.parseHTTPBody = async function ( request ) {
72
-
73
- if ( request.method === 'GET' ) return null
74
-
75
- let contentType = request.headers [ 'content-type' ]
76
-
77
- // application/json; charset=utf-8
78
- if ( contentType ) contentType = contentType.split ( ';' ) [ 0 ].trim ( )
79
-
80
- const contentSize = request.headers [ 'content-length' ]
81
-
82
- const buffer = await exports.stream2buffer ( request, +contentSize || 0 )
83
-
84
- if ( contentSize && buffer.length !== +contentSize ) throw new Error ( 'Content-Length Incorrect' )
85
-
86
- const bodyString = buffer.toString ( )
87
-
88
- /*
89
- if ( 'application/x-www-form-urlencoded' === contentType )
90
- return querystring.parse ( bodyString )
91
- */
92
-
93
- try {
94
-
95
- return JSON.parse ( bodyString )
96
- } catch ( error ) {
97
-
98
- return bodyString
99
- }
100
- }
101
-
102
-
103
-
104
- /**
105
- * http request
106
- * @param {URL|String|http.RequestOptions} url
107
- * @param {http.RequestOptions|String} options
108
- * @param {String} body
109
- */
110
- exports.httpRequest = function ( url, options, body ) {
111
-
112
- if ( 'string' === typeof options ) {
113
-
114
- body = options
115
- options = { }
116
- }
117
-
118
- return new Promise ( function ( resolve, reject ) {
119
-
120
- const request = http.request ( url, options, async function ( response ) {
121
-
122
- try {
123
-
124
- const result = await exports.parseHTTPBody ( response )
125
-
126
- resolve ( result )
127
- } catch ( error ) {
128
-
129
- const decoration = new Error ( `${response.statusCode} - ${error.message}` )
130
-
131
- reject ( decoration )
132
- }
133
- } )
134
-
135
- request.on ( 'error', reject )
136
-
137
- if ( body ) {
138
-
139
- request.method = 'POST'
140
-
141
- request.setHeader ( 'Content-Type', 'application/json' )
142
-
143
- request.setHeader ( 'Content-Length', Buffer.byteLength ( body ) )
144
-
145
- request.write ( body )
146
- }
147
-
148
- request.end ( )
149
- } )
150
- }
151
-
152
-
153
-
154
- exports.getAllCallablePropertyNames = function ( obj ) {
155
-
156
- if ( !obj ) return [ ]
157
-
158
- let props = [ ], tmpProps = [ ], index = 0, size = 0, tmpProp = ''
159
-
160
- const bans = [ "constructor", "__defineGetter__", "__defineSetter__"
161
- , "hasOwnProperty", "__lookupGetter__", "__lookupSetter__"
162
- , "isPrototypeOf", "propertyIsEnumerable", "toString"
163
- , "valueOf", "__proto__", "toLocaleString" ]
164
-
165
- do {
166
-
167
- tmpProps = Object.getOwnPropertyNames ( obj )
168
-
169
- index = -1, size = tmpProps.length
170
-
171
- while ( ++index < size ) {
172
-
173
- tmpProp = tmpProps [ index ]
174
-
175
- if ( !props.includes ( tmpProp ) && !bans.includes ( tmpProp ) ) {
176
-
177
- props.push ( tmpProp )
178
- }
179
- }
180
-
181
- } while ( obj = Object.getPrototypeOf ( obj ) )
182
-
183
- return props
184
- }
185
-
186
-
187
-
188
- /**
189
- *
190
- * @param {Object} methods
191
- * @param {Map<String,Function>} kvMethods
192
- * @param {Array<String>} nameStack
193
- */
194
- exports.genKVMethods = function ( methods, kvMethods=new Map(), nameStack=[] ) {
195
-
196
- let keys = exports.getAllCallablePropertyNames ( methods )
197
-
198
- let index = -1, size = keys.length
199
-
200
- while ( ++index < size ) {
201
-
202
- let key = keys [ index ]
203
-
204
- /**
205
- * @type {Function}
206
- */
207
- let val = methods [ key ]
208
-
209
- if ( 'function' === typeof val ) {
210
-
211
- kvMethods.set ( nameStack.concat ( key ).join ( '.' ), val.bind ( methods ) )
212
- } else {
213
-
214
- exports.genKVMethods ( val, kvMethods, nameStack.concat ( key ) )
215
- }
216
- }
217
-
218
- return kvMethods
219
- }
220
-
221
-
222
-
223
- /**
224
- * parse traceId from execution stack
225
- * @param {String} stack
226
- * @returns {String}
227
- */
228
- exports.getTraceIdByStack = function ( stack ) {
229
-
230
- if ( !stack ) {
231
-
232
- let trace = { }
233
-
234
- Error.captureStackTrace ( trace )
235
-
236
- stack = trace.stack
237
- }
238
-
239
- const prefix = 'OOXTrace.<computed>'
240
-
241
- const index = stack.indexOf ( prefix )
242
-
243
- if ( index === -1 ) return null
244
-
245
- return stack.slice ( index ).match ( /(?<=as\s).*?(?=\s|\])/ ) [ 0 ]
246
- }
247
-
248
-
249
-
250
- /**
251
- *
252
- * @param {String} traceId 全局唯一请求ID
253
- * @param {Map<String,Function>} methods 服务函数扁平化列表
254
- */
255
- exports.genOOXTrace = function ( traceId, methods ) {
256
-
257
- const OOXTrace = { /* OOXTrace.<computed> [as traceId] */ }
258
-
259
-
260
-
261
- /**
262
- * trace magic function
263
- * @param {String} action
264
- * @param {Array} params
265
- * @param {Context} context
266
- */
267
- OOXTrace [ traceId ] = async function ( action, params, context ) {
268
-
269
- const __proxy = '__proxy', _proxy = '_proxy'
270
-
271
-
272
-
273
- // 目标函数
274
- const target = methods.get ( action )
275
-
276
- // 目标代理函数
277
- const targetProxy = methods.get ( action + _proxy )
278
-
279
- // 即不存在目标也不存在目标代理时, 报错函数不存在
280
- if ( !target && !targetProxy ) throw new Error ( 'Invalid Action [' + action + ']' )
281
-
282
-
283
-
284
- // 最顶层代理
285
- const topProxy = methods.get ( __proxy )
286
-
287
- if ( topProxy ) {
288
-
289
- const proxyReturns = await topProxy ( action, params, context )
290
-
291
- if ( proxyReturns !== undefined ) return proxyReturns
292
- }
293
-
294
-
295
-
296
- // 'x.y.z' => [ 'x', 'y', 'z' ]
297
- const nameStack = action.split ( '.' ), size = nameStack.length - 1
298
-
299
- let index = -1, proxyPrefix = ''
300
-
301
-
302
-
303
- // 根代理遍历
304
- while ( ++index < size ) {
305
-
306
- // x.
307
- // x.y.
308
- proxyPrefix += nameStack [ index ] + '.'
309
-
310
- // x.__proxy
311
- // x.y.__proxy
312
- const rootProxy = methods.get ( proxyPrefix + __proxy )
313
-
314
- // x.__proxy ( 'y.z', ... )
315
- // x.y.__proxy ( 'z', ... )
316
- if ( rootProxy ) {
317
-
318
- const proxyReturns = await rootProxy ( nameStack.slice ( index ).join ( '.' ), params, context )
319
-
320
- if ( proxyReturns !== undefined ) return proxyReturns
321
- }
322
- }
323
-
324
-
325
-
326
- // 同级代理
327
- const layerProxy = methods.get ( proxyPrefix + _proxy )
328
-
329
- if ( layerProxy ) {
330
-
331
- const proxyReturns = await layerProxy ( nameStack [ index ], params, context )
332
-
333
- if ( proxyReturns !== undefined ) return proxyReturns
334
- }
335
-
336
-
337
-
338
- if ( targetProxy ) {
339
-
340
- const proxyReturns = await targetProxy ( params, context )
341
-
342
- if ( proxyReturns !== undefined ) return proxyReturns
343
- }
344
-
345
-
346
-
347
- // make sure target action execute after all proxies
348
- if ( target ) return await target ( ...params )
349
- }
350
-
351
- return OOXTrace
352
- }
1
+
2
+ const os = require ( 'os' )
3
+
4
+ const http = require ( 'http' )
5
+
6
+ const https = require ( 'https' )
7
+
8
+ const Context = require ( './rpc/context.class' )
9
+
10
+ const Middleware = require ( './middleware' )
11
+
12
+
13
+
14
+ exports.getIPAddress = function ( version = 4 ) {
15
+
16
+ const interfaces = os.networkInterfaces ( )
17
+
18
+ const ip = [ ]
19
+
20
+ for ( const name of Object.keys ( interfaces ) )
21
+ for ( const intf of interfaces [ name ] )
22
+ if ( intf.mac !== '00:00:00:00:00:00' )
23
+ if ( ( version !== 4 && version !== 6 ) || 'IPv' + version === intf.family )
24
+ ip.push ( intf.address )
25
+
26
+ if ( !ip.length ) {
27
+ if ( version !== 6 ) ip.push ( '127.0.0.1' )
28
+ if ( version !== 4 ) ip.push ( '::1' )
29
+ }
30
+
31
+ return ip
32
+ }
33
+
34
+
35
+
36
+ /**
37
+ * String => Buffer
38
+ * @param {*} stream
39
+ * @param {*} totalLength
40
+ * @returns {Promise<Buffer>}
41
+ */
42
+ exports.stream2buffer = function ( stream, totalLength=0 ) {
43
+
44
+ return new Promise ( function ( resolve, reject ) {
45
+
46
+ let buffers = [ ]
47
+
48
+ stream.on ( 'error', reject )
49
+
50
+ if ( totalLength ) {
51
+
52
+ stream.on ( 'data', function ( data ) { buffers.push ( data ) } )
53
+ } else {
54
+
55
+ stream.on ( 'data', function ( data ) {
56
+ buffers.push ( data )
57
+ totalLength += data.length
58
+ } )
59
+ }
60
+
61
+ stream.on ( 'end', function ( ) { resolve ( Buffer.concat ( buffers, totalLength ) ) } )
62
+ } )
63
+ }
64
+
65
+
66
+
67
+ /**
68
+ * Request => JSONObject
69
+ * @param {http.IncomingMessage} request
70
+ */
71
+ exports.parseHTTPBody = async function ( request ) {
72
+
73
+ if ( request.method === 'GET' ) return null
74
+
75
+ let contentType = request.headers [ 'content-type' ]
76
+
77
+ // application/json; charset=utf-8
78
+ if ( contentType ) contentType = contentType.split ( ';' ) [ 0 ].trim ( )
79
+
80
+ const contentSize = request.headers [ 'content-length' ]
81
+
82
+ const buffer = await exports.stream2buffer ( request, +contentSize || 0 )
83
+
84
+ if ( contentSize && buffer.length !== +contentSize ) throw new Error ( 'Content-Length Incorrect' )
85
+
86
+ const bodyString = buffer.toString ( )
87
+
88
+ /*
89
+ if ( 'application/x-www-form-urlencoded' === contentType )
90
+ return querystring.parse ( bodyString )
91
+ */
92
+
93
+ try {
94
+
95
+ return JSON.parse ( bodyString )
96
+ } catch ( error ) {
97
+
98
+ return bodyString
99
+ }
100
+ }
101
+
102
+
103
+
104
+ /**
105
+ * http request
106
+ * @param {URL|String|http.RequestOptions} url
107
+ * @param {http.RequestOptions|String} options
108
+ * @param {String} body
109
+ */
110
+ exports.httpRequest = function ( url, options, body ) {
111
+
112
+ if ( 'string' === typeof options ) {
113
+
114
+ body = options
115
+ options = { }
116
+ }
117
+
118
+ return new Promise ( function ( resolve, reject ) {
119
+
120
+ const request = http.request ( url, options, async function ( response ) {
121
+
122
+ try {
123
+
124
+ const result = await exports.parseHTTPBody ( response )
125
+
126
+ resolve ( result )
127
+ } catch ( error ) {
128
+
129
+ const decoration = new Error ( `${response.statusCode} - ${error.message}` )
130
+
131
+ reject ( decoration )
132
+ }
133
+ } )
134
+
135
+ request.on ( 'error', reject )
136
+
137
+ if ( body ) {
138
+
139
+ request.method = 'POST'
140
+
141
+ request.setHeader ( 'Content-Type', 'application/json' )
142
+
143
+ request.setHeader ( 'Content-Length', Buffer.byteLength ( body ) )
144
+
145
+ request.write ( body )
146
+ }
147
+
148
+ request.end ( )
149
+ } )
150
+ }
151
+
152
+
153
+
154
+ exports.getAllCallablePropertyNames = function ( obj ) {
155
+
156
+ if ( !obj ) return [ ]
157
+
158
+ let props = [ ], tmpProps = [ ], index = 0, size = 0, tmpProp = ''
159
+
160
+ const bans = [ "constructor", "__defineGetter__", "__defineSetter__"
161
+ , "hasOwnProperty", "__lookupGetter__", "__lookupSetter__"
162
+ , "isPrototypeOf", "propertyIsEnumerable", "toString"
163
+ , "valueOf", "__proto__", "toLocaleString" ]
164
+
165
+ do {
166
+
167
+ tmpProps = Object.getOwnPropertyNames ( obj )
168
+
169
+ index = -1, size = tmpProps.length
170
+
171
+ while ( ++index < size ) {
172
+
173
+ tmpProp = tmpProps [ index ]
174
+
175
+ if ( !props.includes ( tmpProp ) && !bans.includes ( tmpProp ) ) {
176
+
177
+ props.push ( tmpProp )
178
+ }
179
+ }
180
+
181
+ } while ( obj = Object.getPrototypeOf ( obj ) )
182
+
183
+ return props
184
+ }
185
+
186
+
187
+
188
+ /**
189
+ *
190
+ * @param {Object} methods
191
+ * @param {Map<String,Function>} kvMethods
192
+ * @param {Array<String>} nameStack
193
+ */
194
+ exports.genKVMethods = function ( methods, kvMethods=new Map(), nameStack=[] ) {
195
+
196
+ let keys = exports.getAllCallablePropertyNames ( methods )
197
+
198
+ let index = -1, size = keys.length
199
+
200
+ while ( ++index < size ) {
201
+
202
+ let key = keys [ index ]
203
+
204
+ /**
205
+ * @type {Function}
206
+ */
207
+ let val = methods [ key ]
208
+
209
+ if ( 'function' === typeof val ) {
210
+
211
+ const action = nameStack.concat ( key ).join ( '.' )
212
+
213
+ // 中間件函數脫殼綁定
214
+ Middleware.wrappedActions.set ( action, val )
215
+
216
+ kvMethods.set ( action, val.bind ( methods ) )
217
+ } else {
218
+
219
+ exports.genKVMethods ( val, kvMethods, nameStack.concat ( key ) )
220
+ }
221
+ }
222
+
223
+ return kvMethods
224
+ }
package/global.class.js DELETED
@@ -1,124 +0,0 @@
1
-
2
- const { getTraceIdByStack } = require ( './util' )
3
-
4
- const Context = require ( './rpc/context.class' )
5
-
6
- const RPC = require ( './rpc/rpc.interface.class' )
7
-
8
- const Socket = require ( './socketio/socket.class' )
9
-
10
- const SetMap = require ( './setMap.class' )
11
-
12
-
13
-
14
- module.exports = class Global {
15
-
16
-
17
-
18
- /**
19
- * @type {[RPC]}
20
- */
21
- instances = [ ]
22
-
23
-
24
-
25
- /**
26
- * all contexts map
27
- * @type {Map<String,Context>}
28
- */
29
- contexts = new Map ( )
30
-
31
-
32
-
33
- /**
34
- * @type {Map<String,Socket>}
35
- */
36
- sockets = new Map ( )
37
-
38
-
39
-
40
- /**
41
- * @type {SocketIOServer[]}
42
- */
43
- socketIOServers = [ ]
44
-
45
-
46
-
47
- /**
48
- * @type {Map<String,Set<Socket>>}
49
- */
50
- socketIORegistry = new SetMap
51
-
52
-
53
-
54
- /**
55
- * 生成随机不重复id
56
- * @returns {String}
57
- */
58
- genTraceId ( ) {
59
-
60
- const uid = [
61
- Math.floor ( Date.now ( ) / 1000 ).toString ( 16 ),
62
- Math.floor ( Math.random ( ) * 0xffffffff ).toString ( 16 ).padStart ( 8, '0' )
63
- ]
64
-
65
- return uid.join ( '' )
66
- }
67
-
68
-
69
-
70
- /**
71
- * 获取链路跟踪上下文
72
- * @param {Context} param0
73
- */
74
- genContext ( { caller, callerId, traceId, ip, sourceIP } = { } ) {
75
-
76
- const context = new Context ( )
77
-
78
- if ( caller ) {
79
-
80
- context.caller = caller
81
- } else {
82
-
83
- const primaryService = this.instances [ 0 ]
84
-
85
- if ( primaryService ) context.caller = primaryService.name
86
- }
87
-
88
- context.traceId = traceId || this.genTraceId ( )
89
- context.ip = ip
90
- context.sourceIP = sourceIP || ip
91
- context.callerId = callerId
92
-
93
- return context
94
- }
95
-
96
-
97
-
98
- genContextByStack ( stack ) {
99
-
100
- if ( !stack ) {
101
-
102
- let trace = { }
103
-
104
- Error.captureStackTrace ( trace )
105
-
106
- stack = trace.stack
107
- }
108
-
109
- const traceId = getTraceIdByStack ( stack )
110
-
111
- if ( traceId ) {
112
-
113
- const sourceContext = this.contexts.get ( traceId )
114
-
115
- if ( sourceContext ) {
116
-
117
- return this.genContext ( { traceId, sourceIP: sourceContext.sourceIP } )
118
- } else {
119
-
120
- return this.genContext ( { traceId } )
121
- }
122
- } else return this.genContext ( )
123
- }
124
- }