Publish Vulpes Preview 15 sources for desktop, Android and Tundra

Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
OverSu 2026-09-30 23:13:03 +02:00
commit b38dea0597
25901 changed files with 9982925 additions and 369 deletions

1344
gaia/apps/sms/lib/bridge/client.js Executable file

File diff suppressed because it is too large Load diff

29
gaia/apps/sms/lib/bridge/client.min.js vendored Executable file
View file

@ -0,0 +1,29 @@
var $jscomp={scope:{},global:this},Symbol;$jscomp.initSymbol=function(){$jscomp.global.Symbol||(Symbol=$jscomp.Symbol);$jscomp.initSymbol=function(){}};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(h){return"jscomp_symbol_"+h+$jscomp.symbolCounter_++};$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();Symbol.iterator||(Symbol.iterator=Symbol("iterator"));$jscomp.initSymbolIterator=function(){}};
$jscomp.makeIterator=function(h){$jscomp.initSymbolIterator();if(h[Symbol.iterator])return h[Symbol.iterator]();if(!(h instanceof Array||"string"==typeof h||h instanceof String))throw new TypeError(h+" is not iterable");var d=0;return{next:function(){return d==h.length?{done:!0}:{done:!1,value:h[d++]}}}};$jscomp.arrayFromIterator=function(h){for(var d,g=[];!(d=h.next()).done;)g.push(d.value);return g};$jscomp.arrayFromIterable=function(h){return h instanceof Array?h:$jscomp.arrayFromIterator($jscomp.makeIterator(h))};
$jscomp.arrayFromArguments=function(h){for(var d=[],g=0;g<h.length;g++)d.push(h[g]);return d};$jscomp.inherits=function(h,d){function g(){}g.prototype=d.prototype;h.prototype=new g;h.prototype.constructor=h;for(var l in d)if($jscomp.global.Object.defineProperties){var c=$jscomp.global.Object.getOwnPropertyDescriptor(d,l);void 0!==c&&$jscomp.global.Object.defineProperty(h,l,c)}else h[l]=d[l]};
(function(h){"object"===typeof exports&&"undefined"!==typeof module?module.exports=h():"function"===typeof define&&define.amd?define([],h):("undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:this).bridge=h()})(function(){return function d(g,l,c){function m(f,r){if(!l[f]){if(!g[f]){var k="function"==typeof require&&require;if(!r&&k)return k(f,!0);if(n)return n(f,!0);k=Error("Cannot find module '"+f+"'");throw k.code="MODULE_NOT_FOUND",k;}k=l[f]={exports:{}};
g[f][0].call(k.exports,function(b){var a=g[f][1][b];return m(a?a:b)},k,k.exports,d,g,l,c)}return l[f].exports}for(var n="function"==typeof require&&require,f=0;f<c.length;f++)m(c[f]);return m}({1:[function(d,g,l){var c=g.exports=self.bridge||{};c.client=d("../src/client");"u"!="undefined"[0]?(void 0)([],function(){return c}):self.bridge=c},{"../src/client":2}],2:[function(d,g,l){function c(a,t,b){if(!(this instanceof c))return new c(a,t,b);"object"==typeof a&&(t=a.endpoint,b=a.timeout,a=a.service);
this.id=r();this.service=a;this.timeout=b;this.endpoint=t||this.endpoint;if(!this.endpoint)throw m(1);this.setPort(this.endpoint);this.pending=new Set;this.receiver=q.receiver(this.id).on("_push",this.onPush.bind(this));k("initialized",a)}function m(a,b){for(var e=[],p=1;p<arguments.length;++p)e[p-1]=arguments[p];return Error({1:"an endpoint must be defined",2:'Unable to establish a connection with "'+e[0]+'". Either the target endpoint is not alive or the Service is not `.listen()`ing.',3:'Method "'+
e[0]+"\" didn't get a response. Either the target endpoint is not alive or the Service is not `.listen()`ing."}[a])}var n=d("./message/port-adaptors"),f=d("./emitter"),q=d("./message"),r=d("./utils").uuid;g.exports=c;var k={0:function(){},1:function(a){return performance.mark("["+self.constructor.name+"][Client] - "+a)},2:function(a,b){for(var e=[],p=1;p<arguments.length;++p)e[p-1]=arguments[p];console.log.apply(console,[].concat(["[Client]"+("["+self.constructor.name+"]["+location.pathname+"]")+
' - "'+a+'"'],$jscomp.arrayFromIterable(e)))}}[0],b=self.constructor.name;c.prototype={connect:function(){var a=this;k("connect");if(this.connected)return this.connected;k("connecting...",this.service);var t=new MessageChannel;this.channel=t.port1;this.channel.start();var e={clientId:this.id,service:this.service,originEnv:b};return this.connected=this.message("_connect").set("transfer",[t.port2]).set("data",e).listen(t.port1).send().then(function(b){k("connected",b);b.event.target===a.channel?a.setPort(a.channel):
(a.channel.close(),delete a.channel);a.receiver.listen(a.port)}).catch(function(b){"timeout"==(b&&b.message)&&(b=m(2,a.service),console.error(b.message));throw b;})},disconnect:function(a){var b=this;if(!this.connected)return Promise.resolve();k("disconnecting ...");a={noRespond:a&&a.noRespond,data:this.id};this.cancelPending();return this.message("_disconnect").set(a).send().then(function(){return b.onDisconnected()})},method:function(a,b){for(var e=[],c=1;c<arguments.length;++c)e[c-1]=arguments[c];
var d=this;return this.connect().then(function(){k("method",a);return d.message("_method").set({recipient:d.service,data:{name:a,args:e}}).send()}).then(function(a){return a.value}).catch(function(b){"timeout"==(b&&b.message)&&(b=m(3,a),console.error(b.message));throw b;})},plugin:function(a){a(this,{Emitter:f,uuid:r});return this},message:function(a){var b=this;k("create message",a);var e=q(a).set("port",this.port).set("timeout",this.timeout).on("response",function(){return b.pending.delete(e)}).on("cancel",
function(){return b.pending.delete(e)});this.pending.add(e);return e},cancelPending:function(){k("cancel pending");this.pending.forEach(function(a){a.cancel()});this.pending.clear()},pendingResponded:function(){var a=[];this.pending.forEach(function(b){return a.push(b.responded)});return Promise.all(a)},onPush:function(a){k("on push",a.data);this._emit(a.data.type,a.data.data)},onDisconnected:function(){var a=this;delete this.connected;this.pendingResponded().then(function(){k("disconnected");a.channel&&
a.channel.close();a._emit("disconnected")})},setPort:function(a){k("set port");this.port=n(a)},destroy:function(){var a=this;return this.disconnect().then(function(){a.destroyed||(k("destroy"),a.destroyed=!0,a.receiver.destroy(),a._off(),a.port=a.endpoint=a.receiver=null)})},_on:f.prototype.on,_off:f.prototype.off,_emit:f.prototype.emit};c.prototype.on=function(a,b){var e=this;this.connect().then(function(){k("bind on",a);f.prototype.on.call(e,a,b);e.message("_on").set("noRespond",!0).set("data",
{name:a,clientId:e.id}).send(e.port)});return this};c.prototype.off=function(a,b){var e=this;this.connect().then(function(){f.prototype.off.call(e,a,b);e.message("_off").set("noRespond",!0).set("data",{name:a,clientId:e.id}).send(e.port)});return this}},{"./emitter":3,"./message":4,"./message/port-adaptors":5,"./utils":6}],3:[function(d,g,l){function c(d){if(d)return Object.assign(d,c.prototype)}g.exports=c;c.prototype={on:function(c,d){this._callbacks||(this._callbacks={});this._callbacks[c]||(this._callbacks[c]=
[]);this._callbacks[c].push(d);return this},off:function(c,d){if(this._callbacks)switch(arguments.length){case 0:this._callbacks={};break;case 1:delete this._callbacks[c];break;default:var f=this._callbacks[c];if(!f)return;var g=f.indexOf(d);~g&&f.splice(g,1)}return this},emit:function(c,d){if(this._callbacks)for(var f=this._callbacks[c]||[],f=f.concat(this._callbacks["*"]||[]),g=0;g<f.length;g++)f[g].call(this,d,c);return this}};d=c.prototype;d.off=d.off;d.on=d.on},{}],4:[function(d,g,l){function c(a){this.cancelled=
!1;this.listeners=[];this.deferred=r();this.listen=this.listen.bind(this);this.onMessage=this.onMessage.bind(this);this.onTimeout=this.onTimeout.bind(this);"object"===typeof a?this.setupInbound(a):this.setupOutbound(a);b("initialized",this.type)}function m(a){this.name=a;this.ports=new Set;this.onMessage=this.onMessage.bind(this);this.listen=this.listen.bind(this);this.unlisten=this.unlisten.bind(this);b("receiver initialized",a)}function n(a,b){for(var e=1;e<arguments.length;++e);return Error({1:".send() can only be called once",
2:"response already sent for this message",3:"a port must be defined",4:"timeout"}[a])}var f=d("./port-adaptors"),q=d("../emitter");d=d("../utils");var r=d.deferred,k=d.uuid;l=g.exports=function(a){return new c(a)};l.receiver=function(a,b){return new m(a,b)};l.Receiver=m;l.Message=c;var b={0:function(){},1:function(a){return performance.mark("["+self.constructor.name+"][Message] - "+a)},2:function(a,b){for(var e=[],c=1;c<arguments.length;++c)e[c-1]=arguments[c];console.log.apply(console,[].concat(["[Message]"+
("["+self.constructor.name+"]["+location.pathname+"]")+' - "'+a+'"'],$jscomp.arrayFromIterable(e)))}}[0];c.prototype={setupOutbound:function(a){this.id=k();this.type=a;this.sent=!1;this.recipient="*"},setupInbound:function(a){b("inbound");this.hasResponded=!1;this.setSourcePort(a.source||a.target);this.event=a;Object.assign(this,a.data)},setSourcePort:function(a){b("set source",a.constructor.name);this.sourcePort=f(a,{ready:!0});return this},set:function(a,c){b("set",a,c);"object"==typeof a?Object.assign(this,
a):this[a]=c;return this},serialize:function(){return{id:this.id,type:this.type,data:this.data,recipient:this.recipient,noRespond:this.noRespond}},preventDefault:function(){b("prevent default");this.defaultPrevented=!0},send:function(a){b("send",this.type);if(this.sent)throw n(1);var c=this.serialize(),e=!this.noRespond;this.port=a?f(a):this.port;if(!this.port)throw n(3);e?(this.listen(this.port),this.setResponseTimeout()):this.deferred.resolve();this.port.postMessage(c,this.getTransfer());b("sent",
c);return this.deferred.promise},setResponseTimeout:function(){!1!==this.timeout&&(this._timer=setTimeout(this.onTimeout,this.timeout||2E3))},clearResponseTimeout:function(){clearTimeout(this._timer)},getTransfer:function(){return this.transfer||this.event&&this.event.ports},onMessage:function(a){if(a.data.response&&a.data.id===this.id&&!this.cancelled)this.onResponse(a)},onTimeout:function(){b("response timeout",this.type);this.silentTimeout||this.deferred.reject(n(4));this.teardown()},listen:function(a){b("add response listener",
a);a=f(a);a.addListener(this.onMessage,this.listen);this.listeners.push(a);return this},unlisten:function(){var a=this;b("remove response listeners");this.listeners.forEach(function(b){return b.removeListener(a.onMessage)});this.listeners=[]},cancel:function(){this.teardown();this.cancelled=!0;this.emit("cancel")},teardown:function(){this.clearResponseTimeout();this.unlisten()},respond:function(a){function c(a){b("resolve",a);d({type:"resolve",value:a})}function e(a){a:switch(a&&a.constructor.name){case "DOMException":case "Error":a=
{message:a.message};break a;case "DOMError":a={message:a.message,name:a.name};break a}b("reject",a);d({type:"reject",value:a})}function d(a){f.response=a;f.sourcePort.postMessage({id:f.id,response:a},f.transfer);b("responded with:",a)}b("respond",a,this.id);if(this.hasResponded)throw n(2);if(this.sourcePort&&!this.noRespond){this.hasResponded=!0;var f=this;this.error&&e(this.error);Promise.resolve(a).then(c,e).catch(e)}},forward:function(a){var c=this;b("forward");return this.set("silentTimeout",
!0).send(a).then(function(a){return c.respond(a.value)})},onResponse:function(a){b("on response",a.data);var c=a.data.response,e="reject"==c.type?c.value:c;c.event=a;this.response=c;this.teardown();this.deferred[this.response.type](e);this.emit("response",c)}};q(c.prototype);m.prototype={listen:function(a){b("listen");a=f(a||self,{receiver:!0});if(!this.ports.has(a))return a.addListener(this.onMessage,this.listen),this.ports.add(a),this},unlisten:function(){var a=this;b("unlisten");this.ports.forEach(function(b){return b.removeListener(a.onMessage)})},
onMessage:function(a){if(a.data.id&&a.data.type&&this.isRecipient(a.data.recipient)&&(b("receiver on message",a.data),a=new c(a),this.emit("message",a),!a.defaultPrevented))try{this.emit(a.type,a)}catch(d){throw a.error=d,a.respond(),d;}},isRecipient:function(a){return a==this.name||"*"==a||"*"==this.name},destroy:function(){this.unlisten();delete this.name;return this}};q(m.prototype)},{"../emitter":3,"../utils":6,"./port-adaptors":5}],5:[function(d,g,l){function c(b){this.target=b}function m(b,
a,c){b.addEventListener(a,c)}function n(b,a,c){a={data:a,source:self};c&&(a.ports=c);b.dispatchEvent(new MessageEvent("message",a))}var f=d("../utils").deferred;g.exports=function(b,a){if(!b)throw Error({1:"target is undefined"}[1]);if(b&&b.addListener)return b;var d=r[b.constructor.name];return d?d(b,a):new c(b,a)};var q=c.prototype={constructor:c,addListener:function(b){this.target.addEventListener("message",b)},removeListener:function(b){this.target.removeEventListener("message",b)},postMessage:function(b,
a){this.target.postMessage(b,a)}},r={HTMLIFrameElement:function(b){var a=k(b);return{addListener:function(a){window.addEventListener("message",a)},removeListener:function(a){window.removeEventListener("message",a)},postMessage:function(c,e){a.then(function(){return n(b.contentWindow,c,e)})}}},BroadcastChannel:function(b,a){function c(){var a=f();b.postMessage("ready?");m(b,"message",function u(c){"ready"==c.data&&(b.removeEventListener("message",u),a.resolve())});return a.promise}var e=a&&a.receiver,
d=a&&a.ready,d=d||e?Promise.resolve():c();e&&(b.postMessage("ready"),m(b,"message",function(a){"ready?"==a.data&&b.postMessage("ready")}));return{target:b,addListener:q.addListener,removeListener:q.removeListener,postMessage:function(a,c){d.then(function(){return b.postMessage(a,c)})}}},Window:function(b,a){var c=a&&a.ready||b===parent||b===self,c=c?Promise.resolve():k(b);return{addListener:function(a){window.addEventListener("message",a)},removeListener:function(a){window.removeEventListener("message",
a)},postMessage:function(a,d){c.then(function(){return n(b,a,d)})}}},SharedWorker:function(b){b.port.start();return new c(b.port)},SharedWorkerGlobalScope:function(){var b=[];return{postMessage:function(){},addListener:function(a,c){this.onconnect=function(a){a=a.ports[0];b.push(a);a.start();c(a)};self.addEventListener("connect",this.onconnect)},removeListener:function(a){self.removeEventListener("connect",this.onconnect);b.forEach(function(b){b.close();b.removeEventListener("message",a)})}}}},k=
function(){if("undefined"!=typeof window){var b=window.opener||window.parent,a=new WeakSet;b!=self&&m(window,"DOMContentLoaded",function e(){window.removeEventListener("DOMContentLoaded",e);n(b,"load")});m(self,"message",function(b){return"load"==b.data&&a.add(b.source)});return function(b){var c=b.contentWindow||b;if(a.has(c)||c==window.parent)return Promise.resolve();var d=f();m(window,"message",function u(a){"load"==a.data&&a.source==c&&(window.removeEventListener("message",u),d.resolve())});return d.promise}}}()},
{"../utils":6}],6:[function(d,g,l){l.uuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(c){var d=16*Math.random()|0;return("x"==c?d:d&3|8).toString(16)})};l.deferred=function(){var c={};c.promise=new Promise(function(d,g){c.resolve=d;c.reject=g});return c}},{}]},{},[1])(1)});

