service-model
Version:
An object oriented web service framework inspired by Windows Communication Foundation.
176 lines (175 loc) • 7.53 kB
JavaScript
var requestDispatcher_1 = require("./dispatcher/requestDispatcher");
var serviceDescription_1 = require("./description/serviceDescription");
var dispatchService_1 = require("./dispatcher/dispatchService");
var dispatchEndpoint_1 = require("./dispatcher/dispatchEndpoint");
var dispatchOperation_1 = require("./dispatcher/dispatchOperation");
var defaultOperationInvoker_1 = require("./dispatcher/defaultOperationInvoker");
var defaultInstanceProvider_1 = require("./dispatcher/defaultInstanceProvider");
var reflect_helper_1 = require("reflect-helper");
/**
* The DispatcherFactory is the primary class used to configure the service model, and is responsible for creating the
* [[RequestDispatcher]] based on the service descriptions.
*
* <uml>
* hide members
* hide circle
* DispatcherFactory *-- ServiceDescription : services
* DispatcherFactory .> RequestDispatcher
* </uml>
*
* ### Example
*
* Once our service is defined, we add it to a DispatcherFactory. We then add an endpoint to the service,
* providing the name of the contract, the base address for the endpoint, and a list of endpoint behaviors.
*
* ```typescript
* import { DispatcherFactory, RpcBehavior } from "service-model";
*
* var factory = new DispatcherFactory();
*
* factory.addService(CalculatorService)
* .addEndpoint("Calculator", "/api/calculator", [new RpcBehavior()]);
* ```
*
* In this case, we add the [[RpcBehavior]] which indicates that operations on this endpoint will be available
* through RPC.
*/
var DispatcherFactory = (function () {
function DispatcherFactory() {
/**
* List of service descriptions configured for the dispatcher factory.
*/
this.services = [];
/**
* @hidden
*/
this._context = new reflect_helper_1.ReflectContext();
}
/**
* Adds a service.
* @param ctr The constructor for the service.
* @param name The name of the service. If not specified the name of the constructor is used.
*/
DispatcherFactory.prototype.addService = function (ctr, name) {
if (!ctr) {
throw new Error("Missing required argument 'ctr'.");
}
var service = new serviceDescription_1.ServiceDescription(this._context.getType(ctr), name);
this.services.push(service);
return service;
};
/**
* Creates a request dispatcher used for dispatching service requests.
*/
DispatcherFactory.prototype.createDispatcher = function () {
// Build the request dispatcher
var dispatcher = new requestDispatcher_1.RequestDispatcher();
for (var i = 0; i < this.services.length; i++) {
dispatcher.services.push(this._createDispatchService(dispatcher, this.services[i]));
}
// Apply behaviors
for (var i = 0; i < this.services.length; i++) {
this._applyServiceBehaviors(dispatcher.services[i], this.services[i]);
}
dispatcher.validate();
return dispatcher;
};
/**
* Creates a dispatch service based on the service description.
* @param dispatcher The dispatcher.
* @param service The service description.
* @hidden
*/
DispatcherFactory.prototype._createDispatchService = function (dispatcher, service) {
var ret = new dispatchService_1.DispatchService(dispatcher, service.name);
for (var i = 0; i < service.endpoints.length; i++) {
ret.endpoints.push(this._createDispatchEndpoint(ret, service.endpoints[i]));
}
ret.instanceProvider = new defaultInstanceProvider_1.DefaultInstanceProvider(service);
return ret;
};
/**
* Creates a dispatch endpoint based on an endpoint description.
* @param service The dispatch service.
* @param endpoint The endpoint description.
* @hidden
*/
DispatcherFactory.prototype._createDispatchEndpoint = function (service, endpoint) {
var ret = new dispatchEndpoint_1.DispatchEndpoint(service, endpoint.address, endpoint.contract.name);
for (var i = 0; i < endpoint.contract.operations.length; i++) {
ret.operations.push(this._createDispatchOperation(ret, endpoint.contract.operations[i]));
}
return ret;
};
/**
* Creates a dispatch operation based on an operation description.
* @param endpoint The dispatch endpoint.
* @param operation The operation description
* @hidden
*/
DispatcherFactory.prototype._createDispatchOperation = function (endpoint, operation) {
var ret = new dispatchOperation_1.DispatchOperation(endpoint, operation.name);
ret.isOneWay = operation.isOneWay;
var invoker = new defaultOperationInvoker_1.DefaultOperationInvoker(operation);
;
if (operation.timeout != undefined) {
invoker.timeout = operation.timeout;
}
ret.invoker = invoker;
return ret;
};
/**
* Applies all behaviors from the description objects to the dispatch objects.
* @param service The dispatch service.
* @param description The service description.
* @hidden
*/
DispatcherFactory.prototype._applyServiceBehaviors = function (service, description) {
// apply service behaviors
description.behaviors.forEach(function (behavior) { return behavior.applyServiceBehavior(description, service); });
// apply contract behaviors
for (var i = 0; i < description.endpoints.length; i++) {
this._applyContractBehaviors(service.endpoints[i], description.endpoints[i].contract);
}
// apply endpoint behaviors
for (var i = 0; i < description.endpoints.length; i++) {
this._applyEndpointBehaviors(service.endpoints[i], description.endpoints[i]);
}
// apply operation behaviors
for (var i = 0; i < description.endpoints.length; i++) {
var operations = description.endpoints[i].contract.operations;
for (var j = 0; j < operations.length; j++) {
this._applyOperationBehaviors(service.endpoints[i].operations[j], operations[j]);
}
}
};
/**
* Applies endpoint behaviors to the dispatch endpoint.
* @param endpoint The dispatch endpoint.
* @param description The endpoint description.
* @hidden
*/
DispatcherFactory.prototype._applyEndpointBehaviors = function (endpoint, description) {
description.behaviors.forEach(function (behavior) { return behavior.applyEndpointBehavior(description, endpoint); });
};
/**
* Applies contract behaviors to the dispatch endpoint.
* @param endpoint The dispatch endpoint.
* @param description The contract description.
* @hidden
*/
DispatcherFactory.prototype._applyContractBehaviors = function (endpoint, description) {
description.behaviors.forEach(function (behavior) { return behavior.applyContractBehavior(description, endpoint); });
};
/**
* Applies operation behaviors to the dispatch operation.
* @param operation The dispatch operation.
* @param description The operation description.
* @hidden
*/
DispatcherFactory.prototype._applyOperationBehaviors = function (operation, description) {
description.behaviors.forEach(function (behavior) { return behavior.applyOperationBehavior(description, operation); });
};
return DispatcherFactory;
})();
exports.DispatcherFactory = DispatcherFactory;