Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
197 lines
No EOL
4.1 KiB
JavaScript
Executable file
197 lines
No EOL
4.1 KiB
JavaScript
Executable file
!((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)); |