您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

Utils.ts 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. import * as uuidv4 from "uuid/v4"
  2. import * as T from "./Types";
  3. import * as I from "./Interfaces";
  4. import { SubscriptionResponse } from "./Types";
  5. export const rpcToRpcinfo = <SubResT = {}>(rpc : T.RPC<SubResT>, owner: T.Owner):T.RpcInfo => {
  6. switch (typeof rpc){
  7. case "object":
  8. if(rpc['call']){
  9. return {
  10. owner: owner,
  11. argNames: extractArgs(rpc['call']),
  12. type: "Call",
  13. name: rpc.name,
  14. call: rpc['call'],
  15. }
  16. }else{
  17. const generator = hookGenerator(<T.HookRPC<any>>rpc)
  18. return {
  19. owner: owner,
  20. argNames: extractArgs(generator(undefined)),
  21. type: "Hook",
  22. name: rpc.name,
  23. generator: generator,
  24. }
  25. }
  26. case "function":
  27. if(!rpc.name) throw new Error(`
  28. RPC did not provide a name.
  29. \nUse 'funtion name(..){ .. }' syntax instead.
  30. \n
  31. \n<------------OFFENDING RPC:
  32. \n`+rpc.toString()+`
  33. \n>------------OFFENDING RPC`)
  34. return {
  35. owner : owner,
  36. argNames: extractArgs(rpc),
  37. type: "Call",
  38. name: rpc.name,
  39. call: async(...args) => rpc.apply({}, args),
  40. }
  41. }
  42. throw new Error("Bad socketIORPC type "+ typeof rpc)
  43. }
  44. export function rpcHooker<SubResT = {}>(socket: I.Socket, exporter:I.Exporter<SubResT>, makeUnique = true):T.ExtendedRpcInfo[]{
  45. const owner = exporter.name
  46. const RPCs = [...exporter.exportRPCs()]
  47. const suffix = makeUnique?"-"+uuidv4().substr(0,4):""
  48. return RPCs.map(rpc => rpcToRpcinfo(rpc, owner))
  49. .map(info => {
  50. const ret:any = info
  51. ret.uniqueName = info.name+suffix
  52. switch(info.type){
  53. case "Hook":
  54. socket.hook(ret.uniqueName, info.generator(socket))
  55. break;
  56. case "Call":
  57. socket.hook(ret.uniqueName, info.call)
  58. break;
  59. }
  60. socket.on('close', () => socket.unhook(info.name))
  61. return ret
  62. })
  63. }
  64. //
  65. const hookGenerator = (rpc:T.HookRPC<any>): T.HookInfo['generator'] => {
  66. const argsArr = extractArgs(rpc.hook)
  67. argsArr.pop()
  68. const args = argsArr.join(',')
  69. return eval(`(socket) => async (`+args+`) => {
  70. const res = await rpc.hook(`+args+(args.length!==0?',':'')+` (...cbargs) => {
  71. if(rpc.onCallback) rpc.onCallback.apply({}, cbargs)
  72. socket.call.apply(socket, [res.uuid, ...cbargs])
  73. })
  74. if(res.result === 'Success'){
  75. if(rpc.onClose){
  76. socket.on('close', async () => {
  77. rpc.onClose(res, rpc)
  78. })
  79. }
  80. }
  81. return res
  82. }`)
  83. }
  84. const extractArgs = (f:Function):T.Arg[] => {
  85. let fn
  86. return (fn = String(f)).substr(0, fn.indexOf(")")).substr(fn.indexOf("(")+1).split(",")
  87. }
  88. export function makeSubResponse(uuid?:string):SubscriptionResponse{
  89. return {
  90. result: "Success",
  91. uuid: uuid?uuid:uuidv4(),
  92. }
  93. }