Just components sending JSON messages. No extra abstractions, KTHX!
Intro
appborg helps you build hybrid apps:
one ({Mac,Windows,Linux} fully-native desktop app) + zero or more (JS interfaces in embedded WebKit view)s + zero or more ({NodeJS,Java,...} subprocess)es
...where components can send each other JSON events, which arrive in order.
You'll probably want to minimize the amount of native code.
Details
Components
Each component has a name. The default names are "native", "subprocess", and "js".
Each event has {from
,to
}. to
defaults to:
From a JS component, "subprocess" From a subprocess component, 'js' From the native component, there is no default.
Events
Events are similar to those of JSON-RPC.
Request
{ "method": "event-name", "info": ...some JSON value..., "id": 1234, "from": "js", "to": "subprocess" }
Response
{ "result": ...some JSON value..., "error": ...some JSON value..., "id": 1234, "from": "subprocess", "to": "js" }
Exactly one of result
, error
must be null
. The other one must not be falsish.
How subprocess communication works:
(base64Encode(jsonEncode(event)) + "\n") on {stdin,stdout}
How JS communication works:
...QtWebKit 2-way communication...
or when that's not available, e.g. when using a Cocoa WebView to reduce your app's size...
window.appborg.pushAndPullEvents([...]) --> [...]
JS (running in WebKit)
{ABBrowserComm} = require 'appborg' comm = new ABBrowserComm comm.send 'foo' comm.send 'foo', to:'native', {...info...}, (err, res) -> # send(method, [options], [info], [callback]) -- you cannot specify options unless you specify info # If take fewer than three arguments (JS fun fact: (function(x, y, z){}).length == 3), comm will send a blank response when you return. comm.on 'bar', (e, info) -> ... comm.on 'bar', (e, info, callback) -> ... callback null, {...}
Subprocesses
{NodeJS, Python, ...}
TODO
Java
Prereq: org.json
import org.json.*; import org.appborg.ABComm; import org.appborg.ABEvent; import org.appborg.ABEventHandler; public class SomeController implements ABEventHandler { private ABComm comm; ... private void run() throws Exception { comm = new ABComm(this); comm.listenLoop(); } private void handleEvent(ABEvent e) throws Exception { ... } }
Mac
Prereqs:
#import <WebKit/WebKit.h>
#import "SBJson.h"
ABComm - (void) init; - (void) sendEvent:(NSString*)method to:(NSString*)to info:(NSDictionary*)info; ABJSWrapper - (id) initWithComm:(ABComm*)comm name:(NSString*)name webView:(WebView*)webView; ABSubprocessWrapper - (id)initWithComm:(ABComm*)comm name:(NSString*)name launchPath:(NSString*)launchPath arguments:(NSArray*)arguments; ABEvent @property (readonly) long eventId; @property (readonly) NSString *method; @property (readonly) NSDictionary *info; - (void) respond:(NSDictionary*)result; - (void) respondError:(NSDictionary*)error;
Windows
TODO
Linux
TODO