View file

@ -0,0 +1,197 @@
!((define)=>{define((require,exports,module)=>{
/**
* Mini Logger
*
* @type {Function}
*/
var debug = 0 ? function(arg1, ...args) {
var type = `[${self.constructor.name}][${location.pathname}]`;
console.log(`[ClientStream]${type} - "${arg1}"`, ...args);
} : () => {};
/**
* Exports
*/
module.exports = (client, utils) => {
client._activeStreams = [];
client.on('streamevent', onStreamEvent);
client.stream = function(name) {
debug('stream open', name);
var args = [].slice.call(arguments, 1);
var stream = new ClientStream(client, utils);
var self = this;
this.method('_stream', name, stream.id, this.id, args)
.then(() => {
debug('stream connected', name);
stream._connected.resolve();
})
.catch(err => {
debug('error', err);
onStreamEvent({
type: 'abort',
id: stream.id,
data: err
});
});
this._activeStreams[stream.id] = stream;
stream.emitter.on('cancel', onEnd);
stream.emitter.on('abort', onEnd);
stream.emitter.on('close', onEnd);
function onEnd() {
debug('end');
delete self._activeStreams[stream.id];
stream.destroy();
}
return stream;
};
/**
* Called every time the service calls
* write/abort/close on the ServiceStream
*
* @param {Object} broadcast
* @param {String} broadcast.id Stream ID
* @param {String} broadcast.type Event type ('write', 'abort' or 'close')
* @private
*/
function onStreamEvent(data) {
debug('stream event', data.type);
var stream = client._activeStreams[data.streamId];
stream.emitter.emit(data.type, data.data);
}
};
/**
* Readable stream instance returned by
* a `client.stream('methodName')` call.
*
* @param {Object} options
* @param {String} options.id Stream Id, used to match client/service streams
* @param {Client} options.client Client instance
*/
function ClientStream(client, utils) {
this.id = utils.uuid();
this.client = client;
this.emitter = new utils.Emitter();
this.emitter.on('close', this.onClose.bind(this));
this.emitter.on('abort', this.onAbort.bind(this));
this._connected = defer();
this.connected = this._connected.promise;
this._closed = defer();
this.closed = this._closed.promise;
debug('initialized');
}
/**
* Prototype assigned to variable
* to improve compression.
*
* @type {Object}
*/
ClientStream.prototype = {
/**
* Add a listener that will be called
* every time the service broadcasts
* a new chunk of data.
*
* @param {Function} callback
*/
listen(callback) {
debug('listen', callback);
this.emitter.on('write', callback);
},
/**
* Removes 'data' listener
*
* @param {Function} callback
*/
unlisten(callback) {
debug('unlisten', callback);
this.emitter.off('write', callback);
},
/**
* Notify the service that
* action should be canceled
*
* @param {*} [reason] Optional data to be sent to service.
*/
cancel(reason) {
debug('cancel', reason);
return this.client.method('_streamcancel', this.id, reason)
.then(result => {
debug('cancelled', result);
this.emitter.emit('cancel');
return result;
})
.catch(e => {
this.emitter.emit('cancel');
});
},
/**
* Used internally by Client when
* it receives an 'abort' event
* from the service.
*
* @private
*/
onAbort(reason) {
debug('abort', reason);
this._closed.reject(reason);
},
/**
* Used internally by Client when
* it receives a 'close' event
* from the service.
*
* @private
*/
onClose() {
debug('close');
this._closed.resolve();
},
destroy() {
debug('destroy');
this.emitter.off();
}
};
/**
* Utils
*/
function defer() {
var result = {};
result.promise = new Promise((resolve, reject) => {
result.resolve = resolve;
result.reject = reject;
});
return result;
}
});})((typeof define)[0]=='f'&&define.amd?define:((n,w)=>{return(typeof
module)[0]=='o'?c=>{c(require,exports,module);}:(c)=>{var m={exports:{}};
c(n=>w[n],m.exports,m);w[n]=m.exports;};})('streamClient',this));

