iosignal 4.6.1 → 4.8.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.
@@ -460,7 +460,7 @@ export class IOCore extends EventEmitter {
460
460
 
461
461
  // **IMPORTANT** change state before subscribe.
462
462
  this.stateChange('ready', 'cid_ready')
463
- this.subscribe_memory_channels() // tags registered by listen() or link().
463
+ this.subscribe_channels()
464
464
  break;
465
465
 
466
466
  case IOMsg.QUOTA_LEVEL:
@@ -732,6 +732,7 @@ export class IOCore extends EventEmitter {
732
732
  console.log('## your maximum signalSize(bytes) is:', this.quota.signalSize)
733
733
  return
734
734
  }
735
+ // console.log(`C->[${IOMsg[ data[0]]}]`)
735
736
  this.socket_send(data);
736
737
  }
737
738
 
@@ -900,7 +901,7 @@ export class IOCore extends EventEmitter {
900
901
  if (!storeName || args.length == 0) {
901
902
  return Promise.reject(new Error('set need storeName and value)'))
902
903
  }
903
- return this.req('store', 'set', storeName, ...args)
904
+ return this.call('store', 'set', storeName, ...args)
904
905
  }
905
906
 
906
907
  /**
@@ -912,26 +913,26 @@ export class IOCore extends EventEmitter {
912
913
  if (!storeName) {
913
914
  return Promise.reject(new Error('store get need storeName)'))
914
915
  }
915
- let pack = await this.req('store', 'get', storeName)
916
+ let pack = await this.call('store', 'get', storeName)
916
917
  let { $ } = MBP.unpack(pack.body)
917
918
  return $
918
919
  }
919
920
 
920
921
 
921
922
  /**
922
- * Sends a request to a target and topic.(remote api call)
923
- * @param {string} target - The target(api name) of the request.
924
- * @param {string} topic - The topic(api function name) of the request.
923
+ * Sends a request to a target and topic.(remote service call)
924
+ * @param {string} target - The target(service name) of the request.
925
+ * @param {string} topic - The topic(service function name) of the request.
925
926
  * @param {...any} args - Optional arguments for the request.
926
927
  * @returns {Promise<any>}
927
928
  */
928
- req(target, topic, ...args) {
929
+ call(target, topic, ...args) {
929
930
  if (!target || !topic)
930
931
  return Promise.reject(new Error('request need target and topic)'))
931
932
  let sigPack;
932
933
  if (args.length > 0) {
933
934
  sigPack = MBP.pack(
934
- MBP.MB('#MsgType', '8', IOMsg.REQUEST),
935
+ MBP.MB('#MsgType', '8', IOMsg.CALL),
935
936
  MBP.MB('mid', '16', ++this.mid),
936
937
  MBP.MB('target', target),
937
938
  MBP.MB('topic', topic),
@@ -939,7 +940,7 @@ export class IOCore extends EventEmitter {
939
940
  )
940
941
  } else {
941
942
  sigPack = MBP.pack(
942
- MBP.MB('#MsgType', '8', IOMsg.REQUEST),
943
+ MBP.MB('#MsgType', '8', IOMsg.CALL),
943
944
  MBP.MB('mid', '16', ++this.mid),
944
945
  MBP.MB('target', target),
945
946
  MBP.MB('topic', topic)
@@ -958,14 +959,6 @@ export class IOCore extends EventEmitter {
958
959
  subscribe(tag) {
959
960
  if (typeof tag !== 'string') throw TypeError('tag should be string.')
960
961
  if (tag.length > SIZE_LIMIT.TAG_LEN1) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN1)
961
- if (this.state !== STATE.READY) return
962
-
963
- // subscribe 사용시, 사용 'ready' 이벤트시 메뉴얼 등록되므로 여기에 등록하면 2중 호출된다.
964
- // 즉, channels 등록은 listen 같은 자동화 구독시만 사용.
965
- // let tagList = tag.split(',')
966
- // tagList.forEach(tag => {
967
- // this.channels.add(tag)
968
- // })
969
962
 
970
963
  try {
971
964
  let tagEncoded = encoder.encode(tag)
@@ -975,47 +968,27 @@ export class IOCore extends EventEmitter {
975
968
  MBP.NB('8', tagEncoded.byteLength),
976
969
  tagEncoded]))
977
970
  } catch (error) { }
971
+
978
972
  }
979
973
 
974
+
980
975
  /**
981
- * Subscribes to a channel or channels with a promise.
982
- * @param {string} tag - The tag(s) of the channel(s) to subscribe to (comma-separated).
983
- * @returns {Promise<any>}
984
- * @throws {TypeError} If tag is not a string or exceeds length limit.
976
+ * Subscribes stored channels.
977
+ * called client state become 'ready'
985
978
  */
986
- subscribe_promise(tag) {
987
- if (typeof tag !== 'string') throw TypeError('tag should be string.')
988
- if (tag.length > SIZE_LIMIT.TAG_LEN2) throw TypeError('please check tag string length limit:' + SIZE_LIMIT.TAG_LEN2)
989
-
990
- if (this.state !== STATE.READY) {
991
- return Promise.reject('subscribe_promise:: connection is not ready')
992
- }
979
+ subscribe_channels() {
980
+ if (this.state !== STATE.READY) return
981
+ if (this.channels.size == 0) return
982
+ let tag = Array.from(this.channels).join(',')
993
983
 
994
984
  try {
995
985
  let tagEncoded = encoder.encode(tag)
996
986
  this.send_enc_mode(
997
987
  Buffer.concat([
998
- MBP.NB('8', IOMsg.SUBSCRIBE_REQ),
999
- MBP.NB('16', ++this.mid),
1000
- MBP.NB('16', tagEncoded.byteLength),
988
+ MBP.NB('8', IOMsg.SUBSCRIBE),
989
+ MBP.NB('8', tagEncoded.byteLength),
1001
990
  tagEncoded]))
1002
- return this.setMsgPromise(this.mid)
1003
991
  } catch (error) { }
1004
- }
1005
-
1006
- /**
1007
- * Subscribes to channels stored in memory (local cache).
1008
- */
1009
- subscribe_memory_channels() { //local cache . auto_resubscribe
1010
- if (this.channels.size == 0) return
1011
- let chList = Array.from(this.channels).join(',')
1012
-
1013
- this.subscribe_promise(chList)
1014
- .then((res) => {
1015
- // console.log('>> SUBSCRIBE_REQ result', res ) // return code == map.size
1016
- }).catch((e) => {
1017
- console.log('>> SUBSCRIBE FAIL:', e)
1018
- })
1019
992
 
1020
993
  }
1021
994
 
@@ -116,7 +116,7 @@ for (let c in PAYLOAD_TYPE) { PAYLOAD_TYPE[PAYLOAD_TYPE[c]] = c }
116
116
  * @property {number} SET
117
117
  * @property {number} RESPONSE_CODE
118
118
  * @property {number} RESPONSE_MBP
119
- * @property {number} REQUEST
119
+ * @property {number} CALL
120
120
  * @property {number} RESPONSE
121
121
  * @property {number} FLOW_MODE
122
122
  * @property {number} WAIT
@@ -181,11 +181,10 @@ export let IOMsg = {
181
181
 
182
182
  //..
183
183
  SET: 0xDB, //
184
- RESPONSE_CODE: 0xDC,
184
+ // RESPONSE_CODE: 0xDC,
185
185
  RESPONSE_MBP: 0xDD,
186
-
187
- REQUEST: 0xDE, //client public
188
- RESPONSE: 0xDF,
186
+ CALL: 0xDE, // rpc call
187
+ // RESPONSE: 0xDF,
189
188
  // ~DF
190
189
 
191
190
 
@@ -203,22 +202,13 @@ export let IOMsg = {
203
202
  for (let c in IOMsg) { IOMsg[IOMsg[c]] = c }
204
203
  // console.log( IOMsg );
205
204
 
206
- /**
207
- * @typedef {object} API_TYPE
208
- * @property {string} REQUEST_RESPONSE
209
- * @property {string} ONE_WAY
210
- */
211
- export const API_TYPE = {
212
- 'REQUEST_RESPONSE': 'requet_response',
213
- 'ONE_WAY': 'one_way'
214
- }
215
205
 
216
206
  /**
217
207
  * @typedef {object} STATUS
218
208
  * @property {number} OK
219
209
  * @property {number} ERROR
220
210
  */
221
- // api response status code
211
+ // service response status code
222
212
  export const STATUS = {
223
213
  OK: 0,
224
214
  //0~127: success
@@ -119,7 +119,7 @@ export class Manager {
119
119
  }
120
120
 
121
121
 
122
- if (remote.uid && this.server.apiNames.has('account')) {
122
+ if (remote.uid && this.server.serviceNames.has('account')) {
123
123
  let req = { topic: 'detachUserRemote' }
124
124
  req.args = ['caller:manager.removeRemote']
125
125
  this.server.emit('account', remote, req)
@@ -187,6 +187,7 @@ export class Remote extends RemoteCore {
187
187
 
188
188
  // node.js server side remote.
189
189
  send(message, isBinary) {
190
+ // console.log(`<-S [${IOMsg[ message[0]]}]`)
190
191
  this.manager.txBytes += message.byteLength;
191
192
  this.socket.txCounter++;
192
193
  if (this.socketType === 'websocket') {
@@ -265,15 +265,15 @@ export class RemoteCore {
265
265
  break;
266
266
 
267
267
 
268
- case IOMsg.REQUEST: //api request
268
+ case IOMsg.CALL: //service request
269
269
  try {
270
270
  let req = MBP.unpack(message)
271
271
  if (req) {
272
272
  if (!req.target || !req.topic) return
273
- if (this.manager.server.apiNames.has(req.target)) {
273
+ if (this.manager.server.serviceNames.has(req.target)) {
274
274
  this.manager.server.emit(req.target, this, req)
275
275
  } else {
276
- // console.log('UnKnown API req: ', req.target)
276
+ // console.log('UnKnown Service call: ', req.target)
277
277
  }
278
278
  }
279
279
  } catch (e) {
@@ -3,13 +3,13 @@ import EventEmitter from 'events'
3
3
  import { WebSocketServer } from 'ws'
4
4
  import { Manager } from './Manager.js'
5
5
  import { serverOption } from './serverOption.js'
6
- import { STATUS } from '../api/api_constant.js'
6
+ import { STATUS } from '../services/constant.js'
7
7
 
8
8
  export class Server extends EventEmitter {
9
9
 
10
10
  constructor(options, authManager) {
11
11
  super();
12
- this.apiNames = new Set()
12
+ this.serviceNames = new Set()
13
13
  this.wss = {};
14
14
  this.port = null;
15
15
  this.congPort = null;
@@ -130,63 +130,63 @@ export class Server extends EventEmitter {
130
130
  }
131
131
 
132
132
  /**
133
- * API register.
134
- * target: api_name <string>
135
- * api: api_module <function module|class instance>
133
+ * RPC service register.
134
+ * target: service_name <string>
135
+ * service: service_module <function module|class instance>
136
136
  * return this
137
137
  */
138
- api(target, api) {
138
+ attach(target, service_module) {
139
139
 
140
140
  if( typeof target !== 'string'){
141
- throw new Error(`api( target ,api ) target name is not a string.`)
141
+ throw new Error(`service( target ,service ) target name is not a string.`)
142
142
  }
143
- if (!api.checkPermission || typeof api.checkPermission != 'function') {
144
- throw new Error(`API ${target} : no checkPermission or not a function.`)
143
+ if (!service_module.checkPermission || typeof service_module.checkPermission != 'function') {
144
+ throw new Error(`Service ${target} : no checkPermission or not a function.`)
145
145
  }
146
- if(!api.commands || !Array.isArray(api.commands) ){
147
- throw new Error(`API ${target} : no commands or !Array.`)
146
+ if(!service_module.commands || !Array.isArray(service_module.commands) ){
147
+ throw new Error(`Service ${target} : no commands or !Array.`)
148
148
  }
149
149
 
150
- // API TYPE 1. single request() function.
151
- if ( api.request && typeof api.request == 'function' ) {
150
+ // Service TYPE 1. single call() function.
151
+ if ( service_module.call && typeof service_module.call == 'function' ) {
152
152
  this.on(target, async (remote, req) => {
153
153
  try {
154
- if (!api.checkPermission(remote, req)) {
154
+ if (!service_module.checkPermission(remote, req)) {
155
155
  remote.response(req.mid, STATUS.ERROR, "NO_PERMISSION.")
156
156
  return
157
157
  }
158
- if( api.commands.includes( req.topic )){
159
- // console.log('server api req', req )
160
- await api.request(remote, req)
158
+ if( service_module.commands.includes( req.topic )){
159
+ // console.log('server service_module req', req )
160
+ await service_module.call(remote, req)
161
161
  }else{
162
162
  remote.response(req.mid, STATUS.ERROR, "UNKNOWN_COMMAND");
163
163
  }
164
164
  } catch (error) {
165
- console.error(`Unhandled API Error in target [${target}]:`, error);
165
+ console.error(`Unhandled Service Error in target [${target}]:`, error);
166
166
  remote.response(req.mid, STATUS.ERROR, "INTERNAL_SERVER_ERROR");
167
167
  }
168
168
  })
169
169
  } else {
170
- // API TYPE 2. multiple functions.
170
+ // Service TYPE 2. multiple functions.
171
171
  this.on(target, async (remote, req) => {
172
172
  try {
173
- if (!api.checkPermission(remote, req)) {
173
+ if (!service_module.checkPermission(remote, req)) {
174
174
  remote.response(req.mid, STATUS.ERROR, "NO_PERMISSION.")
175
175
  return
176
176
  }
177
- if( api.commands.includes( req.topic )){
178
- await api[req.topic](remote, req)
177
+ if( service_module.commands.includes( req.topic )){
178
+ await service_module[req.topic](remote, req)
179
179
  }else{
180
180
  remote.response(req.mid, STATUS.ERROR, "UNKNOWN_COMMAND");
181
181
  }
182
182
  } catch (error) {
183
- console.error(`Unhandled API Error in target [${target}]:`, error);
183
+ console.error(`Unhandled Service Error in target [${target}]:`, error);
184
184
  remote.response(req.mid, STATUS.ERROR, "INTERNAL_SERVER_ERROR");
185
185
  }
186
186
  })
187
187
  }
188
- this.apiNames.add(target)
189
- // console.log(`[API registed: ${target} ] accept commands: ${api.commands}`)
188
+ this.serviceNames.add(target)
189
+ // console.log(`[Service attached: ${target} ] accept commands: ${service_module.commands}`)
190
190
  return this
191
191
  }
192
192
 
@@ -196,8 +196,8 @@ export class Server extends EventEmitter {
196
196
  this.manager.close()
197
197
  }
198
198
 
199
- this.apiNames.forEach(v => this.removeAllListeners(v))
200
- this.apiNames.clear()
199
+ this.serviceNames.forEach(v => this.removeAllListeners(v))
200
+ this.serviceNames.clear()
201
201
 
202
202
  let serverCount = 0;
203
203
  if (this.wss) serverCount++;
@@ -1,14 +1,14 @@
1
1
  /**
2
- * RedisAPI <IOSignal API>
2
+ * RedisService <IOSignal RPC Service>
3
3
  *
4
4
  * iosignal 클라이언트의 redis 질의 요청을 받으면,
5
5
  * redisClient 로 연결된 redis-server 에게 질의 후 결과를 되돌려 준다.
6
6
  *
7
7
  * client ex:
8
- * await io.req('redis','hget','user:id' )
8
+ * await io.call('redis','hget','user:id' )
9
9
  *
10
10
  */
11
- import { STATUS } from './api_constant.js'
11
+ import { STATUS } from './constant.js'
12
12
 
13
13
  const MIN_LEVEL = 200;
14
14
  const COMMANDS = [
@@ -18,10 +18,10 @@ const COMMANDS = [
18
18
  'sMembers', 'exists', 'sRem', 'del', 'keys', 'save'
19
19
  ]
20
20
 
21
- export class RedisAPI {
21
+ export class RedisService {
22
22
  constructor(redisClient, _minLevel) {
23
23
  if (!redisClient) {
24
- throw new Error("RedisAPI constructor: no redisClient")
24
+ throw new Error("RedisService constructor: no redisClient")
25
25
  }
26
26
  this.redisClient = redisClient
27
27
  this.minLevel = _minLevel ? _minLevel : MIN_LEVEL
@@ -32,7 +32,7 @@ export class RedisAPI {
32
32
  return (remote.level >= this.minLevel) ? true : false;
33
33
  }
34
34
 
35
- async request(remote, req) {
35
+ async call(remote, req) {
36
36
  let result;
37
37
  try {
38
38
  let cmd = req.topic
@@ -1,9 +1,9 @@
1
1
 
2
2
  /**
3
- * simple IOSignal API example.
3
+ * simple IOSignal RPC Service example.
4
4
  */
5
5
 
6
- import { STATUS } from './api_constant.js'
6
+ import { STATUS } from './constant.js'
7
7
  export const commands = ['echo', 'date', 'unixtime'];
8
8
 
9
9
  const MIN_LEVEL = 0;
@@ -12,7 +12,7 @@ export function checkPermission(remote) {
12
12
  }
13
13
 
14
14
  /**
15
- * client api call example: await io.req('reply','echo','hello')
15
+ * client api call example: await io.call('reply','echo','hello')
16
16
  */
17
17
  export async function echo(remote, req) {
18
18
  if (!req.args)
@@ -22,7 +22,7 @@ export async function echo(remote, req) {
22
22
  }
23
23
 
24
24
  /**
25
- * client api call example: await io.req('reply','date')
25
+ * client api call example: await io.call('reply','date')
26
26
  */
27
27
  export async function date(remote, req) {
28
28
  let r = new Date().toUTCString()
@@ -30,7 +30,7 @@ export async function date(remote, req) {
30
30
  }
31
31
 
32
32
  /**
33
- * client api call example: await io.req('reply','unixtime')
33
+ * client api call example: await io.call('reply','unixtime')
34
34
  */
35
35
  export async function unixtime(remote, req) {
36
36
  let r = Math.floor(Date.now() / 1000)
@@ -1,4 +1,4 @@
1
- import { STATUS } from './api_constant.js'
1
+ import { STATUS } from './constant.js'
2
2
 
3
3
  export const commands = [
4
4
  'cid', 'remotes', 'clients',
@@ -14,7 +14,7 @@ export function checkPermission(remote) {
14
14
  return (remote.level >= MIN_LEVEL) ? true : false;
15
15
  }
16
16
 
17
- export async function request(remote, req) {
17
+ export async function call(remote, req) {
18
18
  let result;
19
19
  let status = 0;
20
20
  try {
@@ -70,7 +70,7 @@ export async function request(remote, req) {
70
70
  }
71
71
  } else {
72
72
  status = STATUS.ERROR;
73
- result = "api sudo: no such a cmd: " + cmd
73
+ result = "service sudo: no such a cmd: " + cmd
74
74
  }
75
75
 
76
76
  remote.response(req.mid, status, result)
package/tsconfig.json CHANGED
@@ -5,7 +5,7 @@
5
5
  "outDir": "./dist/types",
6
6
  "allowJs": true,
7
7
  "moduleResolution": "node",
8
- "target": "es2015",
8
+ "target": "es2020",
9
9
  "lib": ["es2020", "dom"],
10
10
  "baseUrl": ".",
11
11
  "paths": {