Skip to content

Latest commit

History

42 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

Magic Bridge

Magic Bridge lets you call functions on a Node.JS server from a client, abstracting away HTTP.

Register a function on the server:

constnewBridge=require('@magic-bridge/bridge')// import bridge from '@magic-bridge/bridge'constbridge=newBridge()// register functions (or classes)bridge.register(functiongetServerThing(){return'i am a string from server'}// use with express constapp=express()app.use('/jsonrpc/default',bridge.middleware())

Now you can call it from the client:

constbridge=require('@magic-bridge/client')// import bridge from '@magic-bridge/client'constbridge=newBridge()// call a function on the server!constthingFromServer=awaitbridge.getServerThing()// thingFromServer === 'i am a string from server'

Install

At your server:

npm install @magic-bridge/bridge

At your client:

npm install @magic-bridge/client

Usage

Create a bridge instance

The Magic Bridge module exports a factory function for making new bridges both on the client and the server. The server optionally accepts some advanced options:

On the server

constnewBridge=require('@magic-bridge/bridge')constbridge=newBridge()// orconstbridge=newBridge(opts)
OptionDescriptionTypeDefault
ignoreMethodNameRegexFunctions registered that match this regex will be ignored. Such as methods on a class starting with an underscore to denote that they are privateregex/^_/
throwOnDupWill throw an error if more than one function is added with the same namebooleantrue

On the client

The client accepts one optional arguemnt; the url/path of the Magic Bridge middleware

constnewBridge=require('@magic-bridge/client')constbridge=newBridge()// uses /jsonrpc/default// or constbridge=newBridge('/my-magic-bridge-url')

the client bridge is now ready to call functions on the server:

// bridge calls must always be asyncconstthingFromServer=awaitbridge.doServerThing()

Registering functions

Magic Bridge provides a few ways of registering functions via register():

Just a function

bridge.register(functionfunc(){ ... })// client: await bridge.func()

A function with context

constobj={x: 99,func: function(){returnthis.x}}bridge.register(obj.func,obj)// client: await bridge.func() --> 99

A function with a given name

bridge.register('myFunc',()=>{ ... })// client: await bridge.myFunc()

A function with a given name and context

constobj={x: 99,func: function(){returnthis.x}}bridge.register('myFunc',obj.func,obj)// client: await bridge.myFunc() --> 99

An instance of a class

This is quite handy, espcially in combination with multiple bridges

classClazz{myMethod(){return99}anotherMethod(){return88}}constclazz=newClazz()bridge.register(clazz)// client: await bridge.myMethod() --> 99// client: await bridge.anotherMethod() --> 88

Functions on a plain object

This is quite handy, espcially in combination with multiple bridges

constobj{myFunction(){return99}anotherFunction(){return88}}bridge.register(obj)// client: await bridge.myFunction() --> 99// client: await bridge.anotherFunction() --> 88

Using middleware with Express

Magic Bridge is designed to be used as Express middleware. The default path used by the client is /jsonrpc/default, so the default set up is to do this:

constapp=express()app.use('/jsonrpc/default',bridge.middleware())

If you do use a different path, you must also configure the bridge side on the client to use it:

// client side:constbridge=newBridge('/my-magic-bridge-path')

Multple bridges

You can create multiple bridge instances in a single application, this useful for two main reasons:

  1. It acts as a namespace for classes or collections of related functions
  2. Registered functions/methods requiring different credentials can be used as separate middleware
constnewBridge=require('@magic-bridge/bridge')constauth=newAuth();constaccount=newAccount()constauthBridge=newBridge()constaccountBridge=newBridge()app.use('/jsonrpc/auth',authBridge.middleware())app.use('/jsonrpc/account',ensureLoggedIn(),accountBridge.middleware())

and on the client:

constnewBridge=require('@magic-bridge/client')constauthBridge=newBridge('/jsonrpc/auth')constaccountBridge=newBridge('/jsonrpc/account')awaitauthBridge.login()awaitaccountBridge.changeUsername()

Local arg resolvers

Functions on the server can be injected with request, response, request.session and request.cookie arguments that are invisible to the client.

Use arguments with these method names in any postion to have them injected:

ArgumentResolves to
_request_The (express) request object
_response_The (express) response object
_session_The (express) request session object (if using express-session middleware
_cookies_Parsed request cookies

Examples:

functionchangeUsername(_session_,newUsername){constuser=db.getUser(_session_.userId)user.setUsername(newUsername)...}
functionchangeUsername(newUsername,_cookies_){constuser=db.getUser(_cookies_.token)user.setUsername(newUsername)...}

Credits

Magic Bridge is inspired by JSON-RPC-Java (later renamed Jabsorb) a library I used circa 2006-8 to do Ajaxy stuff.

Magic bridge partially implements the JSON-RPC 2.0 specification (it doesn't do batches)

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages