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 AfbContext.prototype = {
39 call: function(method, query) { return getws(this).call(method, query); },
40 get: function(method, query) { return $http.get(this.uhttp+method, mixtu(this, query)); },
41 post: function(method, query) { return $http.post(this.uhttp+method, mixtu(this, query)); },
44 function getws(ctxt) {
45 return ctxt.ws || (ctxt.ws = new AfbWebSocket(ctxt));
48 function mixtu(ctxt, query) {
49 return ("token" in query) ? query : angular.extend({token:ctxt.token},query);
52 // prototype for websocket
53 function AfbWebSocket(ctxt) {
54 var protos = [ PROTO1 ];
56 var url = "ws:" + ctxt.refid + ctxt.uws;
57 var q = ctxt.uuid ? ("?x-afb-uuid=" + ctxt.uuid) : "";
59 q = (q ? (q + "&") : "?") + ("x-afb-token=" + ctxt.token);
63 this.ws = new WebSocket(url + q, protos);
64 this.ws.onopen = onopen.bind(this);
65 this.ws.onerror = onerror.bind(this);
66 this.ws.onclose = onclose.bind(this);
67 this.ws.onmessage = onmessage.bind(this);
69 this.onabort = onabort;
72 AfbWebSocket.prototype = {
73 call: function(method, query) {
74 return new Promise((function(resolve, reject){
75 var id = String(this.counter = 4095 & (this.counter + 1));
76 while (id in this.pendings) id = String(this.counter = 4095 & (this.counter + 1));
77 this.pendings[id] = [ resolve, reject ];
78 var arr = [CALL, id, method, request ];
79 var tok = this.context.token; if (tok) arr.push(tok);
80 this.ws.send(angular.toJson(arr, 0));
83 addEvent: function (name, handler) {
84 (this.awaitens[name] || (this.awaitens[name] = [])).push(handler);
86 removeEvent: function (name, handler) {
87 var a = this.awaitens[name];
89 var i = a.indexOf(handler);
90 if (i >= 0) a.splice(i, 1);
96 function onmessage(ev) {
97 var obj = angular.fromJson(ev.data);
101 this.context.token = obj[3];
103 case RETOK: reply(this.pendings, id, ans, 0); break;
104 case RETERR: reply(this.pendings, id, ans, 1); break;
105 case EVENT: fire(this.awaitens, id, ans); break;
110 function fire(awaitens, name, data) {
111 var a = awaitens[name];
112 if (a) a.forEach(function(handler){handler(data);});
113 var i = name.indexOf("/");
115 a = awaitens[name.substring(0,i)];
116 if (a) a.forEach(function(handler){handler(data);});
119 if (a) a.forEach(function(handler){handler(data);});
122 function reply(pendings, id, ans, offset) {
123 if (id in pendings) {
124 var p = pendings[id];
140 AFB_websocket = function(onopen, onabort) {
143 function onerror(event) {
144 var f = this.onabort;
150 this.onerror && this.onerror(this);
153 function onopen(event) {
160 function onclose(event) {
161 for (var id in this.pendings) {
162 var ferr = this.pendings[id].onerror;
163 ferr && ferr(null, this);
166 this.onclose && this.onclose();
173 function call(method, request) {
177 // Factory is a singleton and share its context within all instances.
178 AfbClientModule.factory('AppCall', function ($http, AppConfig, $log) {
180 get : function(plugin, action, query, callback) {
181 if (!query.token) query.token = AppConfig.session.token; // add token to provided query
182 $http.get('/api/' + plugin + '/' + action , {params: query}).then (callback, callback);