1 (function (){'use strict';
4 // note that how default values are defined/used may change
15 var PROTO1 = "x-afb-ws-json1";
17 // Definition of the Angular module
18 var AfbClientModule = angular.module('AfbClient', []);
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));
27 // prototype for handling context by uuid and token
28 function AfbContext(refid, params) {
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;
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); },
44 get: function(method, query) { return $http.get(this.uhttp+method, mixtu(this, query)); },
47 post: function(method, query) { return $http.post(this.uhttp+method, mixtu(this, query)); }
50 // get the current websocket
51 function getws(ctxt) {
52 return ctxt.ws || (ctxt.ws = new AfbWebSocket(ctxt));
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);
60 // prototype for websocket
61 function AfbWebSocket(ctxt) {
62 var protos = [ PROTO1 ];
64 var url = "ws:" + ctxt.refid + ctxt.uws;
65 var q = ctxt.uuid ? ("?x-afb-uuid=" + ctxt.uuid) : "";
67 q = (q ? (q + "&") : "?") + ("x-afb-token=" + ctxt.token);
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);
77 this.onabort = onabort;
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));
91 addEvent: function (name, handler) {
92 (this.awaitens[name] || (this.awaitens[name] = [])).push(handler);
94 removeEvent: function (name, handler) {
95 var a = this.awaitens[name];
97 var i = a.indexOf(handler);
98 if (i >= 0) a.splice(i, 1);
104 function onmessage(ev) {
105 var obj = angular.fromJson(ev.data);
109 this.context.token = obj[3];
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;
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("/");
123 a = awaitens[name.substring(0,i)];
124 if (a) a.forEach(function(handler){handler(data);});
127 if (a) a.forEach(function(handler){handler(data);});
130 function reply(pendings, id, ans, offset) {
131 if (id in pendings) {
132 var p = pendings[id];
149 AFB_websocket = function(onopen, onabort) {
152 function onerror(event) {
153 var f = this.onabort;
159 this.onerror && this.onerror(this);
162 function onopen(event) {
169 function onclose(event) {
170 for (var id in this.pendings) {
171 var ferr = this.pendings[id].onerror;
172 ferr && ferr(null, this);
175 this.onclose && this.onclose();
182 function call(method, request) {
188 // Factory is a singleton and share its context within all instances.
189 AfbClientModule.factory('AppCall', function ($http, AppConfig, $log) {
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);