View file

@ -0,0 +1,206 @@
!((define)=>{define((require,exports,module)=>{
/**
* Mini Logger
*
* @type {Function}
*/
var debug = 0 ? function(arg1, ...args) {
var type = `[${self.constructor.name}][${location.pathname}]`;
console.log(`[ServiceStream]${type} - "${arg1}"`, ...args);
} : () => {};
module.exports = function(service) {
debug('attaching plugin');
service
.method('_stream', onStream)
.method('_streamcancel', onStreamCancel);
service._streamHandlers = {};
service._activeStreams = [];
service.stream = function(name, fn) {
debug('register stream', name);
this._streamHandlers[name] = fn;
return this;
};
function onStream(name, id, clientId, args) {
debug('on stream open', name);
var e = {
preventDefault: () => e.defaultPrevented = true,
arguments: arguments
};
// Allow other plugins to override default behaviour
service.emit('before-stream', e);
if (e.defaultPrevented) return;
var fn = service._streamHandlers[name];
if (!fn) throw error(1, name);
var stream = new ServiceStream(id, service, clientId);
service._activeStreams[id] = stream;
// Always pass stream object as first
// argument to simplify the process
fn.apply(service, [stream].concat(args));
}
function onStreamCancel(id, reason) {
debug('stream cancel');
var stream = service._activeStreams[id];
delete service._activeStreams[id];
return stream.cancel(reason);
}
};
/**
* Writable Stream instance passed to the
* `service.stream` implementation
*
* @param {Object} options
* @param {String} options.id Stream ID used to sync client and service streams
* @param {BroadcastChannel} options.channel Channel used to postMessage
* @param {String} options.serviceId ID of the service
* @param {String} options.clientId ID of client that should receive message
*/
function ServiceStream(streamId, service, clientId) {
this.id = streamId;
this.service = service;
this.clientId = clientId;
this.writable = true;
debug('initialized');
}
/**
* Prototype assigned to variable
* to improve compression.
*
* @type {Object}
*/
var ServiceStreamPrototype = ServiceStream.prototype;
/**
* Services that allows clients to
* cancel the operation before it's
* complete should override the
* `stream.cancel` method.
*
* @param {*} [reason] Data sent from client about the cancellation
* @returns {(Promise|*)}
*/
ServiceStreamPrototype.cancel = function(reason) {
var err = new TypeError('service should implement stream.cancel()');
return Promise.reject(err);
};
/**
* Signal to client that action was
* aborted during the process, this
* should be used as a way to
* communicate errors.
*
* @param {*} [data] Reason of failure
* @returns {Promise}
* @public
*/
ServiceStreamPrototype.abort = function(data) {
debug('abort', data);
this._post('abort', data);
this.writable = false;
};
/**
* Sends a chunk of data to the client.
*
* @param {*} data Chunk of data to be sent to client.
* @returns {Promise}
* @public
*/
ServiceStreamPrototype.write = function(data) {
debug('write', data);
this._post('write', data);
};
/**
* Closes the stream, signals that
* action was completed with success.
*
* According to whatwg streams spec,
* WritableStream#close() doesn't send data.
*
* @returns {Promise}
*/
ServiceStreamPrototype.close = function() {
debug('close');
this._post('close');
this.writable = false;
};
/**
* Validate the current state and
* call cancel on the target stream.
*
* Called by the Service when client
* sends a 'streamcancel' message.
*
* @param {*} [reason] Reason for cancelation sent by the client
* @returns {Promise}
* @private
*/
ServiceStreamPrototype._cancel = function(reason) {
debug('cancel', reason);
return this.cancel(reason)
.then(result => {
this.writable = false;
return result;
});
};
/**
* Validate the current state and post message to client.
*
* @param {String} type 'write', 'abort' or 'close'
* @param {String} state 'writable', 'aborted' or 'closed'
* @param {*} [data] Data to be sent to the client
* @returns {Promise}
* @private
*/
ServiceStreamPrototype._post = function(type, data) {
debug('post', type, data, this.writable);
if (!this.writable) return Promise.reject();
this.service.broadcast('streamevent', {
streamId: this.id,
type: type,
data: data
}, [this.clientId]);
};
/**
* Create new `Error` from registery.
*
* @param {Number} id Error Id
* @return {Error}
* @private
*/
function error(id) {
var args = [].slice.call(arguments, 1);
return new Error({
1: 'stream "' + args[0] + '" doesn\'t exist'
}[id]);
}
});})((typeof define)[0]=='f'&&define.amd?define:((n,w)=>{return(typeof
module)[0]=='o'?c=>{c(require,exports,module);}:(c)=>{var m={exports:{}};
c(n=>w[n],m.exports,m);w[n]=m.exports;};})('streamService',this));

