import request from 'request'; const showLogMessages = process.env.NODE_DEBUG ? process.env.NODE_DEBUG.indexOf('apidoc') !== -1 : false; const enums = [{"name":"compareString","plural":"compareStrings","values":[{"name":"greaterThan","attributes":[]},{"name":"equals","attributes":[]},{"name":"smallerThan","attributes":[]}],"attributes":[]},{"name":"formType","plural":"formTypes","values":[{"name":"mobileInvitation","attributes":[]},{"name":"code","attributes":[]}],"attributes":[]},{"name":"ratingViewType","plural":"ratingViewTypes","values":[{"name":"slide","attributes":[]},{"name":"numbersSquare","attributes":[]},{"name":"gradingSlider","attributes":[]},{"name":"gradingDropdown","attributes":[]},{"name":"stars","attributes":[]},{"name":"emoticons","attributes":[]},{"name":"numbers","attributes":[]},{"name":"smilies","attributes":[]},{"name":"bars","attributes":[]}],"attributes":[]}]; const unions = [{"name":"component_union","plural":"component_unions","types":[{"type":"component_label","attributes":[],"discriminator_value":"label"},{"type":"component_image","attributes":[],"discriminator_value":"image"},{"type":"component_nps","attributes":[],"discriminator_value":"nps"},{"type":"component_textArea","attributes":[],"discriminator_value":"textArea"},{"type":"component_textInput","attributes":[],"discriminator_value":"textInput"},{"type":"component_radioSelector","attributes":[],"discriminator_value":"radio"},{"type":"component_checkbox","attributes":[],"discriminator_value":"checkbox"},{"type":"component_dropdown","attributes":[],"discriminator_value":"select"},{"type":"component_grading","attributes":[],"discriminator_value":"grading"},{"type":"component_grading0to10","attributes":[],"discriminator_value":"grading0to10"},{"type":"component_grading1to10","attributes":[],"discriminator_value":"grading1to10"}],"attributes":[],"interfaces":[],"discriminator":"component","description":"Represents the question or fields to be filled by the user"},{"name":"feedback_union","plural":"feedback_unions","types":[{"type":"feedback_nps","attributes":[],"discriminator_value":"nps"},{"type":"feedback_textArea","attributes":[],"discriminator_value":"textArea"},{"type":"feedback_textInput","attributes":[],"discriminator_value":"textInput"},{"type":"feedback_radioSelector","attributes":[],"discriminator_value":"radio"},{"type":"feedback_checkbox","attributes":[],"discriminator_value":"checkbox"},{"type":"feedback_dropdown","attributes":[],"discriminator_value":"select"},{"type":"feedback_grading","attributes":[],"discriminator_value":"grading"},{"type":"feedback_grading0to10","attributes":[],"discriminator_value":"grading0to10"},{"type":"feedback_grading1to10","attributes":[],"discriminator_value":"grading1to10"}],"attributes":[],"interfaces":[],"discriminator":"component","description":"Represents the component or fields to be filled by the user"}]; export function getRequestOptions (settings, userOptions) { return new Promise ((resolve, reject) => { if (!isObject(userOptions || {})) { reject(new Error('options parameter is required and must be a plain object')); return; } // Don't mutate the options the user provided var options = Object.assign({}, userOptions); // Handle the body of the request (options.data as provided by the user) if (settings.requiresBody) { if (!options.data) { reject(new Error('options.data property is required.')); return; } if (settings.discriminator) { if(dataIsAndCanBePrimitive(settings.bodyType, options.data)) { const dataUpdate = { [settings.discriminator]: getApidocTypeForPrimitive(settings.bodyType, options.data), value: options.data }; options.data = Object.assign({}, dataUpdate); } if (!options.data[settings.discriminator]) { reject(new Error(`options.data.${settings.discriminator} must be defined. Available options for [${settings.bodyType}] are: ${getTypesForUnion(settings.bodyType).join(', ')}`)); return; } } } var qs = {}; settings.queryParams.forEach((param) => { if (options[param.nameCamelCase]) { qs[param.name] = options[param.nameCamelCase]; } }); const json = settings.isApplicationJson ? options.data : undefined; const form = settings.isFormUrlEncoded ? options.data : undefined; const method = settings.method; resolve(Object.assign(options, { json, form, method, qs })); }); } export function dataIsAndCanBePrimitive (bodyType, data) { const typesForUnion = getTypesForUnion(bodyType); const dataType = typeof data; if (dataType === 'string') { return typesForUnion.indexOf('string') != -1; } else if (dataType === 'number') { return typesForUnion.indexOf('decimal') != -1 || typesForUnion.indexOf('double') != -1 || typesForUnion.indexOf('integer') != -1 || typesForUnion.indexOf('long') != -1; } else { return false; } } // Within the context of a union type export function getApidocTypeForPrimitive (bodyType, data) { const typesForUnion = getTypesForUnion(bodyType); const dataType = typeof data; if (dataType === 'string') { // Check if data matches an enum. Use the enum name if it does. const enumForData = enums.find((e) => { return !!e.values.find((v) => { return v.name === data; }); }); if (enumForData) { return enumForData.name; } // default to 'string' return dataType; } else if (dataType === 'number') { const containsDecimalPoint = data.toString().indexOf('.') !== -1; const possibleApidocTypes = containsDecimalPoint ? ['decimal', 'double'] : ['integer', 'long']; // Return the first one found. Buggy in that this code should know the // difference between each of the apidoc types. They are all 'number' in // JavaScript though. return typesForUnion.find((t) => { return possibleApidocTypes.indexOf(t) !== -1; }); } } export function getTypesForUnion (unionType) { const ut = unions.find((u) => u.name === unionType); if (ut) { return ut.types.map((t) => t.type); } return []; } /** * Simple plain object check. This is actually really involved to be 100% * accurate */ export function isObject (obj) { return typeof obj === 'object' && !Array.isArray(obj); } function log (message) { if (showLogMessages) { console.log('[apidoc] ' + message); } } export function getQueryString (options) { const qs = options.qs || {}; const params = Object.keys(qs).reduce((kvPairs, key) => { return kvPairs.concat(`${key}=${qs[key]}`); }, []); return params.join('&'); } export function doRequest (options) { var startMs = Date.now(); options = options || {}; options.qsStringifyOptions = { arrayFormat: 'repeat' }; var queryString = getQueryString(options); var url = options.uri + (queryString ? '?' + queryString : ''); log(options.method + ' ' + url); if (options.method === 'POST' || options.method === 'PUT' || options.method === 'PATCH') { log('|--> With body:\n\t\t' + JSON.stringify(options.json)); } return new Promise(function (resolve, reject) { request(options, function (err, response) { if (err) { reject(err); return; } var duration = Date.now() - startMs; var requestHref = response.request ? response.request.href : ''; log('Completed ' + options.method + ' ' + requestHref + ' ' + response.statusCode + ' ' + duration + 'ms'); resolve(response); }); }); }