diff --git a/.gitignore b/.gitignore index 311312ea..b0f128e1 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ wks.* *.swp tmp-* +zz/ diff --git a/.jshintignore b/.jshintignore new file mode 100644 index 00000000..eb945d85 --- /dev/null +++ b/.jshintignore @@ -0,0 +1,5 @@ +lib/expose.js +lib/formatter.js +lib/querier.js +lib/splitter.js +zz/ diff --git a/.jshintrc b/.jshintrc index d7950bea..768d6862 100644 --- a/.jshintrc +++ b/.jshintrc @@ -7,7 +7,7 @@ "curly": true, "eqeqeq": true, "immed": true, - "indent": 4, + "indent": 2, "latedef": true, "newcap": false, "noarg": true, @@ -18,6 +18,5 @@ "strict": true, "trailing": true, "smarttabs": true, - "globals": { - } + "globals": {} } diff --git a/README.md b/README.md index 0a725330..58a28a57 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,68 @@ # Swagger to JS & Typescript Codegen -[![Circle CI](https://circleci.com/gh/wcandillon/swagger-js-codegen.svg?style=svg)](https://circleci.com/gh/wcandillon/swagger-js-codegen) [![NPM version](http://img.shields.io/npm/v/swagger-js-codegen.svg?style=flat)](http://badge.fury.io/js/swagger-js-codegen) -## We are looking for a new maintainer +## Installation +```bash +npm install swagger-js-codegen +``` -This project is no longer actively maintained by its creator. Please let us know if you would like to become a maintainer. -At the time we wrote this package, the swagger didn't have generators for JavaScript nor TypeScript. Now there are [great alternatives of this package available](https://github.com/swagger-api/swagger-codegen). +___ -This package generates a nodejs, reactjs or angularjs class from a [swagger specification file](https://github.com/wordnik/swagger-spec). The code is generated using [mustache templates](https://github.com/wcandillon/swagger-js-codegen/tree/master/templates) and is quality checked by [jshint](https://github.com/jshint/jshint/) and beautified by [js-beautify](https://github.com/beautify-web/js-beautify). +## Multi-class generation (Node) -The typescript generator is based on [superagent](https://github.com/visionmedia/superagent) and can be used for both nodejs and the browser via browserify/webpack. +It is possible now to generate multiple controllers for Node. -## Installation -```bash -npm install swagger-js-codegen +Each controller will have a class that has several methods inside of it. + +Each method represents an API, and has a default built-in response. + +Definitions are generated as well. + +**How it works:** + +Definitions are generated before the APIs. File `expose.js` generates all of the necessary definitions and places them in the destination directory. + +APIs are generated after that, based on the Mustache templates. + +Module utilizes the custom Mustache templates (`multi-class` and `multi-method`). + +Mustache generates a single file with a single ES5 class, that contains all of the methods. + +File `splitter.js` splits the single file into several files with classes (based on tags in the original JSON). After the split is completed and methods are combined, they are saved as a controller file in the destination directory. + +**Options:** + +`className` **[REQUIRED]**: name of the single generated class. You can put any name. + +`swagger` **[REQUIRED]**: loaded Swagger JSON file. + +`multiple` **[REQUIRED]**: this option should be provided and should be set to `true` if you need a multi-class output. + +`path` **[REQUIRED]**: location of the destination directories. `__dirname` is the best option, but you can provide your own destination path. + +`controllersDirName` **[OPTIONAL]**: this is the name of the destination directory for **controllers**. `routes_generated` is the recommended name (it is used as default if this option was not provided). + +`definitionsDirName` **[OPTIONAL]**: this is the name of the destination directory for **definitions**. `definitions_generated` is the recommended name (it is used as default if this option was not provided). + +**Multi-class generation example:** + +``` +const { CodeGen } = require('swagger-js-codegen'); +const fs = require('fs'); + +const file = 'swagger/swagger.json'; +const spec = JSON.parse(fs.readFileSync(file, 'UTF-8')); + +await CodeGen.getNodeCode({ + className: 'Service', + swagger: spec, + multiple: true, + path: __dirname, + controllersDirName: 'routes_generated', + definitionsDirName: 'definitions_generated', +}); ``` +____ ## Example ```javascript var fs = require('fs'); diff --git a/lib/codegen.js b/lib/codegen.js index 54dbe7ef..b9424fcf 100644 --- a/lib/codegen.js +++ b/lib/codegen.js @@ -5,327 +5,394 @@ var Mustache = require('mustache'); var beautify = require('js-beautify').js_beautify; var lint = require('jshint').JSHINT; var _ = require('lodash'); + +var expose = require('./expose'); +var formatter = require('./formatter'); +var querier = require('./querier'); +var splitter = require('./splitter'); var ts = require('./typescript'); var normalizeName = function(id) { - return id.replace(/\.|\-|\{|\}|\s/g, '_'); + return id.replace(/\.|\-|\{|\}|\s/g, '_'); }; var getPathToMethodName = function(opts, m, path){ - if(path === '/' || path === '') { - return m; - } + if(path === '/' || path === '') { + return m; + } - // clean url path for requests ending with '/' - var cleanPath = path.replace(/\/$/, ''); + // clean url path for requests ending with '/' + var cleanPath = path.replace(/\/$/, ''); - var segments = cleanPath.split('/').slice(1); - segments = _.transform(segments, function (result, segment) { - if (segment[0] === '{' && segment[segment.length - 1] === '}') { - segment = 'by' + segment[1].toUpperCase() + segment.substring(2, segment.length - 1); - } - result.push(segment); - }); - var result = _.camelCase(segments.join('-')); - return m.toLowerCase() + result[0].toUpperCase() + result.substring(1); + var segments = cleanPath.split('/').slice(1); + segments = _.transform(segments, function (result, segment) { + if (segment[0] === '{' && segment[segment.length - 1] === '}') { + segment = 'by' + segment[1].toUpperCase() + segment.substring(2, segment.length - 1); + } + result.push(segment); + }); + var result = _.camelCase(segments.join('-')); + return m.toLowerCase() + result[0].toUpperCase() + result.substring(1); }; var getViewForSwagger2 = function(opts, type){ - var swagger = opts.swagger; - var methods = []; - var authorizedMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'COPY', 'HEAD', 'OPTIONS', 'LINK', 'UNLIK', 'PURGE', 'LOCK', 'UNLOCK', 'PROPFIND']; - var data = { - isNode: type === 'node' || type === 'react', - isES6: opts.isES6 || type === 'react', - description: swagger.info.description, - isSecure: swagger.securityDefinitions !== undefined, - moduleName: opts.moduleName, - className: opts.className, - imports: opts.imports, - domain: (swagger.schemes && swagger.schemes.length > 0 && swagger.host && swagger.basePath) ? swagger.schemes[0] + '://' + swagger.host + swagger.basePath.replace(/\/+$/g,'') : '', - methods: [], - definitions: [] - }; - - _.forEach(swagger.paths, function(api, path){ - var globalParams = []; - /** - * @param {Object} op - meta data for the request - * @param {string} m - HTTP method name - eg: 'get', 'post', 'put', 'delete' - */ - _.forEach(api, function(op, m){ - if(m.toLowerCase() === 'parameters') { - globalParams = op; - } + var swagger = opts.swagger; + var methods = []; + var authorizedMethods = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'COPY', 'HEAD', 'OPTIONS', 'LINK', 'UNLIK', 'PURGE', 'LOCK', 'UNLOCK', 'PROPFIND']; + var data = { + isNode: type === 'node' || type === 'react', + isES6: opts.isES6 || type === 'react', + description: swagger.info.description, + isSecure: swagger.securityDefinitions !== undefined, + moduleName: opts.moduleName, + className: opts.className, + imports: opts.imports, + domain: (swagger.schemes && swagger.schemes.length > 0 && swagger.host && swagger.basePath) ? swagger.schemes[0] + '://' + swagger.host + swagger.basePath.replace(/\/+$/g,'') : '', + methods: [], + definitions: [] + }; + + _.forEach(swagger.paths, function(api, path) { + var globalParams = []; + /** + * @param {Object} op - meta data for the request + * @param {string} m - HTTP method name - eg: 'get', 'post', 'put', 'delete' + */ + _.forEach(api, function(op, m) { + if (m.toLowerCase() === 'parameters') { + globalParams = op; + } + }); + _.forEach(api, function(op, m) { + var M = m.toUpperCase(); + if (M === '' || authorizedMethods.indexOf(M) === -1) { + return; + } + var secureTypes = []; + if (swagger.securityDefinitions !== undefined || op.security !== undefined) { + var mergedSecurity = _.merge([], swagger.security, op.security).map(function(security) { + return Object.keys(security); }); - _.forEach(api, function(op, m){ - var M = m.toUpperCase(); - if(M === '' || authorizedMethods.indexOf(M) === -1) { - return; - } - var secureTypes = []; - if(swagger.securityDefinitions !== undefined || op.security !== undefined) { - var mergedSecurity = _.merge([], swagger.security, op.security).map(function(security){ - return Object.keys(security); - }); - if(swagger.securityDefinitions) { - for(var sk in swagger.securityDefinitions) { - if(mergedSecurity.join(',').indexOf(sk) !== -1){ - secureTypes.push(swagger.securityDefinitions[sk].type); - } - } - } - } - var methodName = (op.operationId ? normalizeName(op.operationId) : getPathToMethodName(opts, m, path)); - // Make sure the method name is unique - if(methods.indexOf(methodName) !== -1) { - var i = 1; - while(true) { - if(methods.indexOf(methodName + '_' + i) !== -1) { - i++; - } else { - methodName = methodName + '_' + i; - break; - } - } - } - methods.push(methodName); - - var method = { - path: path, - className: opts.className, - methodName: methodName, - method: M, - isGET: M === 'GET', - isPOST: M === 'POST', - summary: op.description || op.summary, - externalDocs: op.externalDocs, - isSecure: swagger.security !== undefined || op.security !== undefined, - isSecureToken: secureTypes.indexOf('oauth2') !== -1, - isSecureApiKey: secureTypes.indexOf('apiKey') !== -1, - isSecureBasic: secureTypes.indexOf('basic') !== -1, - parameters: [], - headers: [] - }; - if(method.isSecure && method.isSecureToken) { - data.isSecureToken = method.isSecureToken; - } - if(method.isSecure && method.isSecureApiKey) { - data.isSecureApiKey = method.isSecureApiKey; - } - if(method.isSecure && method.isSecureBasic) { - data.isSecureBasic = method.isSecureBasic; - } - var produces = op.produces || swagger.produces; - if(produces) { - method.headers.push({ - name: 'Accept', - value: `'${produces.map(function(value) { return value; }).join(', ')}'`, - }); + if (swagger.securityDefinitions) { + for (var sk in swagger.securityDefinitions) { + if (mergedSecurity.join(',').indexOf(sk) !== -1) { + secureTypes.push(swagger.securityDefinitions[sk].type); } + } + } + } - var consumes = op.consumes || swagger.consumes; - if(consumes) { - method.headers.push({name: 'Content-Type', value: '\'' + consumes + '\'' }); - } + var methodName = (op.operationId ? normalizeName(op.operationId) : getPathToMethodName(opts, m, path)); - var params = []; - if(_.isArray(op.parameters)) { - params = op.parameters; - } - params = params.concat(globalParams); - _.forEach(params, function(parameter) { - //Ignore parameters which contain the x-exclude-from-bindings extension - if(parameter['x-exclude-from-bindings'] === true) { - return; - } - - // Ignore headers which are injected by proxies & app servers - // eg: https://cloud.google.com/appengine/docs/go/requests#Go_Request_headers - if (parameter['x-proxy-header'] && !data.isNode) { - return; - } - if (_.isString(parameter.$ref)) { - var segments = parameter.$ref.split('/'); - parameter = swagger.parameters[segments.length === 1 ? segments[0] : segments[2] ]; - } - parameter.camelCaseName = _.camelCase(parameter.name); - if(parameter.enum && parameter.enum.length === 1) { - parameter.isSingleton = true; - parameter.singleton = parameter.enum[0]; - } - if(parameter.in === 'body'){ - parameter.isBodyParameter = true; - } else if(parameter.in === 'path'){ - parameter.isPathParameter = true; - } else if(parameter.in === 'query'){ - if(parameter['x-name-pattern']){ - parameter.isPatternType = true; - parameter.pattern = parameter['x-name-pattern']; - } - parameter.isQueryParameter = true; - } else if(parameter.in === 'header'){ - parameter.isHeaderParameter = true; - } else if(parameter.in === 'formData'){ - parameter.isFormParameter = true; - } - parameter.tsType = ts.convertType(parameter); - parameter.cardinality = parameter.required ? '' : '?'; - method.parameters.push(parameter); - }); - data.methods.push(method); + // Make sure the method name is unique + if (methods.indexOf(methodName) !== -1) { + var i = 1; + while (true) { + if (methods.indexOf(methodName + '_' + i) !== -1) { + i++; + } else { + methodName = methodName + '_' + i; + break; + } + } + } + methods.push(methodName); + + var method = { + path: path, + className: opts.className, + methodName: methodName, + method: M, + isGET: M === 'GET', + isPOST: M === 'POST', + summary: op.description || op.summary, + externalDocs: op.externalDocs, + isSecure: swagger.security !== undefined || op.security !== undefined, + isSecureToken: secureTypes.indexOf('oauth2') !== -1, + isSecureApiKey: secureTypes.indexOf('apiKey') !== -1, + isSecureBasic: secureTypes.indexOf('basic') !== -1, + parameters: [], + headers: [], + }; + + // add 'destination' field if 'multiple: true' + if (opts.multiple) { + method.destination = op.tags[0].toLowerCase(); + } + + // add 'responses' field, that contains schemas and descriptions + method.responses = op.responses; + + if(method.isSecure && method.isSecureToken) { + data.isSecureToken = method.isSecureToken; + } + if(method.isSecure && method.isSecureApiKey) { + data.isSecureApiKey = method.isSecureApiKey; + } + if(method.isSecure && method.isSecureBasic) { + data.isSecureBasic = method.isSecureBasic; + } + var produces = op.produces || swagger.produces; + if (produces) { + method.headers.push({ + name: 'Accept', + value: `'${produces.map(function(value) { return value; }).join(', ')}'`, }); + } + + var consumes = op.consumes || swagger.consumes; + if(consumes) { + method.headers.push({name: 'Content-Type', value: '\'' + consumes + '\'' }); + } + + var params = []; + if(_.isArray(op.parameters)) { + params = op.parameters; + } + params = params.concat(globalParams); + _.forEach(params, function(parameter) { + //Ignore parameters which contain the x-exclude-from-bindings extension + if(parameter['x-exclude-from-bindings'] === true) { + return; + } + + // Ignore headers which are injected by proxies & app servers + // eg: https://cloud.google.com/appengine/docs/go/requests#Go_Request_headers + if (parameter['x-proxy-header'] && !data.isNode) { + return; + } + if (_.isString(parameter.$ref)) { + var segments = parameter.$ref.split('/'); + parameter = swagger.parameters[segments.length === 1 ? segments[0] : segments[2] ]; + } + parameter.camelCaseName = _.camelCase(parameter.name); + if(parameter.enum && parameter.enum.length === 1) { + parameter.isSingleton = true; + parameter.singleton = parameter.enum[0]; + } + if(parameter.in === 'body'){ + parameter.isBodyParameter = true; + } else if(parameter.in === 'path'){ + parameter.isPathParameter = true; + } else if(parameter.in === 'query'){ + if(parameter['x-name-pattern']){ + parameter.isPatternType = true; + parameter.pattern = parameter['x-name-pattern']; + } + parameter.isQueryParameter = true; + } else if(parameter.in === 'header'){ + parameter.isHeaderParameter = true; + } else if(parameter.in === 'formData'){ + parameter.isFormParameter = true; + } + parameter.tsType = ts.convertType(parameter); + parameter.cardinality = parameter.required ? '' : '?'; + method.parameters.push(parameter); + }); + data.methods.push(method); }); + }); - _.forEach(swagger.definitions, function(definition, name){ - data.definitions.push({ - name: name, - description: definition.description, - tsType: ts.convertType(definition, swagger) - }); + _.forEach(swagger.definitions, function(definition, name) { + data.definitions.push({ + name: name, + description: definition.description, + tsType: ts.convertType(definition, swagger) }); + }); - return data; + return data; }; var getViewForSwagger1 = function(opts, type){ - var swagger = opts.swagger; - var data = { - isNode: type === 'node' || type === 'react', - isES6: opts.isES6 || type === 'react', - description: swagger.description, - moduleName: opts.moduleName, + var swagger = opts.swagger; + var data = { + isNode: type === 'node' || type === 'react', + isES6: opts.isES6 || type === 'react', + description: swagger.description, + moduleName: opts.moduleName, + className: opts.className, + domain: swagger.basePath ? swagger.basePath : '', + methods: [] + }; + swagger.apis.forEach(function(api){ + api.operations.forEach(function(op){ + if (op.method === 'OPTIONS') { + return; + } + var method = { + path: api.path, className: opts.className, - domain: swagger.basePath ? swagger.basePath : '', - methods: [] - }; - swagger.apis.forEach(function(api){ - api.operations.forEach(function(op){ - if (op.method === 'OPTIONS') { - return; - } - var method = { - path: api.path, - className: opts.className, - methodName: op.nickname, - method: op.method, - isGET: op.method === 'GET', - isPOST: op.method.toUpperCase() === 'POST', - summary: op.summary, - parameters: op.parameters, - headers: [] - }; - - if(op.produces) { - var headers = []; - headers.value = []; - headers.name = 'Accept'; - headers.value.push(op.produces.map(function(value) { return '\'' + value + '\''; }).join(', ')); - method.headers.push(headers); - } + methodName: op.nickname, + method: op.method, + isGET: op.method === 'GET', + isPOST: op.method.toUpperCase() === 'POST', + summary: op.summary, + parameters: op.parameters, + headers: [] + }; - op.parameters = op.parameters ? op.parameters : []; - op.parameters.forEach(function(parameter) { - parameter.camelCaseName = _.camelCase(parameter.name); - if(parameter.enum && parameter.enum.length === 1) { - parameter.isSingleton = true; - parameter.singleton = parameter.enum[0]; - } - if(parameter.paramType === 'body'){ - parameter.isBodyParameter = true; - } else if(parameter.paramType === 'path'){ - parameter.isPathParameter = true; - } else if(parameter.paramType === 'query'){ - if(parameter['x-name-pattern']){ - parameter.isPatternType = true; - parameter.pattern = parameter['x-name-pattern']; - } - parameter.isQueryParameter = true; - } else if(parameter.paramType === 'header'){ - parameter.isHeaderParameter = true; - } else if(parameter.paramType === 'form'){ - parameter.isFormParameter = true; - } - }); - data.methods.push(method); - }); - }); - return data; -}; + if(op.produces) { + var headers = []; + headers.value = []; + headers.name = 'Accept'; + headers.value.push(op.produces.map(function(value) { return '\'' + value + '\''; }).join(', ')); + method.headers.push(headers); + } -var getCode = function(opts, type) { - // For Swagger Specification version 2.0 value of field 'swagger' must be a string '2.0' - var data = opts.swagger.swagger === '2.0' ? getViewForSwagger2(opts, type) : getViewForSwagger1(opts, type); - if (type === 'custom') { - if (!_.isObject(opts.template) || !_.isString(opts.template.class) || !_.isString(opts.template.method)) { - throw new Error('Unprovided custom template. Please use the following template: template: { class: "...", method: "...", request: "..." }'); - } - } else { - if (!_.isObject(opts.template)) { - opts.template = {}; + op.parameters = op.parameters ? op.parameters : []; + op.parameters.forEach(function(parameter) { + parameter.camelCaseName = _.camelCase(parameter.name); + if(parameter.enum && parameter.enum.length === 1) { + parameter.isSingleton = true; + parameter.singleton = parameter.enum[0]; } - var templates = __dirname + '/../templates/'; - opts.template.class = opts.template.class || fs.readFileSync(templates + type + '-class.mustache', 'utf-8'); - opts.template.method = opts.template.method || fs.readFileSync(templates + (type === 'typescript' ? 'typescript-' : '') + 'method.mustache', 'utf-8'); - if(type === 'typescript') { - opts.template.type = opts.template.type || fs.readFileSync(templates + 'type.mustache', 'utf-8'); + if(parameter.paramType === 'body'){ + parameter.isBodyParameter = true; + } else if(parameter.paramType === 'path'){ + parameter.isPathParameter = true; + } else if(parameter.paramType === 'query'){ + if(parameter['x-name-pattern']){ + parameter.isPatternType = true; + parameter.pattern = parameter['x-name-pattern']; + } + parameter.isQueryParameter = true; + } else if(parameter.paramType === 'header'){ + parameter.isHeaderParameter = true; + } else if(parameter.paramType === 'form'){ + parameter.isFormParameter = true; } - } + }); + data.methods.push(method); + }); + }); + return data; +}; - if (opts.mustache) { - _.assign(data, opts.mustache); +/** + * Generate code based on the input file + * @param options - options for the file generation + * @param type - type of code / file to be generated (angular, custom, node, react, typescript) + * @returns {*} + */ +var getCode = function(options, type) { + // check 'multiple' & all of the required parameters + const opts = _.cloneDeep(options); + if (options.multiple) { + if (!options.className) { + throw new Error('Missing the class name!'); } - - var source = Mustache.render(opts.template.class, data, opts.template); - var lintOptions = { - node: type === 'node' || type === 'custom', - browser: type === 'angular' || type === 'custom' || type === 'react', - undef: true, - strict: true, - trailing: true, - smarttabs: true, - maxerr: 999 - }; - if (opts.esnext) { - lintOptions.esnext = true; + if (!options.swagger) { + throw new Error('Missing the Swagger JSON!'); } - - if(type === 'typescript') { - opts.lint = false; + if (!options.path) { + throw new Error('Missing the destination path!'); } + if (!options.controllersDirName) { + opts.controllersDirName = 'routes_generated'; + console.log('> swagger-js-codegen @ Controllers directory name not provided, using \'routes_generated\' as a default!'); + } + if (!options.definitionsDirName) { + opts.definitionsDirName = 'definitions_generated'; + console.log('> swagger-js-codegen @ Definitions directory name not provided, using \'definitions_generated\' as a default!'); + } + } - if (opts.lint === undefined || opts.lint === true) { - lint(source, lintOptions); - lint.errors.forEach(function(error) { - if (error.code[0] === 'E') { - throw new Error(error.reason + ' in ' + error.evidence + ' (' + error.code + ')'); - } - }); + // For Swagger Specification version 2.0 value of field 'swagger' must be a string '2.0' + var swaggerView = opts.swagger.swagger === '2.0' ? getViewForSwagger2(opts, type) : getViewForSwagger1(opts, type); + + // format the default responses for the APIs, add objects for the load + var formatted = formatter.format(swaggerView); + + // create definitions + expose(opts.swagger.definitions, formatted.methods, opts.path, opts.definitionsDirName); + + // add all of the necessary query options + var data = querier(formatted); + + if (type === 'custom') { + if (!_.isObject(opts.template) || !_.isString(opts.template.class) || !_.isString(opts.template.method)) { + throw new Error('Unprovided custom template. Please use the following template: template: { class: "...", method: "...", request: "..." }'); + } + } else { + if (!_.isObject(opts.template)) { + opts.template = {}; } - if (opts.beautify === undefined || opts.beautify === true) { - return beautify(source, { indent_size: 4, max_preserve_newlines: 2 }); + var templates = __dirname + '/../templates/'; + + // choose templates based on the 'multiple' option TODO: Typescript support? + if (opts.multiple) { + opts.template.class = fs.readFileSync(templates + 'multi-class.mustache', 'utf-8'); + opts.template.method = fs.readFileSync(templates + 'multi-method.mustache', 'utf-8'); } else { - return source; + opts.template.class = opts.template.class || fs.readFileSync(templates + type + '-class.mustache', 'utf-8'); + opts.template.method = opts.template.method || fs.readFileSync(templates + (type === 'typescript' ? 'typescript-' : '') + 'method.mustache', 'utf-8'); } + if (type === 'typescript') { + opts.template.type = opts.template.type || fs.readFileSync(templates + 'type.mustache', 'utf-8'); + } + } + + if (opts.mustache) { + _.assign(data, opts.mustache); + } + + var source = Mustache.render(opts.template.class, data, opts.template); + var lintOptions = { + node: type === 'node' || type === 'custom', + browser: type === 'angular' || type === 'custom' || type === 'react', + undef: true, + strict: true, + trailing: true, + smarttabs: true, + maxerr: 999 + }; + if (opts.esnext) { + lintOptions.esnext = true; + } + + if(type === 'typescript') { + opts.lint = false; + } + + if (opts.lint === undefined || opts.lint === true) { + lint(source, lintOptions); + lint.errors.forEach(function(error) { + if (error.code[0] === 'E') { + throw new Error(error.reason + ' in ' + error.evidence + ' (' + error.code + ')'); + } + }); + } + if (opts.multiple) { + return splitter.split(beautify(source, { + indent_size: 2, + max_preserve_newlines: 2 + }), opts.className, opts.path, opts.controllersDirName); + } + if (opts.beautify === undefined || opts.beautify === true) { + return beautify(source, { indent_size: 4, max_preserve_newlines: 2 }); + } else { + return source; + } }; exports.CodeGen = { - getTypescriptCode: function(opts){ - if (opts.swagger.swagger !== '2.0') { - throw 'Typescript is only supported for Swagger 2.0 specs.'; - } - return getCode(opts, 'typescript'); - }, - getAngularCode: function(opts){ - return getCode(opts, 'angular'); - }, - getNodeCode: function(opts){ - return getCode(opts, 'node'); - }, - getReactCode: function(opts){ - return getCode(opts, 'react'); - }, - getCustomCode: function(opts){ - return getCode(opts, 'custom'); + getTypescriptCode: function(opts){ + if (opts.swagger.swagger !== '2.0') { + throw 'Typescript is only supported for Swagger 2.0 specs.'; } + return getCode(opts, 'typescript'); + }, + getAngularCode: function(opts){ + return getCode(opts, 'angular'); + }, + getNodeCode: function(opts){ + return getCode(opts, 'node'); + }, + getReactCode: function(opts){ + return getCode(opts, 'react'); + }, + getCustomCode: function(opts){ + return getCode(opts, 'custom'); + } }; diff --git a/lib/expose.js b/lib/expose.js new file mode 100644 index 00000000..c39e96d5 --- /dev/null +++ b/lib/expose.js @@ -0,0 +1,227 @@ +const beauty = require('js-beautify').js; +const fs = require('fs'); +const { inspect } = require('util'); + +/** + * Expose definitions objects, create files with objects + * @param {object} definitions - object that contain definitions objects + * @param {array} methods - array of the available methods + * @param {string} path - where to generate the files, resulting path will be path/ + * @param {string} directory - name of the directory + */ +function expose(definitions, methods, path, directory) { + try { + // get list of the definitions + const list = Object.keys(definitions); + + // do not proceed if there are no definitions + if (list.length === 0) { + return console.log('> swagger-js-codegen @ No objects to expose!'); + } + + // make sure that ~/definitions directory exists + const container = `${path}/${directory}`; + if (!fs.existsSync(container)) { + fs.mkdirSync(container); + } + + // process definitions + list.forEach(async (definition) => { + // bind the parameters + let parameters = ''; + const props = Object.keys(definitions[definition].properties); + if (props.length && props.length > 0) { + props.forEach((prop) => { + const { type,format } = definitions[definition].properties[prop]; + if (type) { + if (type === 'string' && format === 'date-time') { + parameters = `${parameters} + this.data['${prop}'] = params['${prop}'].replace(/T/, ' ').replace('Z', '');`; + }else if (type === 'array') { + const { items } = definitions[definition].properties[prop]; + if (items) { + if (items['$ref']) { + const refName = items['$ref'].split('/').slice(-1)[0]; + Array.isArray() + parameters = `${parameters} + this.data['${prop}'] = []; + if(!params['${prop}'])params['${prop}'] = [] + if (params['${prop}'].length && params['${prop}'].length > 0) { + params['${prop}'].forEach((object) => { + const ${refName} = new global.classes['${refName}'](req, res, object); + this.data.${prop}.push(${refName}.data); + }); + }`; + } else { + parameters = `${parameters} + this.data['${prop}'] = params['${prop}'];`; + } + } else { + parameters = `${parameters} + this.data['${prop}'] = params['${prop}'];`; + } + } else { + parameters = `${parameters} + this.data['${prop}'] = params['${prop}'];`; + } + } else { + if (definitions[definition].properties[prop]['$ref']) { + const refName = definitions[definition].properties[prop]['$ref'].split('/').slice(-1)[0]; + parameters = `${parameters} + this['${refName}'] = new global.classes['${refName}'](req, res, params['${prop}']); + this.data['${prop}'] = this['${refName}'].data; + `; + } + } + }); + } + + // check x-AuthFieldType field + const secure = []; + const secureForEntitySystem = []; + + if (!(definitions[definition].properties instanceof Array)) { + const properties = Object.keys(definitions[definition].properties); + const define = Object.keys(definitions[definition]); + + properties.forEach((property) => { + if ((definitions[definition].properties[property]['x-AuthFieldType'])) { + + methods.forEach((method) => { + method.parameters.forEach((parameter) => { + if (parameter.name === definition) { + secure.push({ + type: parameter['in'], + definition, + property, + value: definitions[definition].properties[property]['x-AuthFieldType'], + parameter_type: definitions[definition].properties[property].type + }); + } + }); + }); + } + }) + + define.forEach((el) => { + if ((el == 'x-EntitySystem')) { + + methods.forEach((method) => { + method.parameters.forEach((parameter) => { + if (parameter.name === definition) { + secureForEntitySystem.push({ + type: parameter['in'], + definition: 'secure', + property: 'secure2', + value: 'secure3', + parameter_type: 'securesecure' + }); + } + }); + }); + } + + }); + } else { + definitions[definition].properties.forEach((property, i) => { + if (property['x-AuthFieldType'] || 'x-EntitySystem') { + methods.forEach((method) => { + method.parameters.forEach((parameter) => { + if (parameter.name === definition) { + secure.push({ + type: parameter['in'], + definition, + property, + value: property['x-AuthFieldType'], + parameter_type:property.type + }); + } + }) + }); + } + }); + } + + // add validation + let validation = ''; + let validators = []; + let validatorsByIdAndType = []; + if (secure.length > 0) { + secure.forEach((property) => { + let origin = property.type; + if (origin === 'path') { origin = 'req.params' } else { origin = 'this.data' }; + validators.push(`${origin}['${property.property}'] = await global.FieldValidator.validate('${property.value}','${property.parameter_type}',${origin}['${property.property}'], this.req, this.res);`); + }); + + validation = ` + async validate() { + try { + ${validators.join('\n')} + } catch (error) { + console.log('validation error', error); + throw new Error(error.message); + } + } + `; + } + + if (secureForEntitySystem.length > 0) { + secureForEntitySystem.forEach((property) => { + let origin = property.type; + if (origin === 'path') { origin = 'req.params' } else { origin = 'this.data' }; + validatorsByIdAndType.push(`${origin}['${props[0]}'] = await global.FieldValidator.validateByIdAndType('${props[0]}','${definitions[definition].type}',${origin}['${props[0]}'], this.req, this.res);`); + + }); + console.log(validatorsByIdAndType); + + validation = ` + async validateByIdAndType() { + try { + ${validatorsByIdAndType.join('\n')} + } catch (error) { + console.log('validation error', error); + throw new Error(error.message); + } + } + `; + } + + + + + // compile the file + const content = `/* auto-generated: ${definition}.js */ + + module.exports = class { + constructor(req = {}, res = {}, params = {}) { + this.req = req; + this.res = res; + this.params = params; + this.data = {}; + ${parameters} + this.schema = ${inspect(definitions[definition], { showHidden: false, depth: null })}; + } + ${validation} + };`; + + // make sure that destination definition directory exists + const destination = `${container}/${definition}`; + if (!fs.existsSync(destination)) { + fs.mkdirSync(destination); + } + + // create file in the destination folder + fs.writeFileSync(`${destination}/${definition}.js`, + beauty(content, { indent_size: 2 }), + (err) => { + if (err) { + throw new Error(err.message || err); + } + }); + }); + } catch (err) { + throw new Error(err.message || err); + } +} + +module.exports = expose; diff --git a/lib/formatter.js b/lib/formatter.js new file mode 100644 index 00000000..e4296bd9 --- /dev/null +++ b/lib/formatter.js @@ -0,0 +1,214 @@ +const { inspect } = require('util'); +const _ = require('lodash'); + +/** + * Parse nested schemas to build the proper response structure + * @param {object} entry - entry definition object + * @param {array} definitions - all of the definitions + * @param {number} status - response status + * @returns {object} + */ +function responseBuilder(entry, definitions, status) { + try { + const response = {}; + + // check tsType + const { tsType } = entry || {}; + if (!tsType) { + return response; + } + + // process properties + const { properties } = tsType || {}; + if (properties && properties.length > 0) { + properties.forEach((property) => { + if (property.tsType === 'string') { + response[property.name] = property.example || 'string'; + + // this is done for a particular case + // TODO: proper error messages mapping - sligtly change the formatter + if (status >= 400) { + if (property.name === 'description') { + response[property.name] = 'ERROR_DESCRIPTION'; + } + if (property.name === 'reasonPhrase') { + response[property.name] = 'BAD_REQUEST'; + } + } + + } + + if (property.tsType === 'number') { + response[property.name] = property.example || 0; + } + + if (property.tsType === 'array') { + // use provided example if any + if (property.example) { + response[property.name] = property.example; + } else { + // check elementType + if (property.elementType) { + const { tsType: type, target } = ((property || {}).elementType || {}); + if (type && type === 'ref' && target) { + definitions.forEach((definition) => { + if (definition.name === target) { + // recursive call to unwrap all of the refs + response[property.name] = [responseBuilder(definition, definitions, status)]; + } + }); + } else { + response[property.name] = []; + } + } else { + response[property.name] = []; + } + } + } + + // just in case... + if (property.tsType === 'object') { + response[property.name] = property.example || {}; + } + + if (property.tsType === 'ref') { + definitions.forEach((definition) => { + if (definition.name === property.target) { + // recursive call to unwrap all of the refs + response[property.name] = responseBuilder(definition, definitions, status); + } + }); + } + }); + } + + return response; + } catch (err) { + throw new Error(err.message || err); + } +} + +/** + * Format the responses for the APIs + * @param data - initial data, that should have all of the necessary methods and schemas + * @returns {object} + */ +function format(data) { + try { + const { methods, definitions } = data; + const objects = []; + + // check if there are none + if (!(methods && methods.length > 0 && definitions && definitions.length > 0)) { + return new Error('Methods and definitions should not be empty!'); + } + + const mutable = _.cloneDeep(data); + + // locate all of the protected properties + const secure = []; + definitions.forEach((definition) => { + definition.tsType.properties.forEach((property) => { + if (property['x-AuthFieldType']) { + secure.push({ + parameterName: definition.name, + propertyName: property.name, + value: property['x-AuthFieldType'], + }); + } + }); + }); + + // get definitions based on $ref + methods.forEach((method, i) => { + const list = Object.keys(method.responses); + const formatted = {}; + if (list.length > 0) { + list.forEach((response) => { + formatted[response] = method.responses[response]; + const refName = formatted[response].schema.items ? + formatted[response].schema.items['$ref'].split('/').slice(-1)[0] : + formatted[response].schema['$ref'].split('/').slice(-1)[0]; + definitions.forEach((definition) => { + // copy properties + if (refName === definition.name) { + formatted[response].properties = definition.tsType.properties; + formatted[response].status = Number(response) || null; + } + }); + }); + } + + // pass protected properties to the parameters + secure.forEach((property, j) => { + method.parameters.forEach((parameter, k) => { + if (parameter.name === property.parameterName) { + mutable.methods[i].parameters[k]['x-AuthFieldType'] = secure[j]; + } + }); + }); + + // add object references to the method (load objects as local variables inside the controller) + method.parameters.forEach((parameter) => { + if (parameter.schema) { + const reference = parameter.schema['$ref'] ? + parameter.schema['$ref'].split('/').slice(-1)[0] : + parameter.schema.items['$ref'].split('/').slice(-1)[0]; + objects.push({ + destination: method.destination, + origin: parameter['in'] === 'path' ? 'params' : parameter['in'], + parameterName: parameter.name, + reference, + }) + } + }); + + // generate the code + list.forEach((response) => { + const ref = formatted[response].schema.items ? + formatted[response].schema.items['$ref'].split('/').slice(-1)[0] : + formatted[response].schema['$ref'].split('/').slice(-1)[0]; + let responseObject = {}; + definitions.forEach((def) => { + if (def.name === ref) { + responseObject = responseBuilder(def, definitions, formatted[response].status); + } + }); + + + const isErr = formatted[response].status >= 400 ? 'err' : 'null'; + formatted[response].code = `res.code(${formatted[response].status}).send(` + + `${inspect(responseObject, { showHidden: false, depth: null })}, ${isErr});`; + }); + + // add the code to the resulting object + mutable.methods[i].responses = formatted; + }); + + // add objects + mutable.objects = objects; + + // fix x-AuthFieldType TODO: need to rewrite it properly + mutable.methods.forEach((method, m) => { + method.parameters.forEach((parameter, p) => { + if (parameter['x-AuthFieldType']) { + const { propertyName: name, value } = parameter['x-AuthFieldType']; + if (!(name && value)) { + mutable.methods[m].parameters[p]['x-AuthFieldType'] = { + propertyName: parameter.name, + value: parameter['x-AuthFieldType'], + }; + } + } + }); + }); + + return mutable; + } catch (err) { + throw new Error(err.message || err); + } +} + +module.exports = { + format, +}; diff --git a/lib/querier.js b/lib/querier.js new file mode 100644 index 00000000..313550ba --- /dev/null +++ b/lib/querier.js @@ -0,0 +1,100 @@ +const _ = require('lodash'); + +const specialKeys = ['Add', 'Create', 'Delete', 'Disable', 'Update', 'Assign', 'Unassign']; + +function capitalizeFirstLetter(string) { + return string.charAt(0).toUpperCase() + string.slice(1); +} + +function getPropertiesForMSSQL(params) { + let inputsJSONParameters = ""; + const variables = []; + params.forEach((param) => { + if (param.name) { + variables.push('@' + param.name); + if(param.in === 'body') inputsJSONParameters += `${param.name}: ${param.name}.data`; + else inputsJSONParameters += `${param.name}`; + } + }); + return { + inputs: `{${inputsJSONParameters}}`, + variables: variables.join(', '), + } +} + +/** + * Get the required properties for the query + * @param params {array} - array of the method parameters + * @returns {object} - { parameters: {string}, questions: {string} } + */ +function getProperties(params) { + const parameters = []; + const questions = []; + params.forEach((param) => { + if (param.name) { + if(param.in === 'body') + parameters.push(param.name + '.data'); + else + parameters.push(param.name); + } + questions.push('?'); + }); + return { + parameters: parameters.join(', '), + questions: questions.join(', '), + } +} + +/** + * Create SQL query for the method + * @param data {object} - object with definitions & methods + * @returns {object} - same as data, but with updated methods + */ +function querier(data) { + try { + const mutable = _.cloneDeep(data); + const { methods, definitions } = mutable; + + if (!(methods && methods.length > 0 && definitions && definitions.length > 0)) { + return new Error('Methods and definitions should not be empty!'); + } + + methods.forEach((method, m) => { + let special = false; + specialKeys.forEach((key) => { + if (method.methodName.includes(key)) { + special = true; + } + }); + + const { inputs, variables } = getPropertiesForMSSQL(method.parameters, special); + let query =''; + if(special){ + query = `CALL SP_${method.methodName}(${variables})`; + } else { + query = `SELECT FN_${method.methodName}(${variables}) as Response`; + } + + mutable.methods[m].query = `const results = await dal.query("${query}", { inputs: ${inputs} } , { redis: ${!special} });`; + + /* + const { parameters, questions } = getProperties(method.parameters, special); + let query =''; + if(special){ + query = `CALL SP_${method.methodName}(${questions})`; + }else{ + query = `SELECT FN_${method.methodName}(${questions}) as Response`; + } + mutable.methods[m].query = `const results = await dal.query("${query}", ` + + `[${parameters}], { redis: ${!special} });`; + + */ + }); + + return mutable; + } catch (err) { + throw new Error(err.message || err); + } +} + +module.exports = querier; diff --git a/lib/splitter.js b/lib/splitter.js new file mode 100644 index 00000000..f939f82e --- /dev/null +++ b/lib/splitter.js @@ -0,0 +1,144 @@ +const beautify = require('js-beautify').js; +const fs = require('fs'); +const { transform } = require('lebab'); +const _ = require('lodash'); + +/** + * First letter capitalization, utility function + * @param string + * @returns {string} + */ +function capitalize(string) { + return string[0].toUpperCase() + string.slice(1); +} + +/** + * Split the code to create multiple files and directories + * @param {string} source - source code generated by swagger-js-codegen (using special templates!) + * @param {string} className - specified class name + * @param {string} path - path to the project directory, that calls the code generator (__dirname) + * @param {string} dir - name of the container directory + * @returns {array} - array of objects (files and wrapper) + */ +async function split(source, className, path, dir) { + // check if everything we need is there + if (!(source && className && path && dir)) { + throw new Error('Missing some of the required parameters!'); + } + + try { + // convert ES5 to ES6 + const { code, warnings } = transform(source, ['let', 'arrow', 'arrow-return', 'class']); + // show conversion errors and warnings + if (warnings && warnings.length && warnings.length > 0) { + console.log('> swagger-js-codegen @ ES6 conversion warnings:\n', warnings); + } + // create the source file + fs.writeFileSync(`${__dirname}/source.js`, code, (err) => { + if (err) { + throw new Error(err.message || err); + } + }); + // load source file and get all of the available methods from the class + const Instance = require(`${__dirname}/source.js`)[`${capitalize(className.toLowerCase())}`]; + const methods = Object.getOwnPropertyNames(Instance.prototype).filter(m => m !== 'constructor'); + + // abort everything if there are no methods (i. e. incorrect JSON or something went wrong) + if (methods.length === 0) { + return console.log('> Methods not found'); + } + + // create new instance of the class, use it as a provider of the code + const provider = new Instance(); + + // process all of the methods, store code in array + const destinations = []; + methods.forEach((method) => { + let standalone = provider[method].toString(); + let functionName = standalone.split('(req, res)')[0]; + const destination = functionName.split('_')[0]; + functionName = functionName.split('_')[1]; + standalone = `async ${functionName}(req, res) ${standalone.split('(req, res)')[1]}`; + standalone = standalone.split('await_FieldValidator').join('await global.FieldValidator'); + destinations.push({ + content: standalone, + file: destination, + function: functionName, + }); + }); + // create file list + const files = []; + destinations.forEach((f) => { + if (!files.some(entry => entry.file === f.file)) { + files.push({ + content: '', + file: f.file, + functions: [], + }); + } + }); + // building the controllers + files.forEach((file, i) => { + destinations.forEach((d) => { + if (file.file === d.file) { + files[i].content = `${files[i].content}${d.content}`; + files[i].functions.push(d.function); + } + }); + }); + + // add 'use strict', exporting and bind definitions + const dal = '// const dal = require(\'../../helpers/dal_mssql\'); \n// const dal = require(\'../../helpers/dal\');'; + + files.forEach((file, i) => { + let fList = ''; + file.functions.forEach((f) => { + fList = `${fList} + ${f},`; + }); + files[i].content = beautify(`${dal} + + module.exports = class {${file.content}};`, { indent_size: 2}); + }); + + // delete the source file + await fs.unlink(`${__dirname}/source.js`, (err) => { + if (err) { + throw new Error(err.message || err); + } + }); + + // make sure container directory exists + const container = `${path}/${dir}`; + if (!fs.existsSync(container)) { + await fs.mkdirSync(container); + } + + // create API directories and files + files.forEach((file) => { + // make sure API directory exists + if (!fs.existsSync(`${container}/${file.file}`)) { + fs.mkdirSync(`${container}/${file.file}`); + } + // create file + fs.writeFileSync(`${container}/${file.file}/${file.file}.controller.js`, + beautify(file.content, { + indent_size: 2 , + end_with_newline: true, + }), + (fErr) => { + if (fErr) { + throw new Error(fErr.message || fErr); + } + }); + }); + + return console.log('> swagger-js-codegen @ SUCCESS!'); + } catch (err) { + throw new Error(err.message || err); + } +} + +module.exports = { + split, +}; diff --git a/lib/typescript.js b/lib/typescript.js index b6c5a844..cf3c7288 100644 --- a/lib/typescript.js +++ b/lib/typescript.js @@ -9,6 +9,7 @@ var _ = require('lodash'); * Not all type are currently supported, but they should be straightforward to add. * * @param swaggerType a swagger type definition, i.e., the right hand side of a swagger type definition. + * @param swagger * @returns a recursive structure representing the type, which can be used as a template model. */ function convertType(swaggerType, swagger) { @@ -62,6 +63,11 @@ function convertType(swaggerType, swagger) { var property = convertType(propertyType); property.name = propertyName; + // add example value if possibles + if (propertyType.example) { + property.example = propertyType.example; + } + property.optional = true; if (swaggerType.required && swaggerType.required.indexOf(propertyName) !== -1) { property.optional = false; @@ -81,6 +87,10 @@ function convertType(swaggerType, swagger) { typespec.isArray = typespec.tsType === 'array'; typespec.isAtomic = typespec.isAtomic || _.includes(['string', 'number', 'boolean', 'any'], typespec.tsType); + if (swaggerType['x-AuthFieldType']) { + typespec['x-AuthFieldType'] = swaggerType['x-AuthFieldType']; + } + return typespec; } diff --git a/package-lock.json b/package-lock.json index 625657b5..f8da60c8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,16 @@ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" }, + "acorn": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.1.1.tgz", + "integrity": "sha512-jPTiwtOxaHNaAPg/dmrJ/beuzLRnXtB0kQPQ8JpotKJgTB6rX6c8mlf315941pyjBSaPg8NHXS9fhP4u17DpGA==" + }, + "acorn-jsx": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.0.1.tgz", + "integrity": "sha512-HJ7CfNHrfJLlNTzIEUTj43LNWGkqpRLxm3YjAlcD0ACydk9XynzYsCBHxut+iqt+1aBXkx9UP/w/ZqMr13XIzg==" + }, "ajv": { "version": "5.5.2", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", @@ -95,6 +105,11 @@ "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=", "dev": true }, + "ast-types": { + "version": "0.11.5", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.11.5.tgz", + "integrity": "sha512-oJjo+5e7/vEc2FBK8gUalV0pba4L3VdBIs2EKhOLHLcOd2FgQIVQN9xb0eZ9IjEWyAL7vq6fGJxOvVvdCHNyMw==" + }, "async": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", @@ -134,11 +149,6 @@ "tweetnacl": "^0.14.3" } }, - "bluebird": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", - "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" - }, "boxen": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/boxen/-/boxen-1.2.2.tgz", @@ -299,9 +309,9 @@ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" }, "config-chain": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.11.tgz", - "integrity": "sha1-q6CXR9++TD5w52am5BWG4YWfxvI=", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", "requires": { "ini": "^1.3.4", "proto-list": "~1.2.1" @@ -382,6 +392,14 @@ "array-find-index": "^1.0.1" } }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "^0.10.9" + } + }, "dashdash": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", @@ -439,30 +457,25 @@ "dev": true }, "dom-serializer": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", - "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.1.tgz", + "integrity": "sha512-l0IU0pPzLWSHBcieZbpOKgkIn3ts3vAh7ZuFyXNwJxJXk/c4Gwj9xaTJwIDVQCXawWD0qb3IzMGH5rglQaO0XA==", "requires": { - "domelementtype": "~1.1.1", - "entities": "~1.1.1" + "domelementtype": "^1.3.0", + "entities": "^1.1.1" }, "dependencies": { - "domelementtype": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", - "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=" - }, "entities": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", - "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.2.tgz", + "integrity": "sha512-f2LZMYl1Fzu7YSBKg+RoROelpOaNrcGmE9AZubeDfrCEia483oW4MI4VyFd5VNHIgQ/7qm1I0wUHK1eJnn2y2w==" } } }, "domelementtype": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", - "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz", + "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==" }, "domhandler": { "version": "2.3.0", @@ -505,15 +518,26 @@ } }, "editorconfig": { - "version": "0.13.3", - "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.13.3.tgz", - "integrity": "sha512-WkjsUNVCu+ITKDj73QDvi0trvpdDWdkDyHybDGSXPfekLCqwmpD7CP7iPbvBgosNuLcI96XTDwNa75JyFl7tEQ==", - "requires": { - "bluebird": "^3.0.5", - "commander": "^2.9.0", - "lru-cache": "^3.2.0", - "semver": "^5.1.0", + "version": "0.15.3", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.3.tgz", + "integrity": "sha512-M9wIMFx96vq0R4F+gRpY3o2exzb8hEj/n9S8unZtHSvYjibBp/iMufSzvmOcV/laG0ZtuTVGtiJggPOSW2r93g==", + "requires": { + "commander": "^2.19.0", + "lru-cache": "^4.1.5", + "semver": "^5.6.0", "sigmund": "^1.0.1" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "semver": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.6.0.tgz", + "integrity": "sha512-RS9R6R35NYgQn++fkDWaOmqGoj4Ek9gGs+DPxNUZKuwE183xjJroKvyo1IzVFeXvUrvmALy6FWD5xrdJT25gMg==" + } } }, "entities": { @@ -530,16 +554,129 @@ "is-arrayish": "^0.2.1" } }, + "es5-ext": { + "version": "0.10.48", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.48.tgz", + "integrity": "sha512-CdRvPlX/24Mj5L4NVxTs4804sxiS2CjVprgCmrgoDkdmjdY4D+ySHa7K3jJf8R40dFg0tIm3z/dk326LrnuSGw==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-map": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-map/-/es6-map-0.1.5.tgz", + "integrity": "sha1-kTbgUD3MBqMBaQ8LsU/042TpSfA=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-set": "~0.1.5", + "es6-symbol": "~3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-set": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/es6-set/-/es6-set-0.1.5.tgz", + "integrity": "sha1-0rPsXU2ADO2BjbU40ol02wpzzLE=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14", + "es6-iterator": "~2.0.1", + "es6-symbol": "3.1.1", + "event-emitter": "~0.3.5" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" }, + "escope": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/escope/-/escope-3.6.0.tgz", + "integrity": "sha1-4Bl16BJ4GhY6ba392AOY3GTIicM=", + "requires": { + "es6-map": "^0.1.3", + "es6-weak-map": "^2.0.1", + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==" + }, + "espree": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.1.0.tgz", + "integrity": "sha512-I5BycZW6FCVIub93TeVY1s7vjhP9CY6cXCznIRfiig7nRviKZYdRnj/sHEWC6A7WE9RDWOFq9+7OsWSYz8qv2w==", + "requires": { + "acorn": "^6.0.2", + "acorn-jsx": "^5.0.0", + "eslint-visitor-keys": "^1.0.0" + } + }, "esprima": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==" }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, "eventemitter2": { "version": "0.4.14", "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-0.4.14.tgz", @@ -610,6 +747,14 @@ "integrity": "sha1-Ys8SAjTGg3hdkCNIqADvPgzCC8A=", "dev": true }, + "f-matches": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/f-matches/-/f-matches-1.1.0.tgz", + "integrity": "sha1-GOmFRQAL84EAe3qfmaae7Q0wQzY=", + "requires": { + "lodash": "^4.17.5" + } + }, "fast-deep-equal": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", @@ -632,6 +777,7 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz", "integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==", + "dev": true, "requires": { "is-number": "^2.1.0", "isobject": "^2.0.0", @@ -921,6 +1067,22 @@ "supports-color": "^2.0.0" } }, + "jshint": { + "version": "2.9.7", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.7.tgz", + "integrity": "sha512-Q8XN38hGsVQhdlM+4gd1Xl7OB1VieSuCJf+fEJjpo59JH99bVJhXRXAh26qQ15wfdd1VPMuDWNeSWoNl53T4YA==", + "dev": true, + "requires": { + "cli": "~1.0.0", + "console-browserify": "1.1.x", + "exit": "0.1.x", + "htmlparser2": "3.8.x", + "lodash": "~4.17.10", + "minimatch": "~3.0.2", + "shelljs": "0.3.x", + "strip-json-comments": "1.0.x" + } + }, "strip-ansi": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", @@ -1199,7 +1361,8 @@ "is-buffer": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true }, "is-builtin-module": { "version": "1.0.0", @@ -1278,6 +1441,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz", "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", + "dev": true, "requires": { "kind-of": "^3.0.2" } @@ -1348,6 +1512,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", + "dev": true, "requires": { "isarray": "1.0.0" }, @@ -1355,7 +1520,8 @@ "isarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true } } }, @@ -1366,14 +1532,39 @@ "dev": true }, "js-beautify": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.7.4.tgz", - "integrity": "sha512-6YX1g+lIl0/JDxjFFbgj7fz6i0bWFa2Hdc7PfGqFhynaEiYe1NJ3R1nda0VGaRiGU82OllR+EGDoWFpGr3k5Kg==", + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.9.0.tgz", + "integrity": "sha512-P0skmY4IDjfLiVrx+GLDeme8w5G0R1IGXgccVU5HP2VM3lRblH7qN2LTea5vZAxrDjpZBD0Jv+ahpjwVcbz/rw==", "requires": { - "config-chain": "~1.1.5", - "editorconfig": "^0.13.2", + "config-chain": "^1.1.12", + "editorconfig": "^0.15.2", + "glob": "^7.1.3", "mkdirp": "~0.5.0", - "nopt": "~3.0.1" + "nopt": "~4.0.1" + }, + "dependencies": { + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + } } }, "js-yaml": { @@ -1393,25 +1584,18 @@ "optional": true }, "jshint": { - "version": "2.9.5", - "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.9.5.tgz", - "integrity": "sha1-HnJSkVzmgbQIJ+4UJIxG006apiw=", + "version": "2.10.1", + "resolved": "https://registry.npmjs.org/jshint/-/jshint-2.10.1.tgz", + "integrity": "sha512-9GpPfKeffYBl7oBDX2lHPG16j0AM7D2bn3aLy9DaWTr6CWa0i/7UGhX8WLZ7V14QQnnr4hXbjauTLYg06F+HYw==", "requires": { "cli": "~1.0.0", "console-browserify": "1.1.x", "exit": "0.1.x", "htmlparser2": "3.8.x", - "lodash": "3.7.x", + "lodash": "~4.17.10", "minimatch": "~3.0.2", "shelljs": "0.3.x", "strip-json-comments": "1.0.x" - }, - "dependencies": { - "lodash": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-3.7.0.tgz", - "integrity": "sha1-Nni9irmVBXwHreg27S7wh9qBHUU=" - } } }, "json-schema": { @@ -1458,6 +1642,7 @@ "version": "3.2.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, "requires": { "is-buffer": "^1.1.5" } @@ -1470,6 +1655,33 @@ "package-json": "^4.0.0" } }, + "lebab": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/lebab/-/lebab-3.0.4.tgz", + "integrity": "sha512-wrh0VBhyPybeS/NaydN09KvPOeK7bAHt0Yyuz96t/kuqzbKNxoawlAxXlJ3vDJZ890jL+njMJitQA69Y6gztJQ==", + "requires": { + "commander": "^2.15.1", + "escope": "^3.6.0", + "espree": "^4.0.0", + "estraverse": "^4.1.1", + "f-matches": "^1.1.0", + "glob": "^7.1.2", + "lodash": "^4.17.11", + "recast": "^0.15.5" + }, + "dependencies": { + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + } + } + }, "load-json-file": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", @@ -1512,11 +1724,12 @@ "integrity": "sha1-TjNms55/VFfjXxMkvfb4jQv8cwY=" }, "lru-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-3.2.0.tgz", - "integrity": "sha1-cXibO39Tmb7IVl3aOKow0qCX7+4=", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", "requires": { - "pseudomap": "^1.0.1" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } }, "make-dir": { @@ -1548,7 +1761,8 @@ "math-random": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.1.tgz", - "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=" + "integrity": "sha1-izqsWIuKZuSXXjzepn97sylgH6w=", + "dev": true }, "meow": { "version": "3.7.0", @@ -1656,6 +1870,11 @@ "resolved": "https://registry.npmjs.org/mustache/-/mustache-2.2.1.tgz", "integrity": "sha1-LEDKIcJ49TFQaCvPkJDkGjM5uHY=" }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, "node-fs": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/node-fs/-/node-fs-0.1.7.tgz", @@ -1701,6 +1920,7 @@ "version": "3.0.6", "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "dev": true, "requires": { "abbrev": "1" } @@ -1769,11 +1989,24 @@ "wrappy": "1" } }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, "os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", - "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", - "dev": true + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } }, "p-finally": { "version": "1.0.0", @@ -1892,6 +2125,11 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "private": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", + "integrity": "sha512-VvivMrbvd2nKkiG38qjULzlc+4Vx4wm/whI9pQD35YrARNnhxeiRktSOhSukRLFNlzg6Br/cJPet5J/u19r/mg==" + }, "process-nextick-args": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-1.0.7.tgz", @@ -1930,6 +2168,7 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.0.0.tgz", "integrity": "sha512-VdxFOIEY3mNO5PtSRkkle/hPJDHvQhK21oa73K4yAc9qmp6N429gAyF1gZMOTMeS0/AYzaV/2Trcef+NaIonSA==", + "dev": true, "requires": { "is-number": "^4.0.0", "kind-of": "^6.0.0", @@ -1939,12 +2178,14 @@ "is-number": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz", - "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==" + "integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==", + "dev": true }, "kind-of": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz", - "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==", + "dev": true } } }, @@ -2003,6 +2244,17 @@ "string_decoder": "~0.10.x" } }, + "recast": { + "version": "0.15.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.15.5.tgz", + "integrity": "sha512-nkAYNqarh73cMWRKFiPQ8I9dOLFvFk6SnG8u/LUlOYfArDOD/EjsVRAs860TlBLrpxqAXHGET/AUAVjdEymL5w==", + "requires": { + "ast-types": "0.11.5", + "esprima": "~4.0.0", + "private": "~0.1.5", + "source-map": "~0.6.1" + } + }, "redent": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-1.0.0.tgz", @@ -2048,12 +2300,14 @@ "repeat-element": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.2.tgz", - "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=" + "integrity": "sha1-7wiaF40Ug7quTZPrmLT55OEdmQo=", + "dev": true }, "repeat-string": { "version": "1.6.1", "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=" + "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", + "dev": true }, "repeating": { "version": "2.0.1", @@ -2092,6 +2346,11 @@ "uuid": "^3.1.0" } }, + "require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==" + }, "resolve": { "version": "1.1.7", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.1.7.tgz", @@ -2159,6 +2418,11 @@ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" + }, "spdx-correct": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", diff --git a/package.json b/package.json index 824b3488..cc496c87 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "swagger-js-codegen", "main": "./lib/codegen.js", - "version": "1.12.0", + "version": "2.0.0", "description": "A Swagger codegen for JavaScript", "scripts": { "test": "grunt", @@ -13,9 +13,12 @@ "bugs": { "url": "https://github.com/wcandillon/swagger-js-codegen/issues" }, + "engines" : { + "node" : "^11.14.0" + }, "repository": { "type": "git", - "url": "git://github.com/wcandillon/swagger-js-codegen.git" + "url": "git://github.com/voicenter/swagger-js-codegen" }, "keywords": [ "swagger", @@ -30,9 +33,10 @@ "homepage": "https://github.com/wcandillon/swagger-js-codegen", "dependencies": { "commander": "^2.9.0", - "js-beautify": "^1.5.1", + "js-beautify": "^1.9.0", "js-yaml": "^3.10.0", - "jshint": "^2.5.1", + "jshint": "^2.10.1", + "lebab": "^3.0.4", "lodash": "^4.17.10", "mustache": "2.2.1", "update-notifier": "^2.1.0" diff --git a/templates/method.mustache b/templates/method.mustache index 5151e26a..6ad3d9df 100644 --- a/templates/method.mustache +++ b/templates/method.mustache @@ -1,96 +1,96 @@ /** - * {{&summary}} - * @method - * @name {{&className}}#{{&methodName}} - * @param {object} parameters - method options and parameters +* {{&summary}} +* @method +* @name {{&className}}#{{&methodName}} +* @param {object} parameters - method options and parameters {{#parameters}} - {{^isSingleton}} * @param {{=<% %>=}}{<%&type%>}<%={{ }}=%> parameters.{{&camelCaseName}} - {{&description}}{{/isSingleton}} + {{^isSingleton}} * @param {{=<% %>=}}{<%&type%>}<%={{ }}=%> parameters.{{&camelCaseName}} - {{&description}}{{/isSingleton}} {{/parameters}} - */ - {{&className}}.prototype.{{&methodName}} = function(parameters){ - if(parameters === undefined) { - parameters = {}; - } - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} deferred = {{#isNode}}Q{{/isNode}}{{^isNode}}$q{{/isNode}}.defer(); - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} domain = this.domain, path = '{{&path}}'; - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} body = {}, queryParameters = {}, headers = {}, form = {}; +*/ +{{&className}}.prototype.{{&methodName}} = function(parameters){ +if(parameters === undefined) { +parameters = {}; +} +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} deferred = {{#isNode}}Q{{/isNode}}{{^isNode}}$q{{/isNode}}.defer(); +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} domain = this.domain, path = '{{&path}}'; +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} body = {}, queryParameters = {}, headers = {}, form = {}; + +{{#isSecure}} + headers = this.setAuthHeaders(headers); +{{/isSecure}} +{{#headers}} + headers['{{&name}}'] = [{{&value}}]; +{{/headers}} - {{#isSecure}} - headers = this.setAuthHeaders(headers); - {{/isSecure}} - {{#headers}} - headers['{{&name}}'] = [{{&value}}]; - {{/headers}} +{{#parameters}} + {{#isQueryParameter}} + {{#isSingleton}} + queryParameters['{{&name}}'] = '{{&singleton}}'; + {{/isSingleton}} + {{^isSingleton}} + {{#isPatternType}} + Object.keys(parameters).forEach(function(parameterName) { + if(new RegExp('{{&pattern}}').test(parameterName)){ + queryParameters[parameterName] = parameters[parameterName]; + } + }); + {{/isPatternType}} + {{#default}} + /** set default value **/ + queryParameters['{{&name}}'] = {{&default}}; + {{/default}} - {{#parameters}} - {{#isQueryParameter}} - {{#isSingleton}} - queryParameters['{{&name}}'] = '{{&singleton}}'; - {{/isSingleton}} - {{^isSingleton}} - {{#isPatternType}} - Object.keys(parameters).forEach(function(parameterName) { - if(new RegExp('{{&pattern}}').test(parameterName)){ - queryParameters[parameterName] = parameters[parameterName]; - } - }); - {{/isPatternType}} - {{#default}} - /** set default value **/ - queryParameters['{{&name}}'] = {{&default}}; - {{/default}} + {{^isPatternType}} + if(parameters['{{&camelCaseName}}'] !== undefined){ + queryParameters['{{&name}}'] = parameters['{{&camelCaseName}}']; + } + {{/isPatternType}} + {{/isSingleton}} + {{/isQueryParameter}} - {{^isPatternType}} - if(parameters['{{&camelCaseName}}'] !== undefined){ - queryParameters['{{&name}}'] = parameters['{{&camelCaseName}}']; - } - {{/isPatternType}} - {{/isSingleton}} - {{/isQueryParameter}} - - {{#isPathParameter}} - path = path.replace('{{=<% %>=}}{<%&name%>}<%={{ }}=%>', parameters['{{&camelCaseName}}']); - {{/isPathParameter}} - - {{#isHeaderParameter}} - {{#isSingleton}} - headers['{{&name}}'] = '{{&singleton}}'; - {{/isSingleton}} - {{^isSingleton}} - if(parameters['{{&camelCaseName}}'] !== undefined){ - headers['{{&name}}'] = parameters['{{&camelCaseName}}']; - } - {{/isSingleton}} - {{/isHeaderParameter}} - - {{#isBodyParameter}} - if(parameters['{{&camelCaseName}}'] !== undefined){ - body = parameters['{{&camelCaseName}}']; - } - {{/isBodyParameter}} + {{#isPathParameter}} + path = path.replace('{{=<% %>=}}{<%&name%>}<%={{ }}=%>', parameters['{{&camelCaseName}}']); + {{/isPathParameter}} - {{#isFormParameter}} - {{#isSingleton}} - form['{{&name}}'] = '{{&singleton}}'; - {{/isSingleton}} - {{^isSingleton}} - if(parameters['{{&camelCaseName}}'] !== undefined){ - form['{{&name}}'] = parameters['{{&camelCaseName}}']; - } - {{/isSingleton}} - {{/isFormParameter}} + {{#isHeaderParameter}} + {{#isSingleton}} + headers['{{&name}}'] = '{{&singleton}}'; + {{/isSingleton}} + {{^isSingleton}} + if(parameters['{{&camelCaseName}}'] !== undefined){ + headers['{{&name}}'] = parameters['{{&camelCaseName}}']; + } + {{/isSingleton}} + {{/isHeaderParameter}} - {{#required}} - if(parameters['{{&camelCaseName}}'] === undefined){ - deferred.reject(new Error('Missing required {{¶mType}} parameter: {{&camelCaseName}}')); - return deferred.promise; - } - {{/required}} - - {{/parameters}} - queryParameters = mergeQueryParams(parameters, queryParameters); + {{#isBodyParameter}} + if(parameters['{{&camelCaseName}}'] !== undefined){ + body = parameters['{{&camelCaseName}}']; + } + {{/isBodyParameter}} - this.request('{{method}}', domain + path, parameters, body, headers, queryParameters, form, deferred); + {{#isFormParameter}} + {{#isSingleton}} + form['{{&name}}'] = '{{&singleton}}'; + {{/isSingleton}} + {{^isSingleton}} + if(parameters['{{&camelCaseName}}'] !== undefined){ + form['{{&name}}'] = parameters['{{&camelCaseName}}']; + } + {{/isSingleton}} + {{/isFormParameter}} + {{#required}} + if(parameters['{{&camelCaseName}}'] === undefined){ + deferred.reject(new Error('Missing required {{¶mType}} parameter: {{&camelCaseName}}')); return deferred.promise; - }; + } + {{/required}} + +{{/parameters}} +queryParameters = mergeQueryParams(parameters, queryParameters); + +this.request('{{method}}', domain + path, parameters, body, headers, queryParameters, form, deferred); + +return deferred.promise; +}; diff --git a/templates/multi-class.mustache b/templates/multi-class.mustache new file mode 100644 index 00000000..acfa8c3d --- /dev/null +++ b/templates/multi-class.mustache @@ -0,0 +1,20 @@ +'use strict'; + +/** +* {{&description}} +* @class {{&className}} +*/ +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} {{&className}} = (function(){ + + function {{&className}}() { + + } + + {{#methods}} + {{> method}} + {{/methods}} + + return {{&className}}; +})(); + +exports.{{&className}} = {{&className}}; diff --git a/templates/multi-method.mustache b/templates/multi-method.mustache new file mode 100644 index 00000000..28275fe5 --- /dev/null +++ b/templates/multi-method.mustache @@ -0,0 +1,72 @@ +/** +* {{&summary}} +* @method {{&methodName}} +* @name {{&className}}#{{&methodName}} +* @param {object} req - request object +* @param {object} res - response object +*/ +{{&className}}.prototype.{{&destination}}_{{&methodName}} = function(req, res) { +try { +console.log('===> Executing generated route: {{&methodName}}'); + +{{#parameters}} + {{#isQueryParameter}} + {{#x-AuthFieldType}} + var auth{{&x-AuthFieldType.propertyName}} = await_FieldValidator.validate('{{&x-AuthFieldType.value}}', req.query['{{&x-AuthFieldType.propertyName}}'], req, res); + if (!auth{{&x-AuthFieldType.propertyName}}) { return; } + {{/x-AuthFieldType}} + var {{name}} = req.query['{{name}}']; + {{/isQueryParameter}} + {{#isPathParameter}} + {{#x-AuthFieldType}} + var auth{{&x-AuthFieldType.propertyName}} = await_FieldValidator.validate('{{&x-AuthFieldType.value}}', req.params['{{&x-AuthFieldType.propertyName}}'], req, res); + if (!auth{{&x-AuthFieldType.propertyName}}) { return; } + {{/x-AuthFieldType}} + var {{name}} = req.params['{{name}}']; + {{/isPathParameter}} + {{#isBodyParameter}} + {{#x-AuthFieldType}} + var auth{{&x-AuthFieldType.propertyName}} = await_FieldValidator.validate('{{&x-AuthFieldType.value}}', req.body['{{&x-AuthFieldType.propertyName}}'], req, res); + if (!auth{{&x-AuthFieldType.propertyName}}) { return; } + {{/x-AuthFieldType}} + //const {{name}} = new global.classes['{{tsType.target}}'](req, res, req.body); + {{/isBodyParameter}} + {{#isHeaderParameter}} + {{#isSingleton}}{{/isSingleton}} + {{^isSingleton}}{{/isSingleton}} + {{/isHeaderParameter}} + {{#isFormParameter}} + {{#isSingleton}}{{/isSingleton}} + {{^isSingleton}}{{/isSingleton}} + {{/isFormParameter}} +{{/parameters}} +{{#query}} + {{#parameters}} + {{#isBodyParameter}} + //await {{tsType.target}}.validate(); + + {{/isBodyParameter}} + {{/parameters}} + //{{&query}} + + //res.code(results.Status).send(results); +{{/query}} + +{{^query}} + /* + Method logic + */ +{{/query}} +{{#responses}} + {{#200}}{{{code}}}{{/200}} +{{/responses}} +} catch (error) { + console.error(`Error in {{&methodName}}: ${error.message}`); + + res.code(500).send({ + Status: 500, + Message: 'Error in {{&methodName}}', + Description: error.message, + }); +} +}; diff --git a/templates/node-class.mustache b/templates/node-class.mustache index 8001cdd1..9fd6a7d2 100644 --- a/templates/node-class.mustache +++ b/templates/node-class.mustache @@ -1,174 +1,174 @@ /*jshint -W069 */ /** - * {{&description}} - * @class {{&className}} - * @param {(string|object)} [domainOrOptions] - The project domain or options object. If object, see the object's optional properties. - * @param {string} [domainOrOptions.domain] - The project domain - * @param {object} [domainOrOptions.token] - auth token - object with value property and optional headerOrQueryName and isQuery properties - */ +* {{&description}} +* @class {{&className}} +* @param {(string|object)} [domainOrOptions] - The project domain or options object. If object, see the object's optional properties. +* @param {string} [domainOrOptions.domain] - The project domain +* @param {object} [domainOrOptions.token] - auth token - object with value property and optional headerOrQueryName and isQuery properties +*/ {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} {{&className}} = (function(){ - 'use strict'; +'use strict'; - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} request = require('request'); - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} Q = require('q'); +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} request = require('request'); +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} Q = require('q'); - function {{&className}}(options){ - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} domain = (typeof options === 'object') ? options.domain : options; - this.domain = domain ? domain : '{{&domain}}'; - if(this.domain.length === 0) { - throw new Error('Domain parameter must be specified as a string.'); - } - {{#isSecure}} - {{#isSecureToken}} - this.token = (typeof options === 'object') ? (options.token ? options.token : {}) : {}; - {{/isSecureToken}} - {{#isSecureApiKey}} - this.apiKey = (typeof options === 'object') ? (options.apiKey ? options.apiKey : {}) : {}; - {{/isSecureApiKey}} - {{#isSecureBasic}} - this.basic = (typeof options === 'object') ? (options.basic ? options.basic : {}) : {}; - {{/isSecureBasic}} - {{/isSecure}} - } +function {{&className}}(options){ +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} domain = (typeof options === 'object') ? options.domain : options; +this.domain = domain ? domain : '{{&domain}}'; +if(this.domain.length === 0) { +throw new Error('Domain parameter must be specified as a string.'); +} +{{#isSecure}} + {{#isSecureToken}} + this.token = (typeof options === 'object') ? (options.token ? options.token : {}) : {}; + {{/isSecureToken}} + {{#isSecureApiKey}} + this.apiKey = (typeof options === 'object') ? (options.apiKey ? options.apiKey : {}) : {}; + {{/isSecureApiKey}} + {{#isSecureBasic}} + this.basic = (typeof options === 'object') ? (options.basic ? options.basic : {}) : {}; + {{/isSecureBasic}} +{{/isSecure}} +} - function mergeQueryParams(parameters, queryParameters) { - if (parameters.$queryParameters) { - Object.keys(parameters.$queryParameters) - .forEach(function(parameterName) { - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} parameter = parameters.$queryParameters[parameterName]; - queryParameters[parameterName] = parameter; - }); - } - return queryParameters; - } +function mergeQueryParams(parameters, queryParameters) { +if (parameters.$queryParameters) { +Object.keys(parameters.$queryParameters) +.forEach(function(parameterName) { +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} parameter = parameters.$queryParameters[parameterName]; +queryParameters[parameterName] = parameter; +}); +} +return queryParameters; +} + +/** +* HTTP Request +* @method +* @name {{&className}}#request +* @param {string} method - http method +* @param {string} url - url to do request +* @param {object} parameters +* @param {object} body - body parameters / object +* @param {object} headers - header parameters +* @param {object} queryParameters - querystring parameters +* @param {object} form - form data object +* @param {object} deferred - promise object +*/ +{{&className}}.prototype.request = function(method, url, parameters, body, headers, queryParameters, form, deferred){ +{{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} req = { +method: method, +uri: url, +qs: queryParameters, +headers: headers, +body: body +}; +if(Object.keys(form).length > 0) { +req.form = form; +} +if(typeof(body) === 'object' && !(body instanceof Buffer)) { +req.json = true; +} +request(req, function(error, response, body){ +if(error) { +deferred.reject(error); +} else { +if(/^application\/(.*\\+)?json/.test(response.headers['content-type'])) { +try { +body = JSON.parse(body); +} catch(e) {} +} +if(response.statusCode === 204) { +deferred.resolve({ response: response }); +} else if(response.statusCode >= 200 && response.statusCode <= 299) { +deferred.resolve({ response: response, body: body }); +} else { +deferred.reject({ response: response, body: body }); +} +} +}); +}; +{{#isSecure}} + {{#isSecureToken}} /** - * HTTP Request - * @method - * @name {{&className}}#request - * @param {string} method - http method - * @param {string} url - url to do request - * @param {object} parameters - * @param {object} body - body parameters / object - * @param {object} headers - header parameters - * @param {object} queryParameters - querystring parameters - * @param {object} form - form data object - * @param {object} deferred - promise object - */ - {{&className}}.prototype.request = function(method, url, parameters, body, headers, queryParameters, form, deferred){ - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} req = { - method: method, - uri: url, - qs: queryParameters, - headers: headers, - body: body - }; - if(Object.keys(form).length > 0) { - req.form = form; - } - if(typeof(body) === 'object' && !(body instanceof Buffer)) { - req.json = true; - } - request(req, function(error, response, body){ - if(error) { - deferred.reject(error); - } else { - if(/^application\/(.*\\+)?json/.test(response.headers['content-type'])) { - try { - body = JSON.parse(body); - } catch(e) {} - } - if(response.statusCode === 204) { - deferred.resolve({ response: response }); - } else if(response.statusCode >= 200 && response.statusCode <= 299) { - deferred.resolve({ response: response, body: body }); - } else { - deferred.reject({ response: response, body: body }); - } - } - }); + * Set Token + * @method + * @name {{&className}}#setToken + * @param {string} value - token's value + * @param {string} headerOrQueryName - the header or query name to send the token at + * @param {boolean} isQuery - true if send the token as query param, otherwise, send as header param + */ + {{&className}}.prototype.setToken = function (value, headerOrQueryName, isQuery) { + this.token.value = value; + this.token.headerOrQueryName = headerOrQueryName; + this.token.isQuery = isQuery; }; + {{/isSecureToken}} + {{#isSecureApiKey}} + /** + * Set Api Key + * @method + * @name {{&className}}#setApiKey + * @param {string} value - apiKey's value + * @param {string} headerOrQueryName - the header or query name to send the apiKey at + * @param {boolean} isQuery - true if send the apiKey as query param, otherwise, send as header param + */ + {{&className}}.prototype.setApiKey = function (value, headerOrQueryName, isQuery) { + this.apiKey.value = value; + this.apiKey.headerOrQueryName = headerOrQueryName; + this.apiKey.isQuery = isQuery; + }; + {{/isSecureApiKey}} + {{#isSecureBasic}} + /** + * Set Basic Auth + * @method + * @name {{&className}}#setBasicAuth + * @param {string} username + * @param {string} password + */ + {{&className}}.prototype.setBasicAuth = function (username, password) { + this.basic.username = username; + this.basic.password = password; + }; + {{/isSecureBasic}} + /** + * Set Auth headers + * @method + * @name {{&className}}#setAuthHeaders + * @param {object} headerParams - headers object + */ + {{&className}}.prototype.setAuthHeaders = function (headerParams) { + {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} headers = headerParams ? headerParams : {}; + {{#isSecureToken}} + if (!this.token.isQuery) { + if (this.token.headerOrQueryName) { + headers[this.token.headerOrQueryName] = this.token.value; + } else if (this.token.value) { + headers['Authorization'] = 'Bearer ' + this.token.value; + } + } + {{/isSecureToken}} + {{#isSecureApiKey}} + if (!this.apiKey.isQuery && this.apiKey.headerOrQueryName) { + headers[this.apiKey.headerOrQueryName] = this.apiKey.value; + } + {{/isSecureApiKey}} + {{#isSecureBasic}} + if (this.basic.username && this.basic.password) { + headers['Authorization'] = 'Basic ' + new Buffer(this.basic.username + ':' + this.basic.password).toString("base64"); + } + {{/isSecureBasic}} + return headers; + }; +{{/isSecure}} - {{#isSecure}} - {{#isSecureToken}} - /** - * Set Token - * @method - * @name {{&className}}#setToken - * @param {string} value - token's value - * @param {string} headerOrQueryName - the header or query name to send the token at - * @param {boolean} isQuery - true if send the token as query param, otherwise, send as header param - */ - {{&className}}.prototype.setToken = function (value, headerOrQueryName, isQuery) { - this.token.value = value; - this.token.headerOrQueryName = headerOrQueryName; - this.token.isQuery = isQuery; - }; - {{/isSecureToken}} - {{#isSecureApiKey}} - /** - * Set Api Key - * @method - * @name {{&className}}#setApiKey - * @param {string} value - apiKey's value - * @param {string} headerOrQueryName - the header or query name to send the apiKey at - * @param {boolean} isQuery - true if send the apiKey as query param, otherwise, send as header param - */ - {{&className}}.prototype.setApiKey = function (value, headerOrQueryName, isQuery) { - this.apiKey.value = value; - this.apiKey.headerOrQueryName = headerOrQueryName; - this.apiKey.isQuery = isQuery; - }; - {{/isSecureApiKey}} - {{#isSecureBasic}} - /** - * Set Basic Auth - * @method - * @name {{&className}}#setBasicAuth - * @param {string} username - * @param {string} password - */ - {{&className}}.prototype.setBasicAuth = function (username, password) { - this.basic.username = username; - this.basic.password = password; - }; - {{/isSecureBasic}} - /** - * Set Auth headers - * @method - * @name {{&className}}#setAuthHeaders - * @param {object} headerParams - headers object - */ - {{&className}}.prototype.setAuthHeaders = function (headerParams) { - {{#isES6}}let{{/isES6}}{{^isES6}}var{{/isES6}} headers = headerParams ? headerParams : {}; - {{#isSecureToken}} - if (!this.token.isQuery) { - if (this.token.headerOrQueryName) { - headers[this.token.headerOrQueryName] = this.token.value; - } else if (this.token.value) { - headers['Authorization'] = 'Bearer ' + this.token.value; - } - } - {{/isSecureToken}} - {{#isSecureApiKey}} - if (!this.apiKey.isQuery && this.apiKey.headerOrQueryName) { - headers[this.apiKey.headerOrQueryName] = this.apiKey.value; - } - {{/isSecureApiKey}} - {{#isSecureBasic}} - if (this.basic.username && this.basic.password) { - headers['Authorization'] = 'Basic ' + new Buffer(this.basic.username + ':' + this.basic.password).toString("base64"); - } - {{/isSecureBasic}} - return headers; - }; - {{/isSecure}} - - {{#methods}} - {{> method}} - {{/methods}} +{{#methods}} + {{> method}} +{{/methods}} - return {{&className}}; +return {{&className}}; })(); exports.{{&className}} = {{&className}};