2 module.exports = Service;
5 var Namespace = require("./namespace");
6 ((Service.prototype = Object.create(Namespace.prototype)).constructor = Service).className = "Service";
8 var Method = require("./method"),
9 util = require("./util"),
10 rpc = require("./rpc");
13 * Constructs a new service instance.
14 * @classdesc Reflected service.
15 * @extends NamespaceBase
17 * @param {string} name Service name
18 * @param {Object.<string,*>} [options] Service options
19 * @throws {TypeError} If arguments are invalid
21 function Service(name, options) {
22 Namespace.call(this, name, options);
26 * @type {Object.<string,Method>}
28 this.methods = {}; // toJSON, marker
31 * Cached methods as an array.
32 * @type {Method[]|null}
35 this._methodsArray = null;
42 * @property {Object.<string,IMethod>} methods Method descriptors
46 * Constructs a service from a service descriptor.
47 * @param {string} name Service name
48 * @param {IService} json Service descriptor
49 * @returns {Service} Created service
50 * @throws {TypeError} If arguments are invalid
52 Service.fromJSON = function fromJSON(name, json) {
53 var service = new Service(name, json.options);
54 /* istanbul ignore else */
56 for (var names = Object.keys(json.methods), i = 0; i < names.length; ++i)
57 service.add(Method.fromJSON(names[i], json.methods[names[i]]));
59 service.addJSON(json.nested);
60 service.comment = json.comment;
65 * Converts this service to a service descriptor.
66 * @param {IToJSONOptions} [toJSONOptions] JSON conversion options
67 * @returns {IService} Service descriptor
69 Service.prototype.toJSON = function toJSON(toJSONOptions) {
70 var inherited = Namespace.prototype.toJSON.call(this, toJSONOptions);
71 var keepComments = toJSONOptions ? Boolean(toJSONOptions.keepComments) : false;
72 return util.toObject([
73 "options" , inherited && inherited.options || undefined,
74 "methods" , Namespace.arrayToJSON(this.methodsArray, toJSONOptions) || /* istanbul ignore next */ {},
75 "nested" , inherited && inherited.nested || undefined,
76 "comment" , keepComments ? this.comment : undefined
81 * Methods of this service as an array for iteration.
82 * @name Service#methodsArray
86 Object.defineProperty(Service.prototype, "methodsArray", {
88 return this._methodsArray || (this._methodsArray = util.toArray(this.methods));
92 function clearCache(service) {
93 service._methodsArray = null;
100 Service.prototype.get = function get(name) {
101 return this.methods[name]
102 || Namespace.prototype.get.call(this, name);
108 Service.prototype.resolveAll = function resolveAll() {
109 var methods = this.methodsArray;
110 for (var i = 0; i < methods.length; ++i)
111 methods[i].resolve();
112 return Namespace.prototype.resolve.call(this);
118 Service.prototype.add = function add(object) {
120 /* istanbul ignore if */
121 if (this.get(object.name))
122 throw Error("duplicate name '" + object.name + "' in " + this);
124 if (object instanceof Method) {
125 this.methods[object.name] = object;
126 object.parent = this;
127 return clearCache(this);
129 return Namespace.prototype.add.call(this, object);
135 Service.prototype.remove = function remove(object) {
136 if (object instanceof Method) {
138 /* istanbul ignore if */
139 if (this.methods[object.name] !== object)
140 throw Error(object + " is not a member of " + this);
142 delete this.methods[object.name];
143 object.parent = null;
144 return clearCache(this);
146 return Namespace.prototype.remove.call(this, object);
150 * Creates a runtime service using the specified rpc implementation.
151 * @param {RPCImpl} rpcImpl RPC implementation
152 * @param {boolean} [requestDelimited=false] Whether requests are length-delimited
153 * @param {boolean} [responseDelimited=false] Whether responses are length-delimited
154 * @returns {rpc.Service} RPC service. Useful where requests and/or responses are streamed.
156 Service.prototype.create = function create(rpcImpl, requestDelimited, responseDelimited) {
157 var rpcService = new rpc.Service(rpcImpl, requestDelimited, responseDelimited);
158 for (var i = 0, method; i < /* initializes */ this.methodsArray.length; ++i) {
159 var methodName = util.lcFirst((method = this._methodsArray[i]).resolve().name).replace(/[^$\w_]/g, "");
160 rpcService[methodName] = util.codegen(["r","c"], util.isReserved(methodName) ? methodName + "_" : methodName)("return this.rpcCall(m,q,s,r,c)")({
162 q: method.resolvedRequestType.ctor,
163 s: method.resolvedResponseType.ctor