Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

Utils.ts 3.3KB

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