mirror of
https://github.com/titanscouting/tra-analysis.git
synced 2025-02-07 11:25:48 +00:00
168 lines
5.0 KiB
JavaScript
168 lines
5.0 KiB
JavaScript
|
"use strict";
|
||
|
module.exports = Service;
|
||
|
|
||
|
// extends Namespace
|
||
|
var Namespace = require("./namespace");
|
||
|
((Service.prototype = Object.create(Namespace.prototype)).constructor = Service).className = "Service";
|
||
|
|
||
|
var Method = require("./method"),
|
||
|
util = require("./util"),
|
||
|
rpc = require("./rpc");
|
||
|
|
||
|
/**
|
||
|
* Constructs a new service instance.
|
||
|
* @classdesc Reflected service.
|
||
|
* @extends NamespaceBase
|
||
|
* @constructor
|
||
|
* @param {string} name Service name
|
||
|
* @param {Object.<string,*>} [options] Service options
|
||
|
* @throws {TypeError} If arguments are invalid
|
||
|
*/
|
||
|
function Service(name, options) {
|
||
|
Namespace.call(this, name, options);
|
||
|
|
||
|
/**
|
||
|
* Service methods.
|
||
|
* @type {Object.<string,Method>}
|
||
|
*/
|
||
|
this.methods = {}; // toJSON, marker
|
||
|
|
||
|
/**
|
||
|
* Cached methods as an array.
|
||
|
* @type {Method[]|null}
|
||
|
* @private
|
||
|
*/
|
||
|
this._methodsArray = null;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Service descriptor.
|
||
|
* @interface IService
|
||
|
* @extends INamespace
|
||
|
* @property {Object.<string,IMethod>} methods Method descriptors
|
||
|
*/
|
||
|
|
||
|
/**
|
||
|
* Constructs a service from a service descriptor.
|
||
|
* @param {string} name Service name
|
||
|
* @param {IService} json Service descriptor
|
||
|
* @returns {Service} Created service
|
||
|
* @throws {TypeError} If arguments are invalid
|
||
|
*/
|
||
|
Service.fromJSON = function fromJSON(name, json) {
|
||
|
var service = new Service(name, json.options);
|
||
|
/* istanbul ignore else */
|
||
|
if (json.methods)
|
||
|
for (var names = Object.keys(json.methods), i = 0; i < names.length; ++i)
|
||
|
service.add(Method.fromJSON(names[i], json.methods[names[i]]));
|
||
|
if (json.nested)
|
||
|
service.addJSON(json.nested);
|
||
|
service.comment = json.comment;
|
||
|
return service;
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Converts this service to a service descriptor.
|
||
|
* @param {IToJSONOptions} [toJSONOptions] JSON conversion options
|
||
|
* @returns {IService} Service descriptor
|
||
|
*/
|
||
|
Service.prototype.toJSON = function toJSON(toJSONOptions) {
|
||
|
var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
|
||
|
var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
|
||
|
return util.toObject([
|
||
|
"options" , inherited && inherited.options || undefined,
|
||
|
"methods" , Namespace.arrayToJSON(this.methodsArray, toJSONOptions) || /* istanbul ignore next */ {},
|
||
|
"nested" , inherited && inherited.nested || undefined,
|
||
|
"comment" , keepComments ? this.comment : undefined
|
||
|
]);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Methods of this service as an array for iteration.
|
||
|
* @name Service#methodsArray
|
||
|
* @type {Method[]}
|
||
|
* @readonly
|
||
|
*/
|
||
|
Object.defineProperty(Service.prototype, "methodsArray", {
|
||
|
get: function() {
|
||
|
return this._methodsArray || (this._methodsArray = util.toArray(this.methods));
|
||
|
}
|
||
|
});
|
||
|
|
||
|
function clearCache(service) {
|
||
|
service._methodsArray = null;
|
||
|
return service;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @override
|
||
|
*/
|
||
|
Service.prototype.get = function get(name) {
|
||
|
return this.methods[name]
|
||
|
|| Namespace.prototype.get.call(this, name);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @override
|
||
|
*/
|
||
|
Service.prototype.resolveAll = function resolveAll() {
|
||
|
var methods = this.methodsArray;
|
||
|
for (var i = 0; i < methods.length; ++i)
|
||
|
methods[i].resolve();
|
||
|
return Namespace.prototype.resolve.call(this);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @override
|
||
|
*/
|
||
|
Service.prototype.add = function add(object) {
|
||
|
|
||
|
/* istanbul ignore if */
|
||
|
if (this.get(object.name))
|
||
|
throw Error("duplicate name '" + object.name + "' in " + this);
|
||
|
|
||
|
if (object instanceof Method) {
|
||
|
this.methods[object.name] = object;
|
||
|
object.parent = this;
|
||
|
return clearCache(this);
|
||
|
}
|
||
|
return Namespace.prototype.add.call(this, object);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* @override
|
||
|
*/
|
||
|
Service.prototype.remove = function remove(object) {
|
||
|
if (object instanceof Method) {
|
||
|
|
||
|
/* istanbul ignore if */
|
||
|
if (this.methods[object.name] !== object)
|
||
|
throw Error(object + " is not a member of " + this);
|
||
|
|
||
|
delete this.methods[object.name];
|
||
|
object.parent = null;
|
||
|
return clearCache(this);
|
||
|
}
|
||
|
return Namespace.prototype.remove.call(this, object);
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Creates a runtime service using the specified rpc implementation.
|
||
|
* @param {RPCImpl} rpcImpl RPC implementation
|
||
|
* @param {boolean} [requestDelimited=false] Whether requests are length-delimited
|
||
|
* @param {boolean} [responseDelimited=false] Whether responses are length-delimited
|
||
|
* @returns {rpc.Service} RPC service. Useful where requests and/or responses are streamed.
|
||
|
*/
|
||
|
Service.prototype.create = function create(rpcImpl, requestDelimited, responseDelimited) {
|
||
|
var rpcService = new rpc.Service(rpcImpl, requestDelimited, responseDelimited);
|
||
|
for (var i = 0, method; i < /* initializes */ this.methodsArray.length; ++i) {
|
||
|
var methodName = util.lcFirst((method = this._methodsArray[i]).resolve().name).replace(/[^$\w_]/g, "");
|
||
|
rpcService[methodName] = util.codegen(["r","c"], util.isReserved(methodName) ? methodName + "_" : methodName)("return this.rpcCall(m,q,s,r,c)")({
|
||
|
m: method,
|
||
|
q: method.resolvedRequestType.ctor,
|
||
|
s: method.resolvedResponseType.ctor
|
||
|
});
|
||
|
}
|
||
|
return rpcService;
|
||
|
};
|