Просмотр исходного кода

mad app <zero|nitro> [yourname]

Namdak Tonpa 5 лет назад
Родитель
Сommit
10c5ef5c19

+ 1 - 1
include/mad.hrl

@@ -1 +1 @@
--define(VERSION,"5.4-22-gd3f90e7").
+-define(VERSION,"5.4-23-g590873b").


+ 0 - 38
priv/mqtt/priv/static/index.htm

@@ -1,38 +0,0 @@
-<html>
-
-<head>
-    <meta charset="utf-8">
-    <meta http-equiv="x-ua-compatible" content="ie=edge">
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link href='synrc.css' type='text/css' rel='stylesheet'>
-    <title>Chat</title>
-</head>
-
-<body class="chat">
-    <header>
-        <a href="/login.htm"><img src="https://n2o.space/img/Synrc%20Neo.svg"></a>
-        <h2 id=heading>room</h2>
-        <button id=logout>logout</button>
-    </header>
-    <main>
-        <form>
-            <textarea id=message rows='4' autofocus placeholder="Just type what you think about this"></textarea>
-            <button id=upload>Browse</button>
-            <button id=send>chat</button>
-        </form>
-        <history id="history">
-        </history>
-
-    </main>
-    <script src="//cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js"></script>
-    <script src='https://ws.n2o.space/priv/utf8.js'></script>
-    <script src='https://ws.n2o.space/priv/bert.js'></script>
-    <script src='https://ws.n2o.space/priv/ieee754.js'></script>
-    <script src='https://ws.n2o.space/priv/n2o.js'></script>
-    <script>host = location.hostname === 'review.n2o.space' ? 'ns.synrc.com' : location.hostname; port = 8000;</script>
-    <script src='https://ws.n2o.space/priv/ftp.js'></script>
-    <script src='https://ws.n2o.space/priv/nitro.js'></script>
-    <script src='https://ws.n2o.space/priv/mq.js'></script>
-</body>
-
-</html>

+ 0 - 36
priv/mqtt/priv/static/login.htm

@@ -1,36 +0,0 @@
-<html>
-
-<head>
-    <meta charset="utf-8">
-    <meta http-equiv="x-ua-compatible" content="ie=edge">
-    <meta name="viewport" content="width=device-width, initial-scale=1">
-    <link href='synrc.css' type='text/css' rel='stylesheet'>
-    <title>Login</title>
-</head>
-
-<body class="login">
-    <header>
-        <a href="/index.htm">
-        <img src="https://n2o.space/img/Synrc%20Neo.svg" style="margin-bottom:40px;"></a>
-    </header>
-    <form>
-        <label for="user">Choose Nickname:</label>
-        <input type="text" id="user" autofocus>
-        <label for="pass">Join or Create Channel:</label>
-        <input type="text" id="pass">
-        <button id="loginButton">login</button>
-    </form>
-    <footer>Brought to you with ♡ by N2O developers.</footer>
-    <script src="//cdnjs.cloudflare.com/ajax/libs/paho-mqtt/1.0.1/mqttws31.js"></script>
-    <script src='https://ws.n2o.space/priv/utf8.js'></script>
-    <script src='https://ws.n2o.space/priv/bert.js'></script>
-    <script src='https://ws.n2o.space/priv/ieee754.js'></script>
-    <script src='https://ws.n2o.space/priv/n2o.js'></script>
-    <script>host = location.hostname === 'review.n2o.space' ? 'ns.synrc.com' : location.hostname; port = 8000;</script>
-    <script src='https://ws.n2o.space/priv/ftp.js'></script>
-    <script src='https://ws.n2o.space/priv/nitro.js'></script>
-    <script src='https://ws.n2o.space/priv/mq.js'></script>
-    <script> qi('pass').value = module == "login" ? "" : module; </script>
-</body>
-
-</html>

+ 0 - 7
priv/mqtt/rebar.config

@@ -1,7 +0,0 @@
-{deps, [
-    {kvs,    ".*", {git, "git://github.com/synrc/kvs",    []}},
-    {mad,    ".*", {git, "git://github.com/synrc/mad",    []}},
-    {n2o,    ".*", {git, "git://github.com/synrc/n2o",    []}},
-    {emqttd, ".*", {git, "git://github.com/synrc/emqttd", []}},
-    {nitro,  ".*", {git, "git://github.com/synrc/nitro",  []}}
-]}.

+ 0 - 57
priv/mqtt/src/index.erl

