function () { var done = this.async(); var options = this.options({}); var swagger = require('swagger-client'); var url = require('url'); var util = require('util'); var fs = require('fs'); var mustache = require('mustache'); var _ = require('underscore'); var resourcesLib = require('./lib/resources.js'); var operations = ''; var events = ''; var operationTemplate = fs.readFileSync( './dev/operation.mustache', 'utf-8' ); var eventTemplate = fs.readFileSync( './dev/event.mustache', 'utf-8' ); var parsedUrl = url.parse(options.baseUrl); swagger.authorizations.add( 'basic-auth', new swagger.PasswordAuthorization( parsedUrl.hostname, options.username, options.password ) ); // Connect to API using swagger and attach resources on Client instance var resourcesUrl = util.format( '%s//%s/ari/api-docs/resources.json', parsedUrl.protocol, parsedUrl.host ); var swaggerClient = new swagger.SwaggerApi({ url: resourcesUrl, success: swaggerLoaded, failure: swaggerFailed }); // Swagger success callback function swaggerLoaded () { if(swaggerClient.ready === true) { grunt.log.writeln('generating operations documentation'); var apis = _.sortBy(_.keys(swaggerClient.apis)); _.each(apis, generateOperations); grunt.log.writeln('generating events documentation'); var models = _.sortBy(_.keys(swaggerClient.apis.events.models)); _.each(models, generateEvents); var template = fs.readFileSync('./dev/README.mustache', 'utf-8'); var output = mustache.render(template, { operations: operations, events: events }); fs.writeFileSync('./README.md', output, 'utf-8'); done(); } } // Swagger failure callback function swaggerFailed (err) { grunt.log.error(err); done(false); } // Generate all operations function generateOperations (resource) { if (resource !== 'events') { operations += util.format('#### %s\n\n', resource); var api = swaggerClient.apis[resource]; var ops = _.sortBy(_.keys(api.operations)); _.each(ops, function (name) { var operation = api.operations[name]; var results = ''; if (operation.type !== null) { var returnType = operation.type; var regexArr = resourcesLib.swaggerListTypeRegex.exec(returnType); if (regexArr !== null) { returnType = util.format('%ss', regexArr[1]); } returnType = returnType.toLowerCase(); results += util.format(', %s', returnType); } var params = ''; var paramsPromises = ''; var requiredParams = []; var availableParams = []; var parameters = _.sortBy(operation.parameters, 'name'); _.each(parameters, function (param) { if (param.required) { requiredParams.push( util.format('%s: val', param.name) ); } availableParams.push( util.format( '- %s (%s) - %s', param.name, param.type, param.description ) ); }); if (requiredParams.length > 0) { params = util.format( '{%s}', requiredParams.join(', ') ); params += ',\n '; paramsPromises = util.format( '{\n %s\n}', requiredParams.join(',\n ') ); } operations += mustache.render(operationTemplate, { name: name, desc: operation.summary, resource: operation.resourceName, params: params, paramsPromises: paramsPromises, results: results, resultsPromises: results.substring(2) }); if (availableParams.length > 0) { operations += util.format( '###### Available Parameters\n%s\n\n', availableParams.join('\n') ); } }); } } // Generate all events function generateEvents (name) { if (name !== 'Event' && name !== 'Message') { var event = swaggerClient.apis.events.models[name]; var results = ''; var props = _.sortBy(event.properties, 'name'); var availableProps = []; var promoted = []; var instances = []; _.each(props, function (prop) { var propType = prop.dataType; var regexArr = resourcesLib.swaggerListTypeRegex.exec(propType); if (regexArr !== null) { propType = util.format('%s', regexArr[1]); } if (_.contains(resourcesLib.knownTypes, propType)) { promoted.push(prop.name); if (!_.contains(instances, propType)) { instances.push(propType); } } availableProps.push( util.format( '- %s (%s) - %s', prop.name, prop.dataType, prop.descr ) ); }); if (promoted.length > 1) { results += util.format(', {%s: val}', promoted.join(': val, ')); } else if (promoted.length === 1) { results += util.format(', %s', promoted[0]); } events += mustache.render(eventTemplate, { name: name, desc: swaggerClient.apis.events.rawModels[name].description, results: results }); if (availableProps.length > 0) { events += util.format( '##### Available Event Properties\n%s\n\n', availableProps.join('\n') ); } if (instances.length > 0) { events += util.format( '##### Resource Specific Emitters\n%s\n\n', instances.join('\n') ); } } } });
return new Promise(function(resolve, reject) { swagger.authorizations.add( 'basic-auth', new swagger.PasswordAuthorization( self._connection.hostname, self._connection.user, self._connection.pass ) ); // Connect to API using swagger and attach resources on Client instance var ariUrl = util.format( '%s//%s/ari/api-docs/resources.json', self._connection.protocol, self._connection.host ); self._swagger = new swagger.SwaggerApi({ url: ariUrl, success: swaggerLoaded, failure: swaggerFailed }); /** * Success handler for swagger connect. * * @callback swaggerConnectSuccessCallback * @method swaggerLoaded * @memberof module:ari-client~Client~_attachApi * @private */ function swaggerLoaded () { if(self._swagger.ready === true) { // Attach resources to client _.each(_.keys(self._swagger.apis), attachResource); // Attach resource creators to client _.each(_resources.knownTypes, attachResourceCreators); resolve(self); } } /** * Failure handler for swagger connect. * * @callback swaggerConnectFailureCallback * @method swaggerFailed * @memberof module:ari-client~Client~_attachApi * @private */ function swaggerFailed (err) { self.emit('APILoadError', err); reject(err); } /** * Attach resource creators to Client instance to enable id generation. * * Optionally, a values object can be used to set certain values on the * resource instance. * * If the first argument is a string, it is used as an id. * * @callback attachResourceCreatorsCallback * @method attachResourceCreators * @memberof module:ari-client~Client~_attachApi * @private * @param {string} resourceType - the type of the resource to setup a * create method for */ function attachResourceCreators (resourceType) { self[resourceType] = function (id, values) { return _resources[resourceType](self, id, values); }; } /** * Attach resources and operations to Client instance. * * @callback attachResourceCallback * @method attachResource * @memberof module:ari-client~Client~_attachApi * @private * @param {string} resource - the name of the resource */ function attachResource (resource) { self[resource] = {}; var operations = self._swagger.apis[resource].operations; _.each(_.keys(operations), attachOperation); // Attach operation to resource function attachOperation (operation) { self[resource][operation] = callSwagger; var oper = self._swagger.apis[resource].operations[operation]; var respType = oper.type; var multi = false; var regexArr = _resources.swaggerListTypeRegex.exec(respType); if (regexArr !== null) { respType = regexArr[1]; multi = true; } var params = oper.parameters; /** * Responsible for calling API through Swagger. * * @callback attachResourceCallback * @memberof module:ari-client~Client~_attachApi~attachResource * @method callSwagger * @private * @param {Object} parameters - parameters to swagger * @param {Function} callback - callback invoked with swagger response * @returns {Q} promise - a promise that will resolve to a client */ function callSwagger (/* args..., callback */) { var args = _.toArray(arguments); // Separate user callback from other args var options = _.first(args); var userCallback = (_.isFunction(_.last(args))) ? _.last(args) : undefined; return new Promise(function(innerResolve, innerReject) { args = []; if (options === undefined || options === null || _.isFunction(options) || _.isArray(options)) { options = {}; } else { // Swagger can alter options passed in options = _.clone(options); // convert body params for swagger options = _utils.parseBodyParams(params, options); } args.push(options); // Inject response processing callback args.push(processResponse); // Inject error handling callback args.push(swaggerError); // Run operation against Swagger self._swagger.apis[resource][operation].apply(null, args); // Handle error from Swagger function swaggerError (err) { if (err && err.data) { err = new Error(err.data.toString('utf-8')); } innerReject(err); } /** * Process response from Swagger. * * @callback callSwaggerSuccessCallback * @method processResponse * @memberof * module:ari-client~Client~_attachApi~attachResource~callSwagger * @private * @param {Object} response - response from swagger */ function processResponse (response) { var result = response.data.toString('utf-8'); if (respType !== null && result) { result = JSON.parse(result); } if (_.contains(_resources.knownTypes, respType) && _resources[respType] !== undefined) { if (multi) { result = _.map(result, function (obj) { return _resources[respType]( self, obj ); }); } else { result = _resources[respType]( self, result ); } } innerResolve(result); } }).asCallback(userCallback); } } } });