api-doc-validator
Advanced tools
Comparing version 2.2.0 to 2.3.0
15
cli.js
@@ -31,2 +31,7 @@ #!/usr/bin/env node | ||
.option('-P, --extra-props <boolean>', 'value for ajv "object" additionalProperties, default false') | ||
.option('-N, --class-name <string>', 'name of generated api client class, default "Api"') | ||
.option('--path-to-regexp <boolean>', 'whether to add a path-to-regexp support, default true') | ||
.option('--request-method <boolean>', 'whether to add a Api.request method, default true') | ||
.option('--get-ajv-method <boolean>', 'whether to add a Api.getAjv method, default true') | ||
.option('--error-handler-method <boolean>', 'whether to add a Api.errorHandler method, default true') | ||
; | ||
@@ -64,2 +69,7 @@ | ||
'extraProps', | ||
'className', | ||
'pathToRegexp', | ||
'requestMethod', | ||
'getAjvMethod', | ||
'errorHandlerMethod', | ||
]); | ||
@@ -151,2 +161,7 @@ | ||
jsdocRefs: config.jsdocRefs, | ||
pathToRegexp: config.pathToRegexp, | ||
className: config.className, | ||
requestMethod: config.requestMethod, | ||
getAjvMethod: config.getAjvMethod, | ||
errorHandlerMethod: config.errorHandlerMethod, | ||
}) | ||
@@ -153,0 +168,0 @@ ); |
@@ -18,2 +18,5 @@ const {readFileSync, createWriteStream} = require('fs'); | ||
className = 'Api', | ||
requestMethod = true, | ||
getAjvMethod = true, | ||
errorHandlerMethod = true, | ||
} = {} | ||
@@ -25,11 +28,17 @@ ) { | ||
let mainTpl = getTemplate('api-client.js'); | ||
const methodTpl = getTemplate('api-client-method.js'); | ||
const getTemplate = function (filename) { | ||
let tpl = readFileSync(resolve(__dirname, '..', 'templates', filename + '.js'), 'utf-8'); | ||
if (!pathToRegexp) { | ||
mainTpl = mainTpl.replace(/^const {pathToRegexp,.+$/m, ''); | ||
} | ||
if (className !== 'Api') { | ||
tpl = tpl.replace(/\bApi\b/g, className); | ||
} | ||
if (className !== 'Api') { | ||
mainTpl = mainTpl.replace(/\bApi\b/g, className); | ||
return tpl; | ||
}; | ||
let mainTpl = getTemplate('api-client'); | ||
const methodTpl = getTemplate('api-client-method'); | ||
if (pathToRegexp) { | ||
mainTpl = `const {pathToRegexp, compile: createToPath} = require("path-to-regexp");\n` + mainTpl; | ||
} | ||
@@ -221,2 +230,24 @@ | ||
stream.write(getTemplate('api-classes')); | ||
stream.write( | ||
getTemplate('api-createRequest') | ||
.replace( | ||
'//pathToRegexp\n', | ||
!pathToRegexp ? '' : getTemplate('api-createRequest-pathToRegexp') | ||
) | ||
); | ||
if (requestMethod) { | ||
stream.write(getTemplate('api-request')); | ||
} | ||
if (getAjvMethod) { | ||
stream.write(getTemplate('api-getAjv')); | ||
} | ||
if (errorHandlerMethod) { | ||
stream.write(getTemplate('api-errorHandler')); | ||
} | ||
stream.end(); | ||
@@ -230,5 +261,1 @@ | ||
} | ||
function getTemplate(filename) { | ||
return readFileSync(resolve(__dirname, '..', 'templates', filename), 'utf-8'); | ||
} |
@@ -1,3 +0,1 @@ | ||
const {pathToRegexp, compile: createToPath} = require('path-to-regexp'); | ||
module.exports = Api; | ||
@@ -9,250 +7,3 @@ | ||
Api.getAjv = function () { | ||
let {ajv} = Api; | ||
if (!ajv) { | ||
const Ajv = require('ajv').default; | ||
ajv = Api.ajv = new Ajv({coerceTypes: true}); | ||
try { | ||
var formatsFound = !!require.resolve('ajv-formats'); | ||
} | ||
catch (err) {} | ||
if (formatsFound) { | ||
require('ajv-formats')(ajv); | ||
} | ||
} | ||
return ajv; | ||
}; | ||
/** | ||
* @param {{method: string, url: string, query?: Object, params?: Object, body?: any, endpoint: Object, context: Api, meta: any}} params | ||
* @returns {Promise<{statusCode: number, body?: any}>} | ||
*/ | ||
Api.request = function ajax({method, url, query, body, context}) { | ||
const r = require('request'); | ||
if (!context.requestCookieJar) { | ||
context.requestCookieJar = r.jar(); | ||
} | ||
return new Promise(function (done, fail) { | ||
r({ | ||
method, | ||
url: context.baseUrl + url, | ||
qs: query, | ||
json: true, | ||
jar: context.requestCookieJar, | ||
body, | ||
}, function (err, res) { | ||
if (err) { | ||
fail(err); | ||
} | ||
else { | ||
done(res); | ||
} | ||
}); | ||
}); | ||
}; | ||
Api.errorHandler = function (err) { | ||
throw err; | ||
}; | ||
function createRequest(context, e) { | ||
if (typeof pathToRegexp === 'function') { | ||
e.url.params = []; | ||
e.url.regexp = pathToRegexp( | ||
e.url.path, | ||
e.url.params | ||
); | ||
} | ||
if (typeof createToPath === 'function') { | ||
e.url.toPath = createToPath( | ||
e.url.path | ||
); | ||
} | ||
return async function () { | ||
let args = Array.from(arguments); | ||
const ajv = Api.getAjv(); | ||
const errorHandler = context.errorHandler || Api.errorHandler; | ||
let params = null; | ||
let query = null; | ||
let data = null; | ||
let meta = null; | ||
if (e.url.params && e.url.params.length > 0) { | ||
if (typeof args[0] === 'object') { | ||
params = args.shift(); | ||
} | ||
else { | ||
params = {}; | ||
e.url.params.forEach(function ({name}, i) { | ||
params[name] = args[i]; | ||
}); | ||
args = args.slice(e.url.params.length); | ||
} | ||
} | ||
if (e.query) { | ||
query = args.shift(); | ||
} | ||
if (e.body) { | ||
data = args.shift(); | ||
} | ||
if (args.length > 0) { | ||
meta = args[0]; | ||
} | ||
if (e.params) { | ||
let {schema, validate} = e.params; | ||
if (!validate) { | ||
validate = e.params.validate = ajv.compile(schema); | ||
} | ||
if (!validate(params)) { | ||
errorHandler(new RequestValidationError( | ||
`Invalid URL params`, | ||
e, | ||
'params', | ||
params, | ||
validate.errors | ||
)); | ||
} | ||
} | ||
if (e.query) { | ||
let {schema, validate} = e.query; | ||
if (!validate) { | ||
validate = e.query.validate = ajv.compile(schema); | ||
} | ||
if (!validate(query)) { | ||
errorHandler(new RequestValidationError( | ||
`Invalid URL query`, | ||
e, | ||
'query', | ||
query, | ||
validate.errors | ||
)); | ||
} | ||
} | ||
if (e.body) { | ||
let {schema, validate} = e.body; | ||
if (!validate) { | ||
validate = e.body.validate = ajv.compile(schema); | ||
} | ||
if (!validate(data)) { | ||
errorHandler(new RequestValidationError( | ||
`Invalid request body`, | ||
e, | ||
'body', | ||
data, | ||
validate.errors | ||
)); | ||
} | ||
} | ||
const url = (e.baseUrl || '') + (e.url.toPath ? e.url.toPath(params) : e.url.path); | ||
const res = await Api.request({ | ||
method: e.url.method, | ||
url, | ||
params, | ||
query, | ||
body: data, | ||
endpoint: e, | ||
context, | ||
meta, | ||
}); | ||
const {statusCode, body} = res; | ||
if (e.response) { | ||
for (let i = 0, len = e.response.length; i < len; i++) { | ||
let response = e.response[i]; | ||
let {code, schema, validate, validateCode} = response; | ||
if (code && statusCode && !validateCode) { | ||
validateCode = response.validateCode = ajv.compile(code); | ||
} | ||
if (validateCode && !validateCode(statusCode)) { | ||
continue; | ||
} | ||
if (!validate) { | ||
validate = response.validate = ajv.compile(schema); | ||
} | ||
if (!validate(body)) { | ||
errorHandler(new ResponseValidationError( | ||
`Invalid response body`, | ||
e, | ||
response, | ||
body, | ||
validate.errors | ||
)); | ||
} | ||
} | ||
} | ||
if (statusCode >= 300) { | ||
throw res; | ||
} | ||
return body; | ||
}; | ||
} | ||
class ValidationError extends Error { | ||
constructor(message, endpoint, validator, data, errors) { | ||
super(message); | ||
this.name = "ValidationError"; | ||
this.endpoint = endpoint; | ||
this.validator = validator; | ||
this.data = data; | ||
this.errors = errors; | ||
} | ||
} | ||
class RequestValidationError extends ValidationError { | ||
constructor(message, endpoint, type, data, errors) { | ||
super(message, endpoint, endpoint[type], data, errors); | ||
this.name = "RequestValidationError"; | ||
this.type = type; | ||
} | ||
} | ||
class ResponseValidationError extends ValidationError { | ||
constructor(message, endpoint, validator, data, errors) { | ||
super(message, endpoint, validator, data, errors); | ||
this.name = "ResponseValidationError"; | ||
} | ||
} | ||
Api.ValidationError = ValidationError; | ||
Api.RequestValidationError = RequestValidationError; | ||
Api.ResponseValidationError = ResponseValidationError; | ||
/** | ||
* @name Api | ||
@@ -259,0 +10,0 @@ * @param {string} [baseUrl] |
{ | ||
"name": "api-doc-validator", | ||
"version": "2.2.0", | ||
"version": "2.3.0", | ||
"description": "api doc and validator", | ||
@@ -30,7 +30,7 @@ "main": "index.js", | ||
"dependencies": { | ||
"@babel/parser": "^7.17.8", | ||
"@babel/types": "^7.17.0", | ||
"@babel/parser": "^7.18.9", | ||
"@babel/types": "^7.18.9", | ||
"adv-parser": "^2.0.4", | ||
"commander": "^5.1.0", | ||
"glob": "^7.2.0", | ||
"glob": "^7.2.3", | ||
"mkdirp": "^1.0.4" | ||
@@ -43,5 +43,5 @@ }, | ||
"chai-shallow-deep-equal": "^1.4.6", | ||
"express": "^4.17.3", | ||
"mocha": "^9.2.2", | ||
"path-to-regexp": "^6.2.0" | ||
"express": "^4.18.1", | ||
"mocha": "^10.0.0", | ||
"path-to-regexp": "^6.2.1" | ||
}, | ||
@@ -48,0 +48,0 @@ "peerDependencies": { |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
54751
40
1526
Updated@babel/parser@^7.18.9
Updated@babel/types@^7.18.9
Updatedglob@^7.2.3