You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

demo.ts 6.6KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239
  1. import { RPCServer, RPCSocket } from './Index'
  2. import { RPCExporter } from './src/Interfaces'
  3. // TL;DR
  4. const echo = (text: string) => text
  5. const add = (a: number, b: number) : number => a + b
  6. const getAsync = async () : Promise<{topic: string, message:string}>=> await new Promise((res, _) => {
  7. setTimeout(() => {
  8. res({
  9. topic: "Hey!!",
  10. message: "Hello World Async!"
  11. })
  12. }, 250)
  13. })
  14. const getCallback = (callback: Function) : string => {
  15. setTimeout(() => {
  16. try{
  17. callback({
  18. topic: "Hey!!",
  19. message: "Hello World Callback!"
  20. })
  21. }catch(e){
  22. console.log(String(e))
  23. }
  24. }, 250)
  25. return "Please wait for a callback :)"
  26. }
  27. new RPCServer(20000, [{
  28. name: 'MyRPCGroup1',
  29. exportRPCs: () => [
  30. echo,
  31. add,
  32. getAsync,
  33. {
  34. name: 'getCallback',
  35. hook: getCallback,
  36. onClose: (response, rpc) => { /* ... */ },
  37. onCallback: (...callbackArgs) => { /* ... */ }
  38. }
  39. ]
  40. }])
  41. new RPCSocket(20000, 'localhost').connect().then(async sock => {
  42. try{
  43. const RPCs = sock['MyRPCGroup1']
  44. await RPCs.echo("hello!").then(console.log)
  45. await RPCs.add(1, Math.PI).then(console.log)
  46. await RPCs.getAsync().then(console.log)
  47. await RPCs.getCallback(console.log).then(console.log)
  48. }catch(e){
  49. console.log(String(e))
  50. }
  51. })
  52. //Hooks and events
  53. new RPCServer(20001, [{
  54. name: 'MyRPCGroup1',
  55. exportRPCs: () => [
  56. echo,
  57. add,
  58. getAsync,
  59. {
  60. name: 'getCallback',
  61. hook: getCallback,
  62. onClose: (response, rpc) => { /* client disconnected */ },
  63. onCallback: (...callbackArgs) => { /* callback triggered */ }
  64. }
  65. ],
  66. }], {
  67. visibility: '127.0.0.1', //0.0.0.0
  68. closeHandler: (socket) => { /* global close handler */ },
  69. connectionHandler: (socket) => { /* new connection made */ },
  70. errorHandler: (socket, error, rpcname, argArr) => { /* An error occured inside a RPC */ },
  71. })
  72. const sock = new RPCSocket(20001, 'localhost')
  73. sock.on('error', (e) => { /* handle error */ })
  74. sock.on('close', () => { /* handle close event */ })
  75. sock.hook('RPCName', (/* arg0, arg1, ..., argN */) => { /* bind client-side RPCs */ })
  76. //Retrieve the socket from connectionHandler (Server-side) and trigger with
  77. //socket.call('RPCName', arg0, arg1, ..., argN)
  78. sock.connect().then(_ => { /* ... */})
  79. //Restricting access
  80. new RPCServer(20002, [{
  81. name: 'MyRPCGroup1',
  82. exportRPCs: () => [
  83. echo,
  84. add,
  85. getAsync,
  86. {
  87. name: 'getCallback',
  88. hook: getCallback,
  89. }
  90. ],
  91. }], {
  92. sesame: "sesame open",
  93. /*
  94. OR check sesame dynamically
  95. and refine permissioning with accessfilter (optional)
  96. */
  97. //sesame: (sesame) => true
  98. //accessFilter: (sesame, exporter) => { return exporter.name === "MyRPCGroup1" && sesame === "sesame open" },
  99. })
  100. new RPCSocket(20002, 'localhost').connect("sesame open").then(async sock => {
  101. try{
  102. const RPCs = sock['MyRPCGroup1']
  103. await RPCs.echo("hello!").then(console.log)
  104. await RPCs.add(1, Math.PI).then(console.log)
  105. await RPCs.getAsync().then(console.log)
  106. await RPCs.getCallback(console.log).then(console.log)
  107. }catch(e){
  108. console.log(String(e))
  109. }
  110. })
  111. //TypeScript and pseudo-interfaces
  112. type MyInterface = {
  113. MyRPCGroup1: {
  114. echo: (x: string) => string
  115. add: (a: number, b: number) => number
  116. getAsync: () => Promise<{ topic: string, message: string }>
  117. getCallback: (callback:Function) => string
  118. }
  119. };
  120. /*
  121. exportRPCs is now type safe. Try swapping echo for badEcho.
  122. Sadly TSC's stack traces aren't the best, but try to scroll to the bottom of them to find useful info like
  123. Type '(x: boolean) => number' is not assignable to type '(x: string) => string'
  124. */
  125. const badEcho = (x: boolean) : number => 3
  126. new RPCServer<MyInterface>(20003, [{
  127. name: 'MyRPCGroup1',
  128. exportRPCs: () => [
  129. //badEcho,
  130. echo,
  131. add,
  132. getAsync,
  133. {
  134. name: 'getCallback',
  135. hook: getCallback,
  136. }
  137. ],
  138. }])
  139. new RPCSocket<MyInterface>(20003, 'localhost').connect().then(async sock => {
  140. try{
  141. await sock.MyRPCGroup1.echo("hello!").then(console.log)
  142. await sock.MyRPCGroup1.add(1, Math.PI).then(console.log)
  143. await sock.MyRPCGroup1.getAsync().then(console.log)
  144. await sock.MyRPCGroup1.getCallback(console.log).then(console.log)
  145. }catch(e){
  146. console.log(String(e))
  147. }
  148. })
  149. //Class-based pattern
  150. interface IMyImplementation {
  151. echo: (x: string) => string
  152. add: (a: number, b: number) => number
  153. getAsync: () => Promise<{ topic: string, message: string }>
  154. getCallback: (callback:Function) => string
  155. }
  156. type MyIfc = {
  157. MyRPCGroup1: {
  158. echo: IMyImplementation['echo']
  159. add: IMyImplementation['add']
  160. getAsync: IMyImplementation['getAsync']
  161. getCallback: IMyImplementation['getCallback']
  162. }
  163. }
  164. class MyImplementation implements IMyImplementation, RPCExporter<MyIfc>{
  165. //"X" as "X" syntax is required to satisfy the type system (as it assumed string)
  166. name = "MyRpcGroup11" as "MyRPCGroup1"
  167. //List the functions you declared in MyIfc
  168. exportRPCs = () => [
  169. this.echo,
  170. this.add,
  171. this.getAsync,
  172. this.getCallback
  173. ]
  174. //Write your implementations as you normally would
  175. echo = (text: string) => text
  176. add = (a: number, b: number) : number => a + b
  177. getAsync = async () : Promise<{topic: string, message:string}>=> await new Promise((res, _) => {
  178. setTimeout(() => {
  179. res({
  180. topic: "Hey!!",
  181. message: "Hello World Async!"
  182. })
  183. }, 250)
  184. })
  185. getCallback = (callback: Function) : string => {
  186. setTimeout(() => {
  187. try{
  188. callback({
  189. topic: "Hey!!",
  190. message: "Hello World Callback!"
  191. })
  192. }catch(e){
  193. console.log(String(e))
  194. }
  195. }, 250)
  196. return "Please wait for a callback :)"
  197. }
  198. }
  199. new RPCServer<MyIfc>(20004, [new MyImplementation(), /* ... other RPCExporters */])
  200. new RPCSocket<MyIfc>(20004, 'localhost').connect().then(async sock => {
  201. try{
  202. await sock.MyRPCGroup1.echo("hello!").then(console.log)
  203. await sock.MyRPCGroup1.add(1, Math.PI).then(console.log)
  204. await sock.MyRPCGroup1.getAsync().then(console.log)
  205. await sock.MyRPCGroup1.getCallback(console.log).then(console.log)
  206. }catch(e){
  207. console.log(String(e))
  208. }
  209. })