71338cf9c6390f865fcb40a4eb68414d5fd1753e
[src/app-framework-binder.git] / test / AfbAngular.js
1 (function (){'use strict';
2
3   // some default values
4   // note that how default values are defined/used may change
5   var defaults = {
6       token: '123456789',
7       api: '/api'
8     };
9
10   var CALL = 2;
11   var RETOK = 3;
12   var RETERR = 4;
13   var EVENT = 5;
14
15   var PROTO1 = "x-afb-ws-json1";
16
17   // Definition of the Angular module
18   var AfbClientModule = angular.module('AfbClient', []);
19
20   // The instanciation of the module
21   AfbClientModule.factory('AfbClient', [ '$location', function ($location) {
22     var refid = $location.host();
23     var params = $location.search();
24     return clients[refid] || (client[refid] = new AfbContext(refid, params));
25   }]);
26
27   // prototype for handling context by uuid and token
28   function AfbContext(refid, params) {
29     this.refid = refid;
30     this.api = params.api || defaults.api;
31     this.uhttp = params.uhttp || this.api+'/';
32     this.uws = params.uws || this.api;
33     this.token = params.token || defaults.token;
34     this.uuid = params.uuid;
35     this.ws = null;
36   }
37
38   // prototype of functions linked to AfbContext object
39   AfbContext.prototype = {
40     // call using websockets
41     call: function(method, query) { return getws(this).call(method, query); },
42
43     // call using get
44     get: function(method, query) { return $http.get(this.uhttp+method, mixtu(this, query)); },
45
46     // call using post
47     post: function(method, query) { return $http.post(this.uhttp+method, mixtu(this, query)); }
48   };
49
50   // get the current websocket
51   function getws(ctxt) {
52     return ctxt.ws || (ctxt.ws = new AfbWebSocket(ctxt));
53   }
54
55   // inserts the current token in the answer
56   function mixtu(ctxt, query) {
57     return ("token" in query) ? query : angular.extend({token:ctxt.token},query);
58   }
59
60   // prototype for websocket
61   function AfbWebSocket(ctxt) {
62     var protos = [ PROTO1 ];
63     this.context = ctxt;
64     var url = "ws:" + ctxt.refid + ctxt.uws;
65     var q = ctxt.uuid ? ("?x-afb-uuid=" + ctxt.uuid) : "";
66     if (ctxt.token)
67       q = (q ? (q + "&") : "?") + ("x-afb-token=" + ctxt.token);
68     this.pendings = {};
69     this.awaitens = {};
70     this.counter = 0;
71     this.ws = new WebSocket(url + q, protos);
72     this.ws.onopen = onopen.bind(this);
73     this.ws.onerror = onerror.bind(this);
74     this.ws.onclose = onclose.bind(this);
75     this.ws.onmessage = onmessage.bind(this);
76     this.onopen = onopen;
77     this.onabort = onabort;
78   }
79
80   AfbWebSocket.prototype = {
81     call: function(method, query) {
82         return new Promise((function(resolve, reject){
83           var id = String(this.counter = 4095 & (this.counter + 1));
84           while (id in this.pendings) id = String(this.counter = 4095 & (this.counter + 1));
85           this.pendings[id] = [ resolve, reject ];
86           var arr = [CALL, id, method, request ];
87           var tok = this.context.token; if (tok) arr.push(tok);
88           this.ws.send(angular.toJson(arr, 0));
89         }).bind(this));
90       },
91     addEvent: function (name, handler) {
92         (this.awaitens[name] || (this.awaitens[name] = [])).push(handler);
93       },
94     removeEvent: function (name, handler) {
95         var a = this.awaitens[name];
96         if (a) {
97           var i = a.indexOf(handler);
98           if (i >= 0) a.splice(i, 1);
99         }
100       }
101
102   };
103
104   function onmessage(ev) {
105     var obj = angular.fromJson(ev.data);
106     var id = obj[1];
107     var ans = obj[2];
108     if (obj[3])
109       this.context.token = obj[3];
110     switch (obj[0]) {
111     case RETOK:  reply(this.pendings, id, ans, 0); break; 
112     case RETERR: reply(this.pendings, id, ans, 1); break; 
113     case EVENT:   fire(this.awaitens, id, ans);    break; 
114
115     }
116   }
117
118   function fire(awaitens, name, data) {
119     var a = awaitens[name];
120     if (a) a.forEach(function(handler){handler(data);});
121     var i = name.indexOf("/");
122     if (i >= 0) {
123       a = awaitens[name.substring(0,i)];
124       if (a) a.forEach(function(handler){handler(data);});
125     }
126     a = awaitens["*"];
127     if (a) a.forEach(function(handler){handler(data);});
128   }
129
130   function reply(pendings, id, ans, offset) {
131     if (id in pendings) {
132       var p = pendings[id];
133       delete pendings[id];
134       var f = p[offset];
135       if (f) f(ans);
136     }
137   }
138
139
140
141
142 /*
143
144
145
146
147
148
149         AFB_websocket = function(onopen, onabort) {
150         }
151
152         function onerror(event) {
153                 var f = this.onabort;
154                 if (f) {
155                         delete this.onopen;
156                         delete this.onabort;
157                         f && f(this);
158                 }
159                 this.onerror && this.onerror(this);
160         }
161
162         function onopen(event) {
163                 var f = this.onopen;
164                 delete this.onopen;
165                 delete this.onabort;
166                 f && f(this);
167         }
168
169         function onclose(event) {
170                 for (var id in this.pendings) {
171                         var ferr = this.pendings[id].onerror;
172                         ferr && ferr(null, this);
173                 }
174                 this.pendings = {};
175                 this.onclose && this.onclose();
176         }
177
178         function close() {
179                 this.ws.close();
180         }
181
182         function call(method, request) {
183         }
184
185 */
186
187 /*
188   // Factory is a singleton and share its context within all instances.
189   AfbClientModule.factory('AppCall', function ($http, AppConfig, $log) {
190     var myCalls = {
191       get : function(plugin, action, query, callback) {
192         if (!query.token) query.token = AppConfig.session.token; // add token to provided query
193         $http.get('/api/' + plugin + '/' + action , {params: query}).then (callback, callback);
194       }
195     };
196     return myCalls;
197   });
198 */
199
200
201
202
203
204 })();