| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198 |
- "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 {string} [edition] Edition
- * @property {Object.<string,IMethod>} methods Method descriptors
- * @property {string|null} [comment] Service comment
- */
-
- /**
- * Constructs a service from a service descriptor.
- * @param {string} name Service name
- * @param {IService} json Service descriptor
- * @param {number} [depth] Current nesting depth, defaults to `0`
- * @returns {Service} Created service
- * @throws {TypeError} If arguments are invalid
- */
- Service.fromJSON = function fromJSON(name, json, depth) {
- if (depth === undefined)
- depth = 0;
- if (depth > util.recursionLimit)
- throw Error("max depth exceeded");
- 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, depth);
- if (json.edition)
- service._edition = json.edition;
- service.comment = json.comment;
- service._defaultEdition = "proto3"; // For backwards-compatibility.
- 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([
- "edition" , this._editionToJSON(),
- "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 Object.prototype.hasOwnProperty.call(this.methods, name)
- ? this.methods[name]
- : Namespace.prototype.get.call(this, name);
- };
-
- /**
- * @override
- */
- Service.prototype.resolveAll = function resolveAll() {
- if (!this._needsRecursiveResolve) return this;
-
- Namespace.prototype.resolve.call(this);
- var methods = this.methodsArray;
- for (var i = 0; i < methods.length; ++i)
- methods[i].resolve();
- return this;
- };
-
- /**
- * @override
- */
- Service.prototype._resolveFeaturesRecursive = function _resolveFeaturesRecursive(edition) {
- if (!this._needsRecursiveFeatureResolution) return this;
-
- edition = this._edition || edition;
-
- Namespace.prototype._resolveFeaturesRecursive.call(this, edition);
- this.methodsArray.forEach(method => {
- method._resolveFeaturesRecursive(edition);
- });
- return 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) {
- if (object.name === "__proto__")
- return this;
- 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] = (function(method, requestType, responseType) {
- return function rpcMethod(request, callback) {
- return rpc.Service.prototype.rpcCall.call(this, method, requestType, responseType, request, callback);
- };
- })(method, method.resolvedRequestType.ctor, method.resolvedResponseType.ctor);
- }
- return rpcService;
- };
|