work in progress ;-)
Naga framework is a web development framework written in erlang which implements the server-side MVC pattern. Naga is build on top of N2O framework, many of its components and concepts are from ChicagoBoss.
Naga provides the best of both framework - ChicagoBoss and N2O, for implementing realtime features in modern web HTML5 application.
- some CB & N2O ...
- live reload ala phoenix (see)
- Desktop application erlang/electron-app
- bundle your electron-app with erlang runtime (or not), and your naga-app (mad bundle )
sys.config
[{n2o, [...
,{protocols,[ naga_electron, %ws
naga_load, %live reload
...
]}
erlang: routes file
,{ "/electron" ,[{app, <appname>},{ctrl, electron} ,{act, index}], []}
erlang: naga controller
-module(electron).
-compile(export_all).
index(_,_,_) -> 404.
event({electron,init}) -> wf:wire("console.log('Hello World!!');").
- electron:main process you will need bert.js, utf8.js, client.js and the code below to establish a ws connection to your erlang app.
$ws = { heart: true, interval: 4000,
creator: function(url) { new WebSocket(url); },
onheartbeat: function() { this.channel.send('PING'); } };
// N2O Reliable Connection
$conn = { onopen: nop, onmessage: nop, onclose: nop, onconnect: nop,
send: function(data) { if (this.port.channel) this.port.channel.send(data); },
close: function() { if (this.port.channel) this.port.channel.close(); } };
ct = 0;
transports = [ $ws ];
heartbeat = null;
reconnectDelay = 1000;
maxReconnects = 100;
function nop() { }
function bullet(url) { $conn.url = url; return $conn; }
function xport() { return maxReconnects <= ct ? false : transports[ct++ % transports.length]; }
function reconnect() { setTimeout(function() { connect(); }, reconnectDelay); }
function next() { $conn.port = xport(); return $conn.port ? connect() : false; }
function connect() {
$conn.port.channel = new WebSocket($conn.url);
$conn.port.channel.onerror = function(e){};
if (!$conn.port.channel) { setInterval(next(), 4000);} //retry until we establish cnx
$conn.port.channel.onmessage = function(e) { $conn.onmessage(e); };
$conn.port.channel.onopen = function() {
if ($conn.port.heart) heartbeat = setInterval(function(){$conn.port.onheartbeat();}, $conn.port.interval);
$conn.onopen();
$conn.onconnect(); };
$conn.port.channel.onclose = function() { $conn.onclose(); clearInterval(heartbeat); reconnect(); };
return $conn; }
function NAGA_start(url) {
ws = new bullet(url);ws.onerror = function(e){};
ws.onmessage = function (evt) { // formatters loop
for (var i=0;i<protos.length;i++) { p = protos[i]; if (p.on(evt, p.do).status == "ok") return; } };
ws.onopen = function() { if (!active) { console.log('Connect'); ws.send(enc(tuple(atom('electron'),atom('init')))); active=true; } };
ws.onclose = function() { active = false; console.log('Disconnect'); }; next(); }
function is(x,num,name) { return x.t==106?false:(x.v.length === num && x.v[0].v === name); }
/// N2O Protocols
var $io = {}; $io.on = function onio(r, cb) { if (is(r,3,'io')) {//console.log(utf8_dec(r.v[1].v));
try { eval(utf8_dec(r.v[1].v)); if (typeof cb == 'function') cb(r); return { status: "ok" }; }
catch (e) { console.log(e); return { status: '' }; } } else return { status: '' }; }
var protos = [$client];
app.on('ready', function(){
....
//start your erlang app as a child process using escript
....
//establish ws cnx with your erlang app
NAGA_start("http://127.0.0.1:8001/ws/electron");
});
- Erlang/OTP version >= 18, require maps
To create and build a naga application you need to install mad.
You can download mad directly from github:
$ curl -O https://raw.githubusercontent.com/naga-framework/mad/naga_v2/mad
Then ensure it is executable
$ chmod a+x mad
and drop it in your $PATH
$ git clone https://github.com/naga-framework/mad.git
$ cd mad
$ make
and drop it in your $PATH
mad integrate a small template engine.
$ mad create name=hello tpl=basic port=9000 desc="hello app" vsn="0.0.1"
>mad create name=hello tpl=basic port=9000 desc="my awesome hello app" vsn="0.0.1"
Name = "hello"
TplName = "basic"
Vars = [{port,"9000"},{tpl,"basic"},{name,"hello"}]
Writing hello/apps/hello/priv/hello.routes
Writing hello/apps/hello/rebar.config
Writing hello/apps/hello/src/hello.app.src
Writing hello/apps/hello/src/hello.erl
Writing hello/apps/rebar.config
Writing hello/rebar.config
Writing hello/sys.config
Writing hello/vm.args
Writing hello/apps/hello/src/controller/error.erl
Writing hello/apps/hello/src/controller/index.erl
Writing hello/apps/hello/src/view/error/404.html
Writing hello/apps/hello/src/view/index/index.html
Writing hello/apps/hello/src/view/layout/n2o.html
Writing hello/apps/hello/src/view/layout/page.html
OK
>cd hello
>mad clean deps comp plan repl -name [email protected]