File diff suppressed because it is too large Load diff

27
gaia/apps/sms/lib/bridge/service.min.js vendored Executable file
View file

@ -0,0 +1,27 @@
var $jscomp={scope:{},global:this},Symbol;$jscomp.initSymbol=function(){$jscomp.global.Symbol||(Symbol=$jscomp.Symbol);$jscomp.initSymbol=function(){}};$jscomp.symbolCounter_=0;$jscomp.Symbol=function(k){return"jscomp_symbol_"+k+$jscomp.symbolCounter_++};$jscomp.initSymbolIterator=function(){$jscomp.initSymbol();Symbol.iterator||(Symbol.iterator=Symbol("iterator"));$jscomp.initSymbolIterator=function(){}};
$jscomp.makeIterator=function(k){$jscomp.initSymbolIterator();if(k[Symbol.iterator])return k[Symbol.iterator]();if(!(k instanceof Array||"string"==typeof k||k instanceof String))throw new TypeError(k+" is not iterable");var c=0;return{next:function(){return c==k.length?{done:!0}:{done:!1,value:k[c++]}}}};$jscomp.arrayFromIterator=function(k){for(var c,e=[];!(c=k.next()).done;)e.push(c.value);return e};$jscomp.arrayFromIterable=function(k){return k instanceof Array?k:$jscomp.arrayFromIterator($jscomp.makeIterator(k))};
$jscomp.arrayFromArguments=function(k){for(var c=[],e=0;e<k.length;e++)c.push(k[e]);return c};$jscomp.inherits=function(k,c){function e(){}e.prototype=c.prototype;k.prototype=new e;k.prototype.constructor=k;for(var l in c)if($jscomp.global.Object.defineProperties){var a=$jscomp.global.Object.getOwnPropertyDescriptor(c,l);void 0!==a&&$jscomp.global.Object.defineProperty(k,l,a)}else k[l]=c[l]};
(function(k){"object"===typeof exports&&"undefined"!==typeof module?module.exports=k():"function"===typeof define&&define.amd?define([],k):("undefined"!==typeof window?window:"undefined"!==typeof global?global:"undefined"!==typeof self?self:this).bridge=k()})(function(){return function c(e,l,a){function m(h,f){if(!l[h]){if(!e[h]){var g="function"==typeof require&&require;if(!f&&g)return g(h,!0);if(p)return p(h,!0);g=Error("Cannot find module '"+h+"'");throw g.code="MODULE_NOT_FOUND",g;}g=l[h]={exports:{}};
e[h][0].call(g.exports,function(d){var b=e[h][1][d];return m(b?b:d)},g,g.exports,c,e,l,a)}return l[h].exports}for(var p="function"==typeof require&&require,n=0;n<a.length;n++)m(a[n]);return m}({1:[function(c,e,l){var a=e.exports=self.bridge||{};a.service=c("../src/service");"u"!="undefined"[0]?(void 0)([],function(){return a}):self.bridge=a},{"../src/service":5}],2:[function(c,e,l){function a(c){if(c)return Object.assign(c,a.prototype)}e.exports=a;a.prototype={on:function(a,c){this._callbacks||(this._callbacks=
{});this._callbacks[a]||(this._callbacks[a]=[]);this._callbacks[a].push(c);return this},off:function(a,c){if(this._callbacks)switch(arguments.length){case 0:this._callbacks={};break;case 1:delete this._callbacks[a];break;default:var e=this._callbacks[a];if(!e)return;var h=e.indexOf(c);~h&&e.splice(h,1)}return this},emit:function(a,c){if(this._callbacks)for(var e=this._callbacks[a]||[],e=e.concat(this._callbacks["*"]||[]),h=0;h<e.length;h++)e[h].call(this,c,a);return this}};c=a.prototype;c.off=c.off;
c.on=c.on},{}],3:[function(c,e,l){function a(b){this.cancelled=!1;this.listeners=[];this.deferred=f();this.listen=this.listen.bind(this);this.onMessage=this.onMessage.bind(this);this.onTimeout=this.onTimeout.bind(this);"object"===typeof b?this.setupInbound(b):this.setupOutbound(b);d("initialized",this.type)}function m(b){this.name=b;this.ports=new Set;this.onMessage=this.onMessage.bind(this);this.listen=this.listen.bind(this);this.unlisten=this.unlisten.bind(this);d("receiver initialized",b)}function p(b,
d){for(var a=1;a<arguments.length;++a);return Error({1:".send() can only be called once",2:"response already sent for this message",3:"a port must be defined",4:"timeout"}[b])}var n=c("./port-adaptors"),h=c("../emitter");c=c("../utils");var f=c.deferred,g=c.uuid;l=e.exports=function(b){return new a(b)};l.receiver=function(b,d){return new m(b,d)};l.Receiver=m;l.Message=a;var d={0:function(){},1:function(b){return performance.mark("["+self.constructor.name+"][Message] - "+b)},2:function(b,d){for(var a=
[],f=1;f<arguments.length;++f)a[f-1]=arguments[f];console.log.apply(console,[].concat(["[Message]"+("["+self.constructor.name+"]["+location.pathname+"]")+' - "'+b+'"'],$jscomp.arrayFromIterable(a)))}}[0];a.prototype={setupOutbound:function(b){this.id=g();this.type=b;this.sent=!1;this.recipient="*"},setupInbound:function(b){d("inbound");this.hasResponded=!1;this.setSourcePort(b.source||b.target);this.event=b;Object.assign(this,b.data)},setSourcePort:function(b){d("set source",b.constructor.name);this.sourcePort=
n(b,{ready:!0});return this},set:function(b,a){d("set",b,a);"object"==typeof b?Object.assign(this,b):this[b]=a;return this},serialize:function(){return{id:this.id,type:this.type,data:this.data,recipient:this.recipient,noRespond:this.noRespond}},preventDefault:function(){d("prevent default");this.defaultPrevented=!0},send:function(b){d("send",this.type);if(this.sent)throw p(1);var a=this.serialize(),f=!this.noRespond;this.port=b?n(b):this.port;if(!this.port)throw p(3);f?(this.listen(this.port),this.setResponseTimeout()):
this.deferred.resolve();this.port.postMessage(a,this.getTransfer());d("sent",a);return this.deferred.promise},setResponseTimeout:function(){!1!==this.timeout&&(this._timer=setTimeout(this.onTimeout,this.timeout||2E3))},clearResponseTimeout:function(){clearTimeout(this._timer)},getTransfer:function(){return this.transfer||this.event&&this.event.ports},onMessage:function(b){if(b.data.response&&b.data.id===this.id&&!this.cancelled)this.onResponse(b)},onTimeout:function(){d("response timeout",this.type);
this.silentTimeout||this.deferred.reject(p(4));this.teardown()},listen:function(b){d("add response listener",b);b=n(b);b.addListener(this.onMessage,this.listen);this.listeners.push(b);return this},unlisten:function(){var b=this;d("remove response listeners");this.listeners.forEach(function(d){return d.removeListener(b.onMessage)});this.listeners=[]},cancel:function(){this.teardown();this.cancelled=!0;this.emit("cancel")},teardown:function(){this.clearResponseTimeout();this.unlisten()},respond:function(b){function a(b){d("resolve",
b);c({type:"resolve",value:b})}function f(b){a:switch(b&&b.constructor.name){case "DOMException":case "Error":b={message:b.message};break a;case "DOMError":b={message:b.message,name:b.name};break a}d("reject",b);c({type:"reject",value:b})}function c(b){g.response=b;g.sourcePort.postMessage({id:g.id,response:b},g.transfer);d("responded with:",b)}d("respond",b,this.id);if(this.hasResponded)throw p(2);if(this.sourcePort&&!this.noRespond){this.hasResponded=!0;var g=this;this.error&&f(this.error);Promise.resolve(b).then(a,
f).catch(f)}},forward:function(b){var a=this;d("forward");return this.set("silentTimeout",!0).send(b).then(function(b){return a.respond(b.value)})},onResponse:function(b){d("on response",b.data);var a=b.data.response,f="reject"==a.type?a.value:a;a.event=b;this.response=a;this.teardown();this.deferred[this.response.type](f);this.emit("response",a)}};h(a.prototype);m.prototype={listen:function(b){d("listen");b=n(b||self,{receiver:!0});if(!this.ports.has(b))return b.addListener(this.onMessage,this.listen),
this.ports.add(b),this},unlisten:function(){var b=this;d("unlisten");this.ports.forEach(function(d){return d.removeListener(b.onMessage)})},onMessage:function(b){if(b.data.id&&b.data.type&&this.isRecipient(b.data.recipient)&&(d("receiver on message",b.data),b=new a(b),this.emit("message",b),!b.defaultPrevented))try{this.emit(b.type,b)}catch(f){throw b.error=f,b.respond(),f;}},isRecipient:function(b){return b==this.name||"*"==b||"*"==this.name},destroy:function(){this.unlisten();delete this.name;return this}};
h(m.prototype)},{"../emitter":2,"../utils":6,"./port-adaptors":4}],4:[function(c,e,l){function a(d){this.target=d}function m(d,b,a){d.addEventListener(b,a)}function p(d,b,a){b={data:b,source:self};a&&(b.ports=a);d.dispatchEvent(new MessageEvent("message",b))}var n=c("../utils").deferred;e.exports=function(d,b){if(!d)throw Error({1:"target is undefined"}[1]);if(d&&d.addListener)return d;var g=f[d.constructor.name];return g?g(d,b):new a(d,b)};var h=a.prototype={constructor:a,addListener:function(d){this.target.addEventListener("message",
d)},removeListener:function(d){this.target.removeEventListener("message",d)},postMessage:function(d,b){this.target.postMessage(d,b)}},f={HTMLIFrameElement:function(d){var b=g(d);return{addListener:function(b){window.addEventListener("message",b)},removeListener:function(b){window.removeEventListener("message",b)},postMessage:function(a,f){b.then(function(){return p(d.contentWindow,a,f)})}}},BroadcastChannel:function(a,b){function f(){var b=n();a.postMessage("ready?");m(a,"message",function q(f){"ready"==
f.data&&(a.removeEventListener("message",q),b.resolve())});return b.promise}var g=b&&b.receiver,c=b&&b.ready,c=c||g?Promise.resolve():f();g&&(a.postMessage("ready"),m(a,"message",function(b){"ready?"==b.data&&a.postMessage("ready")}));return{target:a,addListener:h.addListener,removeListener:h.removeListener,postMessage:function(b,f){c.then(function(){return a.postMessage(b,f)})}}},Window:function(a,b){var f=b&&b.ready||a===parent||a===self,f=f?Promise.resolve():g(a);return{addListener:function(b){window.addEventListener("message",
b)},removeListener:function(b){window.removeEventListener("message",b)},postMessage:function(b,g){f.then(function(){return p(a,b,g)})}}},SharedWorker:function(f){f.port.start();return new a(f.port)},SharedWorkerGlobalScope:function(){var a=[];return{postMessage:function(){},addListener:function(b,f){this.onconnect=function(b){b=b.ports[0];a.push(b);b.start();f(b)};self.addEventListener("connect",this.onconnect)},removeListener:function(b){self.removeEventListener("connect",this.onconnect);a.forEach(function(a){a.close();
a.removeEventListener("message",b)})}}}},g=function(){if("undefined"!=typeof window){var a=window.opener||window.parent,b=new WeakSet;a!=self&&m(window,"DOMContentLoaded",function r(){window.removeEventListener("DOMContentLoaded",r);p(a,"load")});m(self,"message",function(a){return"load"==a.data&&b.add(a.source)});return function(a){var f=a.contentWindow||a;if(b.has(f)||f==window.parent)return Promise.resolve();var d=n();m(window,"message",function q(b){"load"==b.data&&b.source==f&&(window.removeEventListener("message",
q),d.resolve())});return d.promise}}}()},{"../utils":6}],5:[function(c,e,l){function a(f){if(!(this instanceof a))return new a(f);n.Receiver.call(this,f);this.clients={};this.methods={};this.on("_disconnect",this.onDisconnect.bind(this)).on("_connect",this.onConnect.bind(this)).on("_method",this.onMethod.bind(this)).on("_off",this.onOff.bind(this)).on("_on",this.onOn.bind(this));this.destroy=this.destroy.bind(this);h("initialized",f)}function m(a){var g=[].slice.call(arguments,1);return Error({4:'method "'+
g[0]+"\" doesn't exist"}[a])}var p=c("./utils").uuid,n=c("./message");c=n.Receiver;e.exports=a;var h={0:function(){},1:function(a){return performance.mark("["+self.constructor.name+"][Service] - "+a)},2:function(a,g){for(var d=[],b=1;b<arguments.length;++b)d[b-1]=arguments[b];console.log.apply(console,[].concat(["[Service]"+("["+self.constructor.name+"]["+location.pathname+"]")+' - "'+a+'"'],$jscomp.arrayFromIterable(d)))}}[0];a.prototype=Object.create(c.prototype);a.prototype.inWindow="Window"===
constructor.name;a.prototype.method=function(a,g){this.methods[a]=g;return this};a.prototype.broadcast=function(a,g,d){var b=this;h("broadcast",a,g,d);this.eachClient(function(c){if(!d||~d.indexOf(c.id))h("broadcasting to",c.id),b.push(a,g,c.id,{noRespond:!0})});return this};a.prototype.push=function(a,g,d,b){b=b&&b.noRespond;var c=this.getClient(d);return n("_push").set({recipient:d,noRespond:b,data:{type:a,data:g}}).send(c.port)};a.prototype.eachClient=function(a){for(var c in this.clients)a(this.clients[c])};
a.prototype.getClient=function(a){return this.clients[a]};a.prototype.onConnect=function(a){h("connection attempt",a.data,this.name);var c=a.data,d=c.clientId;d&&c.service===this.name&&!this.clients[d]&&(this.emit("before-connect",a),a.defaultPrevented||(this.upgradeChannel(a),this.addClient(d,a.sourcePort),a.respond(),this.emit("connected",d),h("connected",d)))};a.prototype.upgradeChannel=function(a){if(!this.inWindow||"Window"!==a.data.originEnv){var c=a.event.ports;if(c=c&&c[0])a.setSourcePort(c),
this.listen(c),c.start();h("channel upgraded")}};a.prototype.onDisconnect=function(a){var c=this.clients[a.data];c&&(this.emit("before-disconnect",a),a.defaultPrevented||(this.removeClient(c.id),a.respond(),this.emit("disconnected",c.id),h("disconnected",c.id)))};a.prototype.onMethod=function(a){h("on method",a.data);this.emit("before-method",a);if(!a.defaultPrevented){var c=a.data,d=c.name,b=this.methods[d],e;if(!b)throw m(4,d);try{e=b.apply(this,c.args)}catch(l){a.error=l}a.respond(e)}};a.prototype.onOn=
function(a){h("on on",a.data);this.emit("on",a.data)};a.prototype.onOff=function(a){h("on off");this.emit("off",a.data)};a.prototype.addClient=function(a,c){this.clients[a]={id:a,port:c}};a.prototype.removeClient=function(a){delete this.clients[a]};a.prototype.plugin=function(a){a(this,{uuid:p});return this};a.prototype.disconnect=function(a){this.removeClient(a.id);n("disconnect").set({recipient:a.id,noRespond:!0}).send(a.port)};a.prototype.destroy=function(){delete this.clients;this.unlisten();
this.off()};e=a.prototype;e.broadcast=e.broadcast;e.destroy=e.destroy;e.method=e.method;e.plugin=e.plugin},{"./message":3,"./utils":6}],6:[function(c,e,l){l.uuid=function(){return"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(a){var c=16*Math.random()|0;return("x"==a?c:c&3|8).toString(16)})};l.deferred=function(){var a={};a.promise=new Promise(function(c,e){a.resolve=c;a.reject=e});return a}},{}]},{},[1])(1)});

671
gaia/apps/sms/lib/sww.js Executable file
View file

@ -0,0 +1,671 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
var sww = require('./lib/sww.js');
self.ServiceWorkerWare = sww.ServiceWorkerWare;
self.StaticCacher = sww.StaticCacher;
self.SimpleOfflineCache = sww.SimpleOfflineCache;
},{"./lib/sww.js":5}],2:[function(require,module,exports){
'use strict';
// Inspired by expressjs and shed (https://github.com/wibblymat/shed)
function Router(options) {
this.options = options;
this.stack = [];
}
Router.prototype.ALL_METHODS = 'all';
Router.prototype.methods = ['get', 'post', 'put', 'delete', 'head',
Router.prototype.ALL_METHODS];
/**
* Add a new route to the stack.
* @param method (String) http verb to handle the request
* @param path (Regexp) string or regexp to match urls
* @param handler (Function) payload to be executed if url matches.
*/
Router.prototype.add = function r_add(method, path, handler) {
var pathRegex;
method = this._sanitizeMethod(method);
// Parse simle string path into regular expression for path matching
pathRegex = this._parseSimplePath(path);
this.stack.push({
method: method,
path: pathRegex,
handler: handler
});
};
/**
* Create the utility methods .get .post ... etc.
*/
Router.prototype.methods.forEach(function(method) {
Router.prototype[method] = function(path, handler) {
return this.add(method, path, handler);
};
});
Router.prototype.proxyMethods = function r_proxyPrototype(obj) {
var self = this;
this.methods.forEach(function(method) {
obj[method] = function(path, mw) {
if (typeof mw.onFetch !== 'function' && typeof mw !== 'function') {
throw new Error('This middleware cannot handle fetch request');
}
var handler = typeof mw.onFetch !== 'undefined' ?
mw.onFetch.bind(mw) : mw;
self.add(method, path, handler);
};
});
};
/**
* Matches the given url and methods with the routes stored in
* the stack.
*/
Router.prototype.match = function r_match(method, url) {
method = this._sanitizeMethod(method);
var matches = [];
var self = this;
this.stack.forEach(function eachRoute(route) {
if (!(method === route.method || route.method === self.ALL_METHODS)) {
return;
}
if (route.path.test(url)) {
matches.push(route.handler);
}
});
return matches;
};
Router.prototype._sanitizeMethod = function(method) {
var sanitizedMethod = method.toLowerCase().trim();
if (this.methods.indexOf(sanitizedMethod) === -1) {
throw new Error('Method "' + method + '" is not supported');
}
return sanitizedMethod;
};
/**
* Simple path-to-regex translation based on the Express "string-based path"
* syntax.
*/
Router.prototype._parseSimplePath = function(path) {
// Check for named placeholder crowding
if (/\:[a-zA-Z0-9]+\:[a-zA-Z0-9]+/g.test(path)) {
throw new Error('Invalid usage of named placeholders');
}
// Check for mixed placeholder crowdings
var mixedPlaceHolders =
/(\*\:[a-zA-Z0-9]+)|(\:[a-zA-Z0-9]+\:[a-zA-Z0-9]+)|(\:[a-zA-Z0-9]+\*)/g;
if (mixedPlaceHolders.test(path.replace(/\\\*/g,''))) {
throw new Error('Invalid usage of named placeholders');
}
// Try parsing the string and converting special characters into regex
try {
// Parsing anonymous placeholders with simple backslash-escapes
path = path.replace(/(.|^)\*/g, function(m,escape) {
return escape==='\\' ? '\\*' : (escape+'(.*?)');
});
// Parsing named placeholders with backslash-escapes
path = path.replace(/(.|^)\:([a-zA-Z0-9]+)/g, function(m,escape,tag) {
return escape==='\\' ? (':'+tag) : (escape+'(.+?)');
});
return new RegExp(path + '$');
}
// Failed to parse final path as a RegExp
catch (ex) {
throw new Error('Invalid path specified');
}
};
module.exports = Router;
},{}],3:[function(require,module,exports){
/* global Promise */
'use strict';
var cacheHelper = require('sw-cache-helper');
var debug = 0 ? console.log.bind(console, '[SimpleOfflineCache]') :
function(){};
// Default Match options, not exposed.
var DEFAULT_MATCH_OPTIONS = {
ignoreSearch: false,
ignoreMethod: false,
ignoreVary: false
};
var DEFAULT_MISS_POLICY = 'fetchAndChace';
// List of different policies
var MISS_POLICIES = [
DEFAULT_MISS_POLICY
];
/**
* Constructor for the middleware that serves the content of a
* cache specified by it's name.
* @param {string} cacheName Name of the cache that will be serving the content
* @param {object} [options] Object use to setup the cache matching alternatives
* @param {string} [missPolicy] Name of the policy to follow if a request miss
* when hitting the cache.
*/
function SimpleOfflineCache(cacheName, options, missPolicy) {
this.cacheName = cacheName || cacheHelper.defaultCacheName;
this.options = options || DEFAULT_MATCH_OPTIONS;
this.missPolicy = missPolicy || DEFAULT_MISS_POLICY;
if (MISS_POLICIES.indexOf(this.missPolicy) === -1) {
console.warn('Policy ' + missPolicy + ' not supported');
this.missPolicy = DEFAULT_MISS_POLICY;
}
}
SimpleOfflineCache.prototype.onFetch = function soc_onFetch(request, response) {
// If another middleware layer already have a response, the simple cache
// just pass through the response and does nothing.
if (response) {
return Promise.resolve(response);
}
var clone = request.clone();
var _this = this;
debug('Handing fetch event: %s', clone.url);
return this.ensureCache().then(function(cache) {
return cache.match(request.clone(), _this.options).then(function(res) {
if (res) {
return res;
}
// So far we just support one policy
switch(_this.missPolicy) {
case DEFAULT_MISS_POLICY:
return cacheHelper.fetchAndCache(request, cache);
}
});
});
};
SimpleOfflineCache.prototype.ensureCache = function soc_ensureCache() {
return cacheHelper.getCache(this.cacheName).then(function(cache) {
return cache;
});
};
module.exports = SimpleOfflineCache;
},{"sw-cache-helper":6}],4:[function(require,module,exports){
/* globals caches, Promise, Request */
'use strict';
function StaticCacher(fileList) {
if (!Array.isArray(fileList) || fileList.length === 0) {
throw new Error('Invalid file list');
}
this.files = fileList;
}
StaticCacher.prototype.onInstall = function sc_onInstall() {
var self = this;
return this.getDefaultCache().then(function(cache) {
return self.addAll(cache, self.files);
});
};
StaticCacher.prototype.getDefaultCache = function sc_getDefaultCache() {
return caches.open('offline');
};
StaticCacher.prototype.addAll = function(cache, urls) {
if (!cache) {
throw new Error('Need a cache to store things');
}
// Polyfill until chrome implements it
if (typeof cache.addAll !== 'undefined') {
return cache.addAll(urls);
}
var promises = [];
var self = this;
urls.forEach(function(url) {
promises.push(self.fetchAndCache(new Request(url), cache));
});
return Promise.all(promises);
};
StaticCacher.prototype.fetchAndCache =
function sc_fetchAndCache(request, cache) {
return fetch(request.clone()).then(function(response) {
if (parseInt(response.status) < 400) {
cache.put(request.clone(), response.clone());
}
return response;
});
};
module.exports = StaticCacher;
},{}],5:[function(require,module,exports){
/* global fetch, BroadcastChannel, clients, Promise, Request, Response */
'use strict';
var debug = 1 ? console.log.bind(console, '[ServiceWorkerWare]') : function(){};
var StaticCacher = require('./staticcacher.js');
var SimpleOfflineCache = require('./simpleofflinecache.js');
var Router = require('./router.js');
var ERROR = 'error';
var CONTINUE = 'continue';
var TERMINATE = 'terminate';
var TERMINATION_TOKEN = {};
function DEFAULT_FALLBACK_MW(request) {
return fetch(request);
}
function ServiceWorkerWare(fallbackMw) {
this.middleware = [];
this.router = new Router({});
this.router.proxyMethods(this);
this.fallbackMw = fallbackMw || DEFAULT_FALLBACK_MW;
}
ServiceWorkerWare.prototype.init = function sww_init() {
// lifecycle events
addEventListener('install', this);
addEventListener('activate', this);
addEventListener('beforeevicted', this);
addEventListener('evicted', this);
// network events
addEventListener('fetch', this);
// misc events
addEventListener('message', this);
// XXX: Add default configuration
};
/**
* Handle and forward all events related to SW
*/
ServiceWorkerWare.prototype.handleEvent = function sww_handleEvent(evt) {
debug('Event received: ' + evt.type);
switch(evt.type) {
case 'install':
this.onInstall(evt);
break;
case 'fetch':
this.onFetch(evt);
break;
case 'activate':
case 'message':
case 'beforeevicted':
case 'evicted':
this.forwardEvent(evt);
break;
default:
debug('Unhandled event ' + evt.type);
}
};
ServiceWorkerWare.prototype.onFetch = function sww_onFetch(evt) {
var steps = this.router.match(evt.request.method, evt.request.url);
// Push the fallback middleware at the end of the list.
// XXX bug 1165860: Decorating fallback MW with `stopIfResponse` until
// 1165860 lands
steps.push((function(req, res) {
if (res) {
return Promise.resolve(res);
}
return this.fallbackMw(req, res);
}).bind(this));
evt.respondWith(this.executeMiddleware(steps, evt.request));
};
/**
* Run the middleware pipeline and inform if errors preventing respondWith()
* to swallow the error.
*
* @param {Array} the middleware pipeline
* @param {Request} the request for the middleware
*/
ServiceWorkerWare.prototype.executeMiddleware = function (middleware, request) {
var response = this.runMiddleware(middleware, 0, request, null);
response.catch(function (error) { console.error(error); });
return response;
};
/**
* Pass through the middleware pipeline, executing each middleware in a
* sequence according to the result from each execution.
*
* Each middleware will be passed with the request and response from the
* previous one in the pipeline. The response from the latest one will be
* used to answer from the service worker. The middleware will receive,
* as the last parameter, a function to stop the pipeline and answer
* immediately.
*
* A middleware run can lead to continuing execution, interruption of the
* pipeline or error. The next action to be performed is calculated according
* the conditions of the middleware execution and its return value.
* See normalizeMwAnswer() for details.
*
* @param {Array} middleware pipeline.
* @param {Number} middleware to execute in the pipeline.
* @param {Request} the request for the middleware.
* @param {Response} the response for the middleware.
*/
ServiceWorkerWare.prototype.runMiddleware =
function (middleware, current, request, response) {
if (current >= middleware.length) {
return Promise.resolve(response);
}
var mw = middleware[current];
var endWith = ServiceWorkerWare.endWith;
var answer = mw(request, response, endWith);
var normalized =
ServiceWorkerWare.normalizeMwAnswer(answer, request, response);
return normalized.then(function (info) {
switch (info.nextAction) {
case TERMINATE:
return Promise.resolve(info.response);
case ERROR:
return Promise.reject(info.error);
case CONTINUE:
var next = current + 1;
var request = info.request;
var response = info.response;
return this.runMiddleware(middleware, next, request, response);
}
}.bind(this));
};
/**
* A function to force interruption of the pipeline.
*
* @param {Response} the response object that will be used to answer from the
* service worker.
*/
ServiceWorkerWare.endWith = function (response) {
if (arguments.length === 0) {
throw new Error('Type error: endWith() must be called with a value.');
}
return [TERMINATION_TOKEN, response];
};
/**
* A middleware is supposed to return a promise resolving in a pair of request
* and response for the next one or to indicate that it wants to answer
* immediately.
*
* To allow flexibility, the middleware is allowed to return other values
* rather than the promise. For instance, it is allowed to return only a
* request meaning the next middleware will be passed that request but the
* previous response untouched.
*
* The function takes into account all the scenarios to compute the request
* and response for the next middleware or the intention to terminate
* immediately.
*
* @param {Any} non normalized answer from the middleware.
* @param {Request} request passed as parameter to the middleware.
* @param {Response} response passed as parameter to the middleware.
*/
ServiceWorkerWare.normalizeMwAnswer = function (answer, request, response) {
if (!answer || !answer.then) {
answer = Promise.resolve(answer);
}
return answer.then(function (value) {
var nextAction = CONTINUE;
var error, nextRequest, nextResponse;
var isArray = Array.isArray(value);
if (isArray && value[0] === TERMINATION_TOKEN) {
nextAction = TERMINATE;
nextRequest = request;
nextResponse = value[1] || response;
}
else if (value === null) {
nextRequest = request;
nextResponse = null;
}
else if (isArray && value.length === 2) {
nextRequest = value[0];
nextResponse = value[1];
}
else if (value instanceof Response) {
nextRequest = request;
nextResponse = value;
}
else if (value instanceof Request) {
nextRequest = value;
nextResponse = response;
}
else {
var msg = 'Type error: middleware must return a Response, ' +
'a Request, a pair [Response, Request] or a Promise ' +
'resolving to one of these types.';
nextAction = ERROR;
error = new Error(msg);
}
return {
nextAction: nextAction,
request: nextRequest,
response: nextResponse,
error: error
};
});
};
/**
* Walk all the middle ware installed asking if they have prerequisites
* (on the way of a promise to be resolved) when installing the SW
*/
ServiceWorkerWare.prototype.onInstall = function sww_oninstall(evt) {
var waitingList = [];
this.middleware.forEach(function(mw) {
if (typeof mw.onInstall !== 'undefined') {
waitingList.push(mw.onInstall());
}
});
evt.waitUntil(Promise.all(waitingList));
};
/**
* Register a new middleware layer, they will treat the request in
* the order that this layers have been defined.
* A middleware layer can behave in the ServiceWorker in two ways:
* - Listening to SW lifecycle events (install, activate, message).
* - Handle a request.
* To handle each case (or both) the middleware object should provide
* the following methods:
* - on<SW LiveCiclyeEvent>: for listening to SW lifeciclye events
* - onFetch: for handling fetch urls
*/
ServiceWorkerWare.prototype.use = function sww_use() {
// If the first parameter is not a function we will understand that
// is the path to handle, and the handler will be the second parameter
if (arguments.length === 0) {
throw new Error('No arguments given');
}
var mw = arguments[0];
var path = '*';
var method = this.router.ALL_METHODS;
if (typeof mw === 'string') {
path = arguments[0];
mw = arguments[1];
var kind = typeof mw;
if (!mw || !(kind === 'object' || kind === 'function')) {
throw new Error('No middleware specified');
}
if (Router.prototype.methods.indexOf(arguments[2]) !== -1) {
method = arguments[2];
}
}
this.middleware.push(mw);
// Add to the router just if middleware object is able to handle onFetch
// or if we have a simple function
var handler = null;
if (typeof mw.onFetch === 'function') {
handler = mw.onFetch.bind(mw);
} else if (typeof mw === 'function') {
handler = mw;
}
if (handler) {
this.router.add(method, path, handler);
}
// XXX: Attaching the broadcastMessage to mw that implements onMessage.
// We should provide a way to get a reference to the SWW object and do
// the broadcast from there
if (typeof mw.onMessage === 'function') {
mw.broadcastMessage = this.broadcastMessage;
}
};
/**
* Forward the event received to any middleware layer that has a 'on<Event>'
* handler
*/
ServiceWorkerWare.prototype.forwardEvent = function sww_forwardEvent(evt) {
this.middleware.forEach(function(mw) {
var handlerName = 'on' + evt.type.replace(/^[a-z]/,
function(m){
return m.toUpperCase();
}
);
if (typeof mw[handlerName] !== 'undefined') {
mw[handlerName].call(mw, evt);
}
});
};
/**
* Broadcast a message to all worker clients
* @param msg Object the message
* @param channel String (Used just in Firefox Nightly) using broadcastchannel
* api to deliver the message, this parameter can be undefined as we listen for
* a channel undefined in the client.
*/
ServiceWorkerWare.prototype.broadcastMessage = function sww_broadcastMessage(
msg, channel) {
// XXX: Until https://bugzilla.mozilla.org/show_bug.cgi?id=1130685 is fixed
// we can use BroadcastChannel API in Firefox Nightly
if (typeof BroadcastChannel === 'function') {
var bc = new BroadcastChannel(channel);
bc.postMessage(msg);
bc.close();
return Promise.resolve();
} else {
// This is suppose to be the way of broadcasting a message, unfortunately
// it's not working yet in Chrome Canary
return clients.matchAll().then(function(consumers) {
consumers.forEach(function(client) {
client.postMessage(msg);
});
});
}
};
ServiceWorkerWare.decorators = {
ifNoResponse: function (mw) {
return function (req, res, endWith) {
if (res) { return [req, res]; }
return mw(req, res, endWith);
};
},
stopAfter: function (mw) {
return function (req, res, endWith) {
var answer = mw(req, res, endWith);
var normalized = ServiceWorkerWare.normalizeMwAnswer(answer, req, res);
return normalized.then(function (info) {
if (info.nextAction === 'error') {
return Promise.reject(info.error);
}
return endWith(info.response);
});
};
}
};
module.exports = {
ServiceWorkerWare: ServiceWorkerWare,
StaticCacher: StaticCacher,
SimpleOfflineCache: SimpleOfflineCache
};
},{"./router.js":2,"./simpleofflinecache.js":3,"./staticcacher.js":4}],6:[function(require,module,exports){
/* global caches, fetch, Promise, Request, module*/
(function() {
'use strict';
var CacheHelper = {
defaultCacheName: 'offline',
getCache: function getCache(name) {
return caches.open(name);
},
getDefaultCache: function getDefaultCache() {
return this.getCache(this.defaultCacheName);
},
fetchAndCache: function fetchAndChache(request, cache) {
return fetch(request.clone()).then(function(response) {
var clone = response.clone();
if (parseInt(clone.status) < 400) {
cache.put(request.clone(), response.clone());
}
return response.clone();
});
},
addAll: function addAll(cache, urls) {
if (!cache) {
throw new Error('Need a cache to store things');
}
// Polyfill until chrome implements it
if (typeof cache.addAll !== 'undefined') {
return cache.addAll(urls);
}
var promises = [];
var self = this;
urls.forEach(function(url) {
promises.push(self.fetchAndCache(new Request(url), cache));
});
return Promise.all(promises);
}
};
module.exports = CacheHelper;
})();
},{}]},{},[1])
//# sourceMappingURL=sww.js.map