@vara/custom-logic-sdk
Version:
Server Side JavaScript SDK for Custom Business Logic
171 lines (144 loc) • 7.63 kB
JavaScript
/**
* Created by stevenchin on 1/31/17.
*/
const _ = require('lodash');
const logSvc = require('../services/log-svc');
const fnRegistry = require('../services/fn-registry');
const customError = require('../services/custom-error');
const configGenerator = require('../services/platform-config-generator');
const ApplicationErrors = require('../constants/application-errors.json');
const { InvalidAPIResponderError, InvalidClActionError } = ApplicationErrors;
const { CUSTOM_LOGIC } = require('../constants/constants');
const { TYPES: CL_FN_TYPES } = CUSTOM_LOGIC.FUNCTIONS;
const { EXECUTION_MODES } = CUSTOM_LOGIC.FUNCTIONS;
const { VERSIONS: CL_PROTOCOL_VERSIONS } = CUSTOM_LOGIC.PROTOCOL;
const { TYPES: CL_ACTION_TYPES } = CUSTOM_LOGIC.ACTIONS;
function initializeSdk(app, options = {}) {
const sdk = { app, server: null };
/**
* @throws InvalidAPIResponderError - thrown when the config object is invalid or the fn param is not a function
* @throws InvalidClActionError - thrown when the config object is invalid or the fn param is not a function
* Adds a function to the internal registry with the configurations specified
* @param config {Object} - configurations for function to be added to the internal registry
* @param fn {Function} - function to add to registry
* @param opts {Object} - options to use when adding the fn to the registry
*/
function addFnToRegistry(config, fn, { isAction } = {}) {
const logPrefix = 'Sdk#addFnToRegistry';
try {
// prevent validation failures for lowercased request methods for developer convenience
// note: httpMethods is only required for pre-hooks
if (Array.isArray(config.httpMethods)) {
config.httpMethods = config.httpMethods.map((method) => method.toUpperCase());
}
fnRegistry.add(config, fn, { isAction });
} catch (validationError) {
let error;
if (isAction) {
error = customError(InvalidClActionError.name, null, { innerError: validationError });
} else {
error = customError(InvalidAPIResponderError.name, null, { innerError: validationError });
}
logSvc.logError(error, {}, logPrefix);
throw error;
}
}
/**
* Defaults the config for the custom logic protocol version to the latest version
* @param config {Object} - config to update
*/
function setDefaultProtocolVersion(config) {
config.clProtocolVersion = config.clProtocolVersion || CL_PROTOCOL_VERSIONS.LATEST;
}
/**
* Adds the relevant configurations for API responders
* @param config {Object} - config to update
*/
function updateConfigForAPIResponders(config) {
config.executionMode = EXECUTION_MODES.SYNC;
setDefaultProtocolVersion(config);
}
/**
* Start custom logic web server
*/
sdk.run = function run() {
logSvc.info('generating registration configs...');
const regConfig = configGenerator.generateRegistrationConfigForPlatform();
logSvc.info('registration configs generated: ', JSON.stringify(regConfig));
sdk.server = app.listen(options.PORT, () => {
logSvc.info('server started on port: %d', options.PORT);
});
};
/**
* @throws InvalidAPIResponderError - thrown when the config object is invalid or the responder property is not a function
* Stores the configurations for a standalone custom logic responder so that it can be executed when matching requests are made to the custom logic web service.
* @param config {Object} - configurations for standalone custom logic responder
* @param config.name {String} - name of standalone function
* @param [config.httpMethods] {Array} - list of http methods (i.e GET, PUT, POST, DELETE) that the standalone function should be invoked for when a matching request is made to the Etx Platform.
* @param [config.supportAllMethods] {Array} - support all http request methods made to the Etx Platform.
* @param [config.clProtocolVersion] {String} - the custom logic protocol version to use for the standalone function
* @param responder {Function} - standalone function to execute
*/
sdk.registerStandaloneAPIResponder = function registerStandaloneAPIResponder(config = {}, responder) {
const updatedConfig = Object.assign({}, config);
updatedConfig.type = CL_FN_TYPES.STANDALONE;
updateConfigForAPIResponders(updatedConfig);
addFnToRegistry(updatedConfig, responder);
};
/**
* @throws InvalidAPIResponderError - thrown when the config object is invalid or the responder property is not a function
* Stores the configurations for a post hook responder so that it can be executed when matching requests are made to the custom logic web service.
* @param config {Object} - configurations for post hook responder
* @param config.name {String} - name of post hook
* @param config.modelName {String} - model the post hook should be executed on
* @param config.modelMethod {String} - name of the model method the post hook should be executed on
* @param [config.clProtocolVersion] {String} - the custom logic protocol version to use for the post hook
* @param responder {Function} - post hook to execute
*/
sdk.registerPostHookAPIResponder = function registerPostHookAPIResponder(config = {}, responder) {
const updatedConfig = Object.assign({}, config);
updatedConfig.type = CL_FN_TYPES.POST_HOOK;
updateConfigForAPIResponders(updatedConfig);
addFnToRegistry(updatedConfig, responder);
};
/**
* @throws InvalidAPIResponderError - thrown when the config object is invalid or the responder property is not a function
* Stores the configurations for a pre hook responder so that it can be executed when matching requests are made to the custom logic web service.
* @param config {Object} - configurations for pre hook responder
* @param config.name {String} - name of hook
* @param config.urlPath {String} - url path the hook should be executed on
* @param config.httpMethods {Array} - HTTP method(s) that the hook should be triggered on. Supported values are GET, POST, PUT, DELETE and *.
* @param [config.clProtocolVersion] {String} - the custom logic protocol version to use for the post hook
* @param responder {Function} - post hook to execute
*/
sdk.registerPreHookAPIResponder = function registerPreHookAPIResponder(config = {}, responder) {
const updatedConfig = Object.assign({}, config);
updatedConfig.type = CL_FN_TYPES.PRE_HOOK;
updateConfigForAPIResponders(updatedConfig);
addFnToRegistry(updatedConfig, responder);
};
/**
* @throws InvalidClActionError - thrown when the config object is invalid or the fn param is not a function
* Stores the configurations for a custom logic action so that it can be executed when matching requests are made to the custom logic web service.
* @param config {Object} - configurations for custom logic action
* @param config.name {String} - name of action
* @param action {Function} - action to execute
*/
sdk.registerAction = function registerAction(config = {}, action) {
const updatedConfig = Object.assign({}, config);
updatedConfig.type = CL_ACTION_TYPES.CL_ACTION;
addFnToRegistry(updatedConfig, action, { isAction: true });
};
// allows developers to use logger while bootstrapping their application or in other contexts outside of their handlers
sdk.log = logSvc;
function stopServer() {
if (sdk.server && _.isFunction(sdk.server.close)) {
sdk.server.close();
}
}
if (options.NODE_ENV === 'test') {
sdk.stop = stopServer;
}
return sdk;
}
module.exports = initializeSdk;