
*Just components sending JSON messages. No extra abstractions, KTHX!*

# Intro

appborg helps you build hybrid apps:
<pre>
    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
</pre>

...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 {<code>from</code>,<code>to</code>}. <code>to</code> defaults to:
<pre>
  From a JS component,            "subprocess"
  From a subprocess component,    'js'
  From the native component,      there is no default.
</pre>

## Events

Events are similar to those of [JSON-RPC](http://json-rpc.org/wiki/specification).

#### Request
<pre>
{
  "method": "event-name",
  "info":   ...some JSON value...,
  "id":     1234,
  "from":   "js",
  "to":     "subprocess"
}
</pre>

#### Response
<pre>
{
  "result": ...some JSON value...,
  "error":  ...some JSON value...,
  "id":     1234,
  "from":   "subprocess",
  "to":     "js"
}
</pre>

Exactly one of <code>result</code>, <code>error</code> must be <code>null</code>. The other one must not be falsish.

#### How subprocess communication works:
<pre>
(base64Encode(jsonEncode(event)) + "\n") on {stdin,stdout}
</pre>


#### How JS communication works:
<pre>
...QtWebKit 2-way communication...
</pre>
or when that's not available, e.g. when using a Cocoa WebView to reduce your app's size...
<pre>
window.appborg.pushAndPullEvents([...])   --> [...]
</pre>


# JS (running in WebKit)
<pre>
{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, {...}
</pre>


# Subprocesses

## {NodeJS, Python, ...}

TODO


## Java

Prereq: [org.json](https://github.com/douglascrockford/JSON-java)

<pre>
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 {
    ...
  }
}
</pre>

## Mac

Prereqs:

* <code>#import &lt;WebKit/WebKit.h></code>
* <code>#import "SBJson.h"</code>

<pre>
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;
</pre>



## Windows

TODO


## Linux

TODO