regard
Version:
Sugar-interface to access multiple data sources.
172 lines (123 loc) • 4.43 kB
JavaScript
var _ = require('lodash'),
Connector = require('./connector'),
ConnectorsManager = require('./managers/connectors'),
Endpoint = require('./endpoint'),
EndpointsManager = require('./managers/endpoints'),
Hash = require('object-hash'),
Request = require('./request'),
RequestsManager = require('./managers/requests'),
Uuid = require('uuid');
exports = module.exports = Manager;
function Manager(cacheMaxAge, cacheMax) {
if (!(this instanceof Manager)) {
return new Manager(cacheMaxAge, cacheMax);
}
this.api = _.bind(handleRequest, this, Connector.DEFAULT_HANDLER);
this.api.$ = _.bind(handleEndpoint, this);
this.api.$$ = _.bind(handleConnector, this);
this.api.to = _.bind(handleEndpointFocused, this);
if (_.isNumber(cacheMaxAge)) {
RequestsManager.CACHE_MAXAGE = cacheMaxAge;
}
if (_.isNumber(cacheMax)) {
RequestsManager.CACHE_MAX = cacheMax;
}
this.connectors = new ConnectorsManager;
this.endpoints = new EndpointsManager;
this.requests = new RequestsManager;
}
Manager.prototype.createConnector = function (ConnectorFactory, initArgs) {
var connector = new ConnectorFactory();
connector.init.apply(connector, initArgs);
if (!connector.handlers.has(Connector.DEFAULT_HANDLER)) {
throw new Error('No default handler was found');
}
this.connectors.add(connector);
return connector;
};
Manager.prototype.createEndpoint = function (key, initArgs) {
var endpoint = new Endpoint(key);
endpoint.init.apply(endpoint, initArgs);
endpoint.parent = this.endpoints.getParent(key);
endpoint.connector = this.connectors.resolve(endpoint);
endpoint.root = _.isUndefined(endpoint.parent);
if (_.isUndefined(endpoint.connector)) {
throw new Error('No connector was found');
}
endpoint.connector.onCreateEndpoint(endpoint);
this.createEndpointApi(endpoint);
this.endpoints.add(endpoint);
return endpoint;
};
Manager.prototype.createEndpointApi = function (endpoint) {
var api = _.bind(handleRequest, this, Connector.DEFAULT_HANDLER, endpoint);
api.$ = _.bind(handleEndpointNested, this, endpoint.key);
_.forEach(endpoint.connector.handlers.data, function (value) {
var key = value.key;
if (key !== Connector.DEFAULT_HANDLER) {
_.set(api, key, _.bind(handleRequest, this, key, endpoint));
}
}, this);
_.set(this.api, endpoint.keyDotted, api);
return api;
};
Manager.prototype.createRequest = function (endpoint, handler, initArgs) {
var hash = Hash(_.toArray(arguments)),
request = this.requests.get(hash);
if (_.isObject(request)) {
return request;
}
request = new Request(hash);
request.init(endpoint, handler, initArgs);
endpoint.connector.onCreateRequest(request);
this.requests.add(request);
return request;
};
function handleConnector(connector) {
if (_.isArray(connector)) {
_.each(connector, _.flow(_.identity, _.bind(handleConnector, this)));
return this.api;
}
if (_.isString(connector)) {
connector = this.connectors.core(connector);
}
if (!_.isFunction(connector)) {
throw new Error('A connector factory or a core connector name was expected');
}
this.createConnector(connector, _.slice(arguments, 1));
return this.api;
}
function handleEndpoint(key) {
if (!_.isString(key) || _.isEmpty(key)) {
throw new Error('A name was expected');
}
this.createEndpoint(key, _.slice(arguments, 1));
return this.api;
}
function handleEndpointNested(parent, key) {
key = [parent, key].join('/');
return _.partial(handleEndpoint, key).apply(this, _.slice(arguments, 2));
}
function handleEndpointFocused() {
var key = Uuid.v4();
_.partial(handleEndpoint, key).apply(this, _.toArray(arguments));
return _.get(this.api, key);
}
function handleRequest(handler, endpoint) {
if (_.isString(endpoint)) {
var doubleDot = endpoint.lastIndexOf(':');
if (doubleDot > -1) {
handler = endpoint.substring(doubleDot+1);
endpoint = endpoint.substring(0, doubleDot);
}
endpoint = this.endpoints.get(endpoint);
}
if (_.isUndefined(endpoint) || !_.isObject(endpoint.connector)) {
throw new Error('No endpoint was found');
}
if (!endpoint.connector.handlers.has(handler)) {
throw new Error('No handler was found');
}
var request = this.createRequest(endpoint, handler, _.slice(arguments, 2));
return this.requests.prepare(request);
}