@@ -1,57 +0,0 @@
--module(index).
--description('MQTT Application').
--compile(export_all).
--include_lib("kvs/include/entry.hrl").
--include_lib("nitro/include/nitro.hrl").
--include_lib("n2o/include/n2o.hrl").
-
-event(init) ->
-    nitro:wire("nodes="++nitro:to_list(length(n2o:ring()))++";"),
-    #cx{session=Token,params=Id,node=Node} = get(context),
-    Room = n2o:session(room),
-    nitro:update(logout,  #button { id=logout,  body="Logout "  ++ n2o:user(),       postback=logout}),
-    nitro:update(send,    #button { id=send,    body="Chat",       source=[message], postback=chat}),
-    nitro:update(heading, #h2     { id=heading, body=Room}),
-    nitro:update(upload,  #upload { id=attach }),
-    nitro:wire("mqtt.subscribe('room/"++Room++"',subscribeOptions);"),
-    Topic = iolist_to_binary(["events/1/",Node,"/index/anon/",Id,"/",Token]),
-    n2o_vnode:send_reply(<<>>, 2, Topic, term_to_binary(#client{data={Room,list}})),
-    io:format("Room: ~p~n",[Room]),
-    nitro:wire(#jq{target=message,method=[focus,select]});
-
-event(chat) ->
-    User    = n2o:user(),
-    Message = nitro:q(message),
-    Room    = n2o:session(room),
-    io:format("Chat pressed: ~p\r~n",[{Room,Message,User}]),
-    #cx{session=ClientId} = get(context),
-    kvs:add(#entry{id=kvs:next_id("entry",1),
-                   from=n2o:user(),feed_id={room,Room},media=Message}),
-    nitro:insert_top(history, nitro:jse(message_view(User,Message))),
-    Actions = iolist_to_binary(n2o_nitro:render_actions(nitro:actions())),
-    M = term_to_binary({io,Actions,<<>>}),
-    n2o_vnode:send_reply(ClientId, 2, iolist_to_binary([<<"room/">>,Room]), M);
-
-event(#client{data={Room,list}}) ->
-    [ nitro:insert_top(history, nitro:jse(message_view(E#entry.from,E#entry.media)))
-      || E <- lists:reverse(kvs:entries(kvs:get(feed,{room,Room}),entry,30)) ];
-
-event(#ftp{sid=_Sid,filename=Filename,status={event,init}}=Data) ->
-    ok;
-
-event(#ftp{sid=_Sid,filename=Filename,status={event,stop}}=Data) ->
-    Name = hd(lists:reverse(string:tokens(nitro:to_list(Filename),"/"))),
-    IP = application:get_env(sample,host,"127.0.0.1"),
-    erlang:put(message,
-    nitro:render(#link{href=iolist_to_binary(["http://",IP,":8000/n2o/",
-                       nitro_conv:url_encode(Name)]),body=Name})),
-    event(chat);
-
-event(logout) ->  nitro:redirect("/login.htm"), n2o:session(room,[]);
-event(Event)  -> io:format("Event: ~p", [Event]).
-
-message_view(User,Message) ->
-   iolist_to_binary(["<message><author>",User,"</author>",Message,"</message>"]).
-
-main() -> [].
-

+ 0 - 21
priv/mqtt/src/login.erl

@@ -1,21 +0,0 @@
--module(login).
--compile(export_all).
--include_lib("kvs/include/feed.hrl").
--include_lib("n2o/include/n2o.hrl").
--include_lib("nitro/include/nitro.hrl").
-
-event(init) ->
-    nitro:wire("nodes="++nitro:to_list(length(n2o:ring()))++";"),
-    nitro:update(loginButton,
-          #button { id=loginButton, body="login",
-                    postback=login,source=[user,pass]});
-
-event(login) ->
-    User = nitro:to_list(nitro:q(user)),
-    Room = nitro:to_list(nitro:q(pass)),
-    n2o:user(User),
-    n2o:session(room,Room),
-    nitro:redirect("/index.htm");
-
-event(_) -> [].
-main()   -> [].

+ 0 - 9
priv/mqtt/src/sample.app.src

@@ -1,9 +0,0 @@
-{application,sample,
-             [{description,"REVIEW TT Application"},
-              {vsn,"1.10"},
-              {registered,[]},
-              {applications, [public_key,asn1,kernel,stdlib,mnesia,syntax_tools,compiler,xmerl,
-                 kvs,goldrush,gen_logger,lager,gproc,esockd,mochiweb,emqttd,n2o]},
-              {mod,{sample,[]}},
-              {env,[]},
-              {modules,[]}]}.

+ 0 - 31
priv/mqtt/src/sample.erl

@@ -1,31 +0,0 @@
--module(sample).
--behaviour(supervisor).
--behaviour(application).
--export([init/1, start/0, start/2, stop/1, main/1]).
--compile(export_all).
-
-main(A)    -> mad:main(A).
-init([])   -> {ok, {{one_for_one, 5, 10}, [spec()]}}.
-start()    -> start(normal,[]).
-start(_,_) -> emqttd_access_control:register_mod(auth, n2o_auth, [[]], 10),
-              supervisor:start_link({local,sample},sample,[]).
-stop(_)    -> ok.
-spec()     ->
-    Acceptors  = application:get_env(?MODULE, acceptors,   4),
-    Clients    = application:get_env(?MODULE, max_clients, 512),
-    Protocol   = application:get_env(?MODULE, protocol,    http),
-    Port       = application:get_env(?MODULE, port,        8000),
-    Options    = [{max_clients, Clients}, {acceptors, Acceptors}],
-    Args       = [{mochiweb, handle, [docroot()]}],
-    mochiweb:child_spec(Protocol, Port, Options, Args).
-
-docroot() ->
-    {file, Here} = code:is_loaded(?MODULE),
-    Dir = filename:dirname(filename:dirname(Here)),
-    Root = application:get_env(?MODULE, "statics_root", "priv/static"),
-    filename:join([Dir, Root]).
-
-rebar3()   -> mad_repl:application_config(mad_repl:load_sysconfig()),
-              {ok,[{_,R,L}]}=file:consult(code:lib_dir(sample)++"/ebin/sample.app"),
-              [ application:ensure_started(X) || X <- proplists:get_value(applications,L,[]) ],
-              application:ensure_started(R).

+ 0 - 25
priv/mqtt/src/sample_auth.erl

@@ -1,25 +0,0 @@
--module(sample_auth).
--include_lib("n2o/include/n2o.hrl").
--compile(export_all).
-
-info({init, <<>>}, Req, State = #cx{session = Session}) ->
-    {'Token', Token} = n2o_session:authenticate([], Session),
-    #cx{params = _ClientId} = get(context),
-    kvs:put({config, Token, State}),
-    io:format("Token Saved: ~p~n",[Token]),
-    n2o_nitro:info({init, Token}, Req, State);
-
-% test protocol
-
-info({load, <<>>}, Req, State = #cx{session = _Session}) ->
-    #cx{params = ClientId} = get(context),
-    M = "list of previous messages",
-    n2o:send_reply(ClientId, 2, iolist_to_binary([<<"actions/1/index/">>,ClientId]), M),
-    {reply, {binary, term_to_binary(<<>>)}, Req, State};
-
-info({message, _Text} = M, Req, State = #cx{session = _Session}) ->
-    #cx{params = ClientId} = get(context),
-    n2o:send_reply(ClientId, 2, <<"room/global">>, M),
-    {reply, {binary, term_to_binary(<<>>)}, Req, State};
-
-info(Message,Req,State) -> {unknown,Message,Req,State}.

+ 0 - 85
priv/mqtt/sys.config

@@ -1,85 +0,0 @@
-[
-   {sample, [{port, 8000},
-             {host,"127.0.0.1"},
-             {protocol, http},
-             {acceptors, 4},
-             {max_clients, 512},
-             {statics_root, "priv/static"},
-             {main_page, "login.html"}
-            ]},
-   {bert,[{js,"deps/sample/bpe/"},
-         {swift,"deps/sample/bpe/"}]},
-   {n2o, [{pickler,n2o_secret},
-          {app,sample},
-          {upload,"./priv/static/n2o"},
-          {routes,routes},
-          {cowboy_spec,cow2},
-          {log_modules,[index,sample,login,n2o_vnode,n2o,n2o_auth,n2o_heart,n2o_nitro]},
-          {formatter,n2o_bert},
-          {protocols,[sample_auth,n2o_nitro,n2o_ftp]}]},
-   {emq_dashboard, [{listeners_dash,[{http,18083,[{acceptors,4},{max_clients,512}]}]}]},
-   {emqttd,
-     [{plugins_loaded_file,"etc/loaded_plugins"},
-      {plugins_etc_dir,"etc/plugins/"},
-      {broker_sys_interval,60},
-      {conn_force_gc_count,100},
-      {cache_acl,true},
-      {acl_file,"etc/acl.conf"},
-      {allow_anonymous,true},
-      {protocol,[{max_clientid_len,1024},{max_packet_size,262144}]},
-      {client,[{client_idle_timeout,30000},{client_enable_stats,false}]},
-      {session,
-          [{upgrade_qos,false},
-           {max_inflight,32},
-           {retry_interval,20000},
-           {max_awaiting_rel,100000},
-           {await_rel_timeout,20000},
-           {enable_stats,false},
-           {expiry_interval,7200000}]},
-      {queue,
-          [{priority,[]},
-           {type,simple},
-           {max_length,infinity},
-           {low_watermark,0.2},
-           {high_watermark,0.6},
-           {queue_qos0,true}]},
-      {pubsub,[{pool_size,8},{by_clientid,true},{async,true}]},
-      {bridge,[{max_queue_len,10000},{ping_down_interval,1}]},
-      {listeners,
-          [{tcp,1883,
-               [{connopts,[]},
-                {sockopts,[{backlog,1024},{nodelay,true}]},
-                {acceptors,8},
-                {max_clients,1024},
-                {tune_buffer,false}]},
-           {ssl,8883,
-               [{sslopts,
-                    [{versions,['tlsv1.2','tlsv1.1',tlsv1]},
-                     {keyfile,"etc/certs/key.pem"},
-                     {certfile,"etc/certs/cert.pem"}]},
-                {connopts,[]},
-                {sockopts,[{nodelay,true}]},
-                {acceptors,4},
-                {max_clients,512}]},
-           {http,8083,
-               [{connopts,[]},
-                {sockopts,[{nodelay,true}]},
-                {acceptors,4},
-                {max_clients,64}]},
-           {https,8084,
-               [{sslopts,
-                    [{keyfile,"etc/certs/key.pem"},
-                     {certfile,"etc/certs/cert.pem"}]},
-                {connopts,[]},
-                {sockopts,[{nodelay,true}]},
-                {acceptors,4},
-                {max_clients,64}]}]},
-      {sysmon,
-          [{long_gc,false},
-           {long_schedule,240},
-           {large_heap,8388608},
-           {busy_port,false},
-           {busy_dist_port,true}]}]},
-   {kvs, [{dba,store_mnesia},
-        {schema, [kvs_user, kvs_acl, kvs_feed, kvs_subscription, emqttd_kvs ]} ]}
-].

+ 15 - 0
priv/nitro/priv/ssl/fullchain.pem

@@ -0,0 +1,15 @@
+-----BEGIN CERTIFICATE-----
+MIICVTCCAb6gAwIBAgIJAICWQlLAMuszMA0GCSqGSIb3DQEBBQUAMD8xCzAJBgNV
+BAYTAlVTMQswCQYDVQQIDAJDQTETMBEGA1UECgwKQmxvY2tjaGFpbjEOMAwGA1UE
+AwwFU1lOUkMwHhcNMTkwMzI4MDAyMTM1WhcNMjkwMzI1MDAyMTM1WjBDMQswCQYD
+VQQGEwJVUzELMAkGA1UECAwCQ0ExEzARBgNVBAoMCkJsb2NrY2hhaW4xEjAQBgNV
+BAMMCWxvY2FsaG9zdDCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA3VBLAE8g
+FcHh+inxD/8N58HOazuQ5P2KTYr0jQo6aii1QgPHpPkWLX1UwxVn3oLLsjZa9iJ9
+fSAQlQyx6k39SQJRlcrUy5LZSRcT4bNFdXfGkFw1HyrBisG7Q8NHvwaiqTGMJHRG
+XniUWjrFGjxfXhJIsp8lwk8kDyLxEegi7zcCAwEAAaNVMFMwUQYDVR0RBEowSIIJ
+bG9jYWxob3N0gg13d3cubG9jYWxob3N0ggxteC5sb2NhbGhvc3SCDnhtcHAubG9j
+YWxob3N0gg5tcXR0LmxvY2FsaG9zdDANBgkqhkiG9w0BAQUFAAOBgQBIB5bN/Lcq
+IwC+NFdVZpjgHqc+3VtLRKk5KD5q2qmlrFQuS6l4l4Cfoac2aF+P+Ns0ZwHW+7f1
+7qIg1nq2/XRJB98QL93rBN0dMKqJTp9i2/KKnGCb3t0/llCMaNQAuG+amXj2FjT3
+U4sv18fM9d6fYYC0PAnFvfwiDHfX38F/1w==
+-----END CERTIFICATE-----

+ 15 - 0
priv/nitro/priv/ssl/privkey.pem

@@ -0,0 +1,15 @@
+-----BEGIN RSA PRIVATE KEY-----
+MIICXAIBAAKBgQDdUEsATyAVweH6KfEP/w3nwc5rO5Dk/YpNivSNCjpqKLVCA8ek
++RYtfVTDFWfegsuyNlr2In19IBCVDLHqTf1JAlGVytTLktlJFxPhs0V1d8aQXDUf
+KsGKwbtDw0e/BqKpMYwkdEZeeJRaOsUaPF9eEkiynyXCTyQPIvER6CLvNwIDAQAB
+AoGBAKDpGj8VSLzJBSbAi/cXeOLCtPSekJEODxqmJ3zMrQA2rONcoDHAsXFNqO1W
+iPjtnHDsuGIxXZA2Whgk7M7w+XBbbZ5iYpDQHgj50NPw2oHiC44TEJTmm7HJTNu3
+cp25tu/HajLZq3V3eZ88FoQRZCKGr+19u1gzyqIucZ0tES0RAkEA+YiF9Bc4akf5
+TFHwycocbV4kM7lIb76MsCzd4XcGEsNEvMXv2jGcR++4Eh+9VKORwYspT0rYFf1Y
+FvAE6tktGwJBAOMMjWTyGczzeOc7oTJMY10YBFNik9NeEKmxA1EAwdOEDT9qJAil
+SJ2qu5gCNbJ4Lh9zV1E0W1c2F17DaJvGdBUCQH5rx4nh1cgqzMf436gsSHi0cFzw
+Kx3KCVccdBFNjvskiQemtJzz83ySm8w63l4qPKc0zOoKPi3t25pLYgJloy8CQACq
+SL/C9dBj5jbHNfGvx5q+N0UHROeZnvLgUeIq3maAPImzBegAk/XiSipn10BumbP9
+4oOaY6odvnPInsXWDwECQE9SHOdNOiO7GQfgqwLH812iWtT59EIQRbqwGgRHBCkP
+5FYWzg7jRvKsGkM6WspAZ9AlUe9yP7YWVDphvi7iNWw=
+-----END RSA PRIVATE KEY-----

+ 0 - 0
priv/web/priv/static/index.htm → priv/nitro/priv/static/index.htm


+ 0 - 0
priv/web/priv/static/login.htm → priv/nitro/priv/static/login.htm


+ 0 - 0
priv/mqtt/priv/static/synrc.css → priv/nitro/priv/static/synrc.css


+ 0 - 0
priv/web/priv/templates/message.html → priv/nitro/priv/templates/message.html


+ 17 - 0
priv/nitro/rebar.config

@@ -0,0 +1,17 @@
+{deps, [{cowboy, ".*", {git, "git://github.com/voxoz/cowboy2", []}},
+        {active, ".*", {git, "git://github.com/synrc/active",  []}},
+        {nitro,  ".*", {git, "git://github.com/synrc/nitro",   []}},
+        {syn,    ".*", {git, "git://github.com/ostinelli/syn", []}},
+        {n2o,    ".*", {git, "git://github.com/synrc/n2o",     []}},
+        {rocksdb,".*", {git, "git://github.com/enterprizing/rocksdb", []}},
+        {kvs,    ".*", {git, "git://github.com/synrc/kvs",     []}}]}.
+
+{relx, [{release, {sample, "0.7.0"},[sample]},
+        {dev_mode, false},
+        {sys_config, "sys.config"},
+        {vm_args, "vm.args"},
+        {include_erts, true},
+        {extended_start_script, true}]}.
+
+{shell,[{config, "sys.config"},
+        {apps, [sample]}]}.

+ 39 - 0
priv/nitro/src/index.erl

@@ -0,0 +1,39 @@
+-module(index).
+-compile(export_all).
+-include_lib("nitro/include/nitro.hrl").
+-include_lib("n2o/include/n2o.hrl").
+-include_lib("kvs/include/cursors.hrl").
+event(init) ->
+    Room = n2o:session(room),
+    Key = {topic,Room},
+    n2o:reg(Key),
+    n2o:reg(n2o:sid()),
+    nitro:clear(history),
+    nitro:update(logout, #button{id=logout, body="Logout " ++ n2o:user(), postback=logout}),
+    nitro:update(heading, [#h2{id=heading, body=Room}]),
+    nitro:update(upload, #upload{}),
+    nitro:update(send, #button{id=send, body= <<"Chat">>, postback=chat, source=[message] }),
+    [ event(#client{data=E})  || E <- lists:reverse(kvs:feed(Key)) ];
+event(logout) ->
+    n2o:user([]),
+    nitro:redirect("/app/login.htm");
+event(chat) ->
+    chat(nitro:q(message),nitro);
+event(#client{data={'$msg',_,_,_,User,Message}}) ->
+    HTML = nitro:to_list(Message),
+    nitro:wire(#jq{target=message,method=[focus,select]}),
+    nitro:insert_top(history, nitro:render(#message{body=[#author{body=User},nitro:jse(HTML)]}));
+event(#ftp{sid=Sid,filename=Filename,status={event,stop}}=Data) ->
+    Name = hd(lists:reverse(string:tokens(nitro:to_list(Filename),"/"))),
+    chat(nitro:render(#link{href=iolist_to_binary(["/app/",Sid,"/",Name]),body=Name}),index);
+event(Event) ->
+    ok.
+
+jse(X) -> X.
+chat(Message,F) ->
+    Room = n2o:session(room),
+    User = n2o:user(),
+    Msg = {'$msg', kvs:seq([], []), [], [], User, F:jse(Message)},
+    kvs:append(Msg,{topic,Room}),
+    n2o:send({topic, Room}, #client{data = Msg}).
+

+ 1 - 2
priv/web/src/login.erl → priv/nitro/src/login.erl

@@ -1,6 +1,5 @@
 -module(login).
 -compile(export_all).
--include_lib("kvs/include/feed.hrl").
 -include_lib("nitro/include/nitro.hrl").
 -include_lib("n2o/include/n2o.hrl").
 
@@ -13,7 +12,7 @@ event(login) ->
     Room = nitro:to_list(nitro:q(pass)),
     n2o:user(User),
     n2o:session(room,Room),
-    ?LOG_INFO("User: ~p",[User]),
     nitro:redirect("/app/index.htm?room="++Room),
     ok;
+
 event(_) -> [].

+ 3 - 3
priv/web/src/routes.erl → priv/nitro/src/routes.erl

@@ -5,14 +5,14 @@
 finish(State, Ctx) -> {ok, State, Ctx}.
 init(State, #cx{req=Req}=Cx) ->
     #{path:=Path}=Req,
-    Fix  = route_prefix(Path),
-    ?LOG_INFO("Route: ~p~n",[{Fix,Path}]),
-    {ok, State, Cx#cx{path=Path,module=Fix}}.
+    {ok, State, Cx#cx{path=Path,module=route_prefix(Path)}}.
 
 route_prefix(<<"/ws/",P/binary>>) -> route(P);
 route_prefix(<<"/",P/binary>>) -> route(P);
 route_prefix(P) -> route(P).
 
+% Don't use fancy routers, be like poor man's pattern mach.
+
 route(<<>>)              -> login;
 route(<<"index",_/binary>>) -> index;   % github static
 route(<<"login",_/binary>>) -> login;   % github static

+ 8 - 0
priv/nitro/src/sample.app.src

@@ -0,0 +1,8 @@
+{application, sample,
+    [{description, "SAMPLE WebSocket application"},
+     {vsn, "0.7.0"},
+     {registered, []},
+     {applications, [public_key,asn1,kernel,stdlib,mnesia,ranch,cowboy,nitro,syntax_tools,compiler,xmerl,kvs,syn,n2o]},
+     {mod, { sample, []}},
+     {env, []},
+     {modules,[]}]}.

+ 1 - 5
priv/web/src/sample.erl → priv/nitro/src/sample.erl

@@ -8,8 +8,4 @@ start()    -> start(normal,[]).
 start(_,_) -> cowboy:start_tls(http,n2o_cowboy:env(?MODULE),
                  #{env=>#{dispatch=>n2o_cowboy2:points() }}),
               supervisor:start_link({local,sample},sample,[]).
-init([])   -> kvs:join(), {ok, {{one_for_one, 5, 10}, [] }}.
-port()     -> application:get_env(n2o,port,8001).
-rebar3()   -> {ok,[{_,R,L}]}=file:consult(code:lib_dir(sample)++"/ebin/sample.app"),
-              [ application:start(X) || X <- proplists:get_value(applications,L,[]) ],
-              application:start(R).
+init([])   -> kvs:join(), syn:init(), {ok, {{one_for_one, 5, 10}, [] }}.

+ 16 - 0
priv/nitro/sys.config

@@ -0,0 +1,16 @@
+[
+ {n2o, [{port,8001},
+        {app,sample},
+        {upload,"./priv/static/"},
+        {routes,routes},
+        {mq,n2o_syn},
+        {formatter,n2o_bert},
+        {protocols,[n2o_heart,n2o_nitro,n2o_ftp]},
+        {session,n2o_session},
+        {origin,<<"*">>},
+        {pickler,n2o_secret},
+        {event,pickle}]},
+ {kvs, [{dba,kvs_mnesia},
+        {dba_st,kvs_stream},
+        {schema, [kvs, kvs_stream ]} ]}
+].

+ 1 - 1
priv/mqtt/vm.args → priv/nitro/vm.args

@@ -9,5 +9,5 @@
 +K true
 -smp auto
 -setcookie emq_dist_cookie
--name mq@127.0.0.1
+-name sample-1@127.0.0.1
 +zdbbl 32768

+ 0 - 201
priv/web/priv/static/synrc.css

@@ -1,201 +0,0 @@
-* {
-    margin: 0;
-    padding: 0;
-    box-sizing: border-box;
-}
-
-body {
-    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol";
-    color: #737373;
-    margin: 0;
-}
-
-button {
-    padding: 10px 20px;
-    font-size: 18px;
-    color: white;
-    background: #4990E2;
-    font-weight: bold;
-    font-family: inherit;
-    line-height: 1;
-    border: none;
-    text-transform: uppercase;
-    border-radius: 4px;
-    box-shadow: 0px 10px 15px -5px rgba(100, 100, 100, .35);
-    margin: 10px;
-}
-
-button:hover {
-    background: #1a84ff;
-}
-
-button:focus {
-    outline: none;
-    background: #1f63b2;
-}
-
-img {
-    width: 140px;
-    margin: auto;
-    padding: 0;
-    display: block;
-}
-
-.login {
-    display: flex;
-    flex-direction: column;
-    height: 100vh;
-    align-items: center;
-}
-
-.login h1 {
-    color: #4990E2;
-    font-size: 34px;
-    margin: 30px 0;
-    text-shadow: 1px 2px 8px rgba(100, 100, 100, .3);
-}
-
-.login img {
-    margin-top: 20px;
-}
-
-.login form {
-    width: 300px;
-    background: white;
-    padding: 20px;
-    display: flex;
-    justify-content: center;
-    flex-wrap: wrap;
-    border-radius: 4px;
-    box-shadow: 0px 4px 40px rgba(100, 100, 100, .35);
-}
-
-.login label {
-    width: 100%;
-    display: block;
-    font-size: 18px;
-}
-
-.login input {
-    width: 100%;
-    display: block;
-    border: none;
-    font-family: inherit;
-    color: inherit;
-    font-size: 19px;
-    line-height: 1.4;
-    border-bottom: 1px solid #4990E2;
-    margin-bottom: 20px;
-}
-
-.login input:focus {
-    outline: none;
-}
-
-.login footer {
-    margin-top: auto;
-    margin-bottom: 30px;
-    font-size: 18px;
-    background: white;
-    padding: 4px 10px;
-    border-radius: 4px;
-    box-shadow: 0px 4px 40px rgba(100, 100, 100, .35);
-}
-
-.chat {
-    text-align: center;
-}
-
-.chat header {
-    display: inline-block;
-    max-width: 200px;
-    vertical-align: top;
-    margin-right: 50px;
-    margin-top: 20px;
-}
-
-.chat img {
-    margin-bottom: 20px;
-}
-
-.chat h2 {
-    color: #4990E2;
-    font-size: 28px;
-    margin: 10px 0;
-    text-shadow: 1px 2px 8px rgba(100, 100, 100, .3);
-}
-
-.chat main {
-    display: inline-block;
-    vertical-align: top;
-    text-align: left;
-    max-width: 600px;
-    margin: 40px 10px;
-}
-
-.chat form {
-    display: flex;
-    flex-wrap: wrap;
-    justify-content: space-between;
-    margin: 0px 0 70px;
-}
-
-.chat textarea:focus {
-    outline: none;
-}
-
-.chat textarea {
-    width: 100% !important;
-    margin-bottom: 20px;
-    border: none;
-    font-family: inherit;
-    color: inherit;
-    font-size: 18px;
-    line-height: 1.2;
-    padding: 8px 16px;
-    border-radius: 4px;
-    box-shadow: 0px 4px 40px rgba(100, 100, 100, .35);
-}
-
-::-webkit-input-placeholder {
-    color: #ccc;
-}
-
-::-moz-placeholder {
-    color: #ccc;
-}
-
-::-ms-input-placeholder {
-    color: #ccc;
-}
-
-.chat span>button {
-    margin-right: 5px;
-}
-
-history {
-    display: block;
-}
-
-message {
-    display: block;
-    font-size: 18px;
-    background: white;
-    padding: 8px 16px;
-    margin: 15px 0;
-    border-radius: 4px;
-    box-shadow: 0px 4px 40px rgba(100, 100, 100, .35);
-}
-
-author {
-    display: inline;
-    font-weight: bold;
-}
-
-author:empty {
-    display: none;
-}
-
-author::after {
-    content: ': ';
-}

+ 0 - 16
priv/web/rebar.config

@@ -1,16 +0,0 @@
-{deps, [
-    {gproc,  ".*", {git, "git://github.com/voxoz/gproc",        []}},
-    {cowboy, ".*", {git, "git://github.com/voxoz/cowboy2",      []}},
-    {erlydtl,".*", {git, "git://github.com/voxoz/erlydtl",      []}},
-    {active, ".*", {git, "git://github.com/synrc/active",       []}},
-    {nitro,  ".*", {git, "git://github.com/synrc/nitro",        []}},
-    {n2o,    ".*", {git, "git://github.com/synrc/n2o",          []}},
-    {kvs,    ".*", {git, "git://github.com/synrc/kvs",          []}}
-]}.
-{erlydtl_opts, [
-    {doc_root,   "priv/templates"},
-    {out_dir,    "ebin"},
-    {compiler_options, [report, return, debug_info]},
-    {source_ext, ".html"},
-    {module_ext, "_view"}
-]}.

+ 0 - 42
priv/web/src/index.erl

@@ -1,42 +0,0 @@
--module(index).
--compile(export_all).
--include_lib("kvs/include/entry.hrl").
--include_lib("nitro/include/nitro.hrl").
--include_lib("n2o/include/n2o.hrl").
-event(init) ->
-    Room = n2o:session(room),
-    io:format("Room: ~p~n",[Room]),
-    n2o:reg({topic,Room}),
-    Sid = (get(context))#cx.session,
-    n2o:reg(Sid),
-    nitro:clear(history),
-    nitro:update(logout, #button{id=logout, body="Logout " ++ n2o:user(), postback=logout}),
-    nitro:update(heading, #h2{id=heading, body=Room}),
-    nitro:update(upload, #upload{}),
-    nitro:update(send, #button{id=send, body= <<"Chat">>, postback=chat, source=[message] }),
-    [ event({client,{E#entry.from,E#entry.media}})
-      || E <- lists:reverse(kvs:entries(kvs:get(feed,{room,Room}),entry,10)) ];
-event(logout) ->
-    n2o:user([]),
-    nitro:redirect("/app/login.htm");
-event(chat) ->
-    User    = n2o:user(),
-    Room    = n2o:session(room),
-    Message = nitro:q(message),
-    ?LOG_INFO("Chat pressed: ~p~n",[{Room,Message,User}]),
-    kvs:add(#entry{id=kvs:next_id("entry",1),from=n2o:user(),
-                   feed_id={room,Room},media=Message}),
-    n2o:send({topic,Room},#client{data={User,Message}});
-event(#client{data={User,Message}}) ->
-    HTML = nitro:to_list(Message),
-    nitro:wire(#jq{target=message,method=[focus,select]}),
-    DTL = #dtl{file="message",app=sample,bindings=[{user,User},{color,"gray"},{message,HTML}]},
-    nitro:insert_top(history, nitro:jse(nitro:render(DTL)));
-event(#ftp{sid=Sid,filename=Filename,status={event,stop}}=Data) ->
-    Name = hd(lists:reverse(string:tokens(nitro:to_list(Filename),"/"))),
-    erlang:put(message,nitro:render(#link{href=iolist_to_binary(["/app/",Sid,"/",Name]),body=Name})),
-    ?LOG_INFO("FTP Delivered ~p~n",[Data]),
-    event(chat);
-event(Event) ->
-    ?LOG_INFO("Event: ~p", [Event]),
-    ok.

+ 0 - 8
priv/web/src/sample.app.src

@@ -1,8 +0,0 @@
-{application, sample,
-    [{description, "sample WebSocket application"},
-     {vsn, "5.11"},
-     {registered, []},
-     {applications, [public_key,asn1,kernel,stdlib,mnesia,
-                     kvs,cowlib,ranch,cowboy,gproc,n2o]},
-     {mod, { sample, []}},
-     {env, []}]}.

+ 0 - 27
priv/web/sys.config

@@ -1,27 +0,0 @@
-[
- {n2o, [{port,8001},
-        {cowboy_spec,cow2},
-        {app,sample},
-        {upload,"./priv/static/"},
-        {routes,routes},
-        {mq,n2o_gproc},
-        {formatter,n2o_bert},
-        {protocols,[n2o_heart,n2o_nitro,n2o_ftp]},
-        {minify,{"priv/static",
-                ["deps/n2o/priv/bullet.js",
-                 "deps/n2o/priv/n2o.js",
-                 "deps/n2o/priv/ftp.js",
-                 "deps/n2o/priv/bert.js",
-                 "deps/n2o/priv/nitrogen.js",
-                 "deps/n2o/priv/utf8.js"]}},
-        {log_modules,[config,n2o,sample,index,login,routes,n2o_heart,
-                      n2o_nitro,n2o_proto,n2o_cowboy,n2o_stream]},
-        {log_backend,n2o_io},
-        {session,n2o_session},
-        {origin,<<"*">>},
-        {pickler,n2o_secret},
-        {erroring,n2o_error},
-        {event,pickle}]},
- {kvs, [{dba,store_mnesia},
-        {schema, [kvs_user, kvs_acl, kvs_feed, kvs_subscription ]} ]}
-].

+ 0 - 13
priv/web/vm.args

@@ -1,13 +0,0 @@
-+W w
--kernel net_ticktime 60
--env ERL_CRASH_DUMP log/crash.dump
-+e 256000
--env ERL_FULLSWEEP_AFTER 1000
-+Q 65536
-+P 256000
-+A 32
-+K true
--smp auto
--setcookie emq_dist_cookie
--name mq@127.0.0.1
-+zdbbl 32768

+ 9 - 0
priv/zero/src/sample.app.src

@@ -0,0 +1,9 @@
+{application, sample,
+ [
+  {description, "sample application"},
+  {vsn, "0.8.0"},
+  {registered, []},
+  {applications, [kernel,stdlib]},
+  {mod, { sample, []}},
+  {env, []}
+ ]}.

+ 9 - 0
priv/zero/src/sample.erl

@@ -0,0 +1,9 @@
+-module(sample).
+-compile(export_all).
+-behaviour(application).
+-behaviour(supervisor).
+-export([start/2, stop/1, init/1]).
+
+start(_, _) -> supervisor:start_link({local, ?MODULE}, ?MODULE, []).
+stop(_) -> ok.
+init([]) -> {ok, { {one_for_one, 5, 10}, []} }.

+ 1 - 1
src/mad.erl

@@ -71,7 +71,7 @@ help()            -> info("MAD Manage Dependencies ~s~n",[?VERSION]),
                      info("~n"),
                      info("    invoke = mad | mad list~n"),
                      info("      list = []  | command [options] list ~n"),
-                     info("   command = app [web|mqtt] <name> | deps | clean | compile | strip~n"),
+                     info("   command = app [nitro|zero] <name> | deps | clean | compile | strip~n"),
                      info("           | bundle [beam|script] <name> | man <html|check|groff> | repl~n"),
                      info("           | start | stop | attach | static <min> | get <repo> | up [name] ~n"),
                      return(false).

+ 4 - 2
src/mad_man.erl

@@ -12,7 +12,9 @@ man(["html"]) ->
 man(["check"]) ->
    case lists:all(fun(X) -> element(1,X) == ok end, [ check(I)
     || I <- filelib:wildcard("man/**/*.htm")
-         ++ filelib:wildcard("*.html") ]) of
+         ++ filelib:wildcard("articles/**/*.htm")
+         ++ filelib:wildcard("*.html")
+         ++ filelib:wildcard("*.htm") ]) of
         true -> {ok,check};
         false -> {error,check} end.
 
@@ -34,7 +36,7 @@ generate(Lower,Temp) ->
     Gen = lists:concat(["man/",Lower,".htm"]),
     case file:read_file_info(Gen) of
          {error,_} -> write(Gen, Bin);
-         {ok,A} -> io:format("man: file ~p already exists.~n",[Gen])
+         {ok,_} -> io:format("man: file ~p already exists.~n",[Gen])
                   % case element(2,A) > size(Bin) of
                   %      true -> skip;
                   %      false -> write(Gen,Bin) end