Comparing version 2.2.3 to 2.3.0
/// <reference types="node" /> | ||
import http from 'http'; | ||
import { MimeTypeParser, StringParser, HttpIncomingMessage, Callback } from "../types"; | ||
import { MimeTypeParser, StringParser, HttpIncomingMessage, Callback } from '../types'; | ||
export default class BodyParserWrapper implements MimeTypeParser { | ||
@@ -5,0 +5,0 @@ private _parser; |
@@ -13,3 +13,3 @@ "use strict"; | ||
limit: maxBodySize, | ||
type: "*/*" | ||
type: '*/*', | ||
}); | ||
@@ -16,0 +16,0 @@ } |
/// <reference types="node" /> | ||
import http from 'http'; | ||
import { MimeTypeParser, Callback } from "../types"; | ||
import { MimeTypeParser, Callback } from '../types'; | ||
export default class TextBodyParser implements MimeTypeParser { | ||
@@ -5,0 +5,0 @@ private _bodyParserMiddlware; |
@@ -13,3 +13,3 @@ "use strict"; | ||
limit: maxBodySize, | ||
type: "*/*" | ||
type: '*/*', | ||
}); | ||
@@ -16,0 +16,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { Controller, ControllerModule, ExegesisContext } from "../types"; | ||
export declare function invokeController(controllerModule: ControllerModule, controller: Controller, context: ExegesisContext): Promise<any>; | ||
import { Controller, ControllerModule, ExegesisContext } from '../types'; | ||
export declare function invokeController(controllerModule: ControllerModule | undefined, controller: Controller, context: ExegesisContext): Promise<any>; |
@@ -9,4 +9,3 @@ "use strict"; | ||
function invokeController(controllerModule, controller, context) { | ||
return promise_breaker_1.default.apply(controller, controllerModule, [context]) | ||
.then(result => { | ||
return promise_breaker_1.default.apply(controller, controllerModule, [context]).then(result => { | ||
if (!context.res.ended) { | ||
@@ -16,3 +15,5 @@ if (result === undefined || result === null) { | ||
} | ||
else if ((typeof result === 'string') || (result instanceof Buffer) || typeUtils_1.isReadable(result)) { | ||
else if (typeof result === 'string' || | ||
result instanceof Buffer || | ||
typeUtils_1.isReadable(result)) { | ||
context.res.setBody(result); | ||
@@ -19,0 +20,0 @@ } |
@@ -23,3 +23,3 @@ "use strict"; | ||
*/ | ||
function loadControllersSync(folder, pattern = "**/*.js", loader = require) { | ||
function loadControllersSync(folder, pattern = '**/*.js', loader = require) { | ||
const controllerNames = glob_1.default.sync(pattern, { cwd: folder }); | ||
@@ -26,0 +26,0 @@ return controllerNames.reduce((result, controllerName) => { |
@@ -16,3 +16,3 @@ "use strict"; | ||
if (this.ended) { | ||
throw new Error("Trying to set status after response has been ended."); | ||
throw new Error('Trying to set status after response has been ended.'); | ||
} | ||
@@ -37,4 +37,3 @@ this.statusCode = status; | ||
// validation. | ||
this.set('content-type', 'application/json') | ||
.setBody(JSON.stringify(json)); | ||
this.set('content-type', 'application/json').setBody(JSON.stringify(json)); | ||
return this; | ||
@@ -44,3 +43,3 @@ } | ||
if (this.ended && !this._afterController) { | ||
throw new Error("Trying to set body after response has been ended."); | ||
throw new Error('Trying to set body after response has been ended.'); | ||
} | ||
@@ -63,3 +62,3 @@ this.body = body; | ||
if (this.ended && !this._afterController) { | ||
throw new Error("Trying to set header after response has been ended."); | ||
throw new Error('Trying to set header after response has been ended.'); | ||
} | ||
@@ -82,3 +81,3 @@ this.headers[name.toLowerCase()] = value; | ||
if (this.ended && !this._afterController) { | ||
throw new Error("Trying to remove header after response has been ended."); | ||
throw new Error('Trying to remove header after response has been ended.'); | ||
} | ||
@@ -88,3 +87,3 @@ delete this.headers[name]; | ||
writeHead(statusCode, statusMessage, headers) { | ||
if (statusMessage && typeof (statusMessage) !== 'string') { | ||
if (statusMessage && typeof statusMessage !== 'string') { | ||
headers = statusMessage; | ||
@@ -91,0 +90,0 @@ statusMessage = undefined; |
import { ApiInterface, ExegesisRunner, ResponseValidationCallback, ExegesisOptions } from '../types'; | ||
import PluginsManager from './PluginsManager'; | ||
import { HandleErrorFunction } from "../types/options"; | ||
import { HandleErrorFunction } from '../types/options'; | ||
/** | ||
@@ -14,5 +14,5 @@ * Returns a `(req, res) => Promise<boolean>` function, which handles incoming | ||
plugins: PluginsManager; | ||
onResponseValidationError: ResponseValidationCallback; | ||
onResponseValidationError?: ResponseValidationCallback; | ||
validateDefaultResponses: boolean; | ||
originalOptions: ExegesisOptions; | ||
}): Promise<ExegesisRunner>; |
@@ -77,3 +77,3 @@ "use strict"; | ||
headers, | ||
body: output | ||
body: output, | ||
}; | ||
@@ -86,3 +86,3 @@ } | ||
const jsonError = { | ||
message: "Validation errors", | ||
message: 'Validation errors', | ||
errors: err.errors.map((error) => { | ||
@@ -93,8 +93,8 @@ return { | ||
}; | ||
}) | ||
}), | ||
}; | ||
return { | ||
status: err.status, | ||
headers: { "content-type": "application/json" }, | ||
body: stringToStream_1.default(JSON.stringify(jsonError), 'utf-8') | ||
headers: { 'content-type': 'application/json' }, | ||
body: stringToStream_1.default(JSON.stringify(jsonError), 'utf-8'), | ||
}; | ||
@@ -105,4 +105,4 @@ } | ||
status: err.status, | ||
headers: { "content-type": "application/json" }, | ||
body: stringToStream_1.default(JSON.stringify({ message: err.message }), 'utf-8') | ||
headers: { 'content-type': 'application/json' }, | ||
body: stringToStream_1.default(JSON.stringify({ message: err.message }), 'utf-8'), | ||
}; | ||
@@ -130,2 +130,3 @@ } | ||
try { | ||
yield plugins.preRouting({ req, res }); | ||
const resolved = api.resolve(method, url, req.headers); | ||
@@ -142,3 +143,3 @@ if (!resolved) { | ||
context._setOperation(resolved.baseUrl, resolved.path, operation); | ||
if (!operation.controllerModule || !operation.controller) { | ||
if (!operation.controller) { | ||
throw new Error(`No controller found for ${method} ${url}`); | ||
@@ -171,7 +172,8 @@ } | ||
try { | ||
if (responseValidationResult.errors && responseValidationResult.errors.length) { | ||
if (responseValidationResult.errors && | ||
responseValidationResult.errors.length) { | ||
options.onResponseValidationError({ | ||
errors: responseValidationResult.errors, | ||
isDefault: responseValidationResult.isDefault, | ||
context | ||
context, | ||
}); | ||
@@ -185,2 +187,3 @@ } | ||
} | ||
yield plugins.postResponseValidation(context); | ||
} | ||
@@ -187,0 +190,0 @@ if (!context.origRes.headersSent) { |
@@ -1,2 +0,4 @@ | ||
import * as exegesis from "../types"; | ||
/// <reference types="node" /> | ||
import * as exegesis from '../types'; | ||
import http from 'http'; | ||
export default class PluginsManager { | ||
@@ -12,5 +14,10 @@ private readonly _plugins; | ||
}): Promise<void>; | ||
preRouting(data: { | ||
req: http.IncomingMessage; | ||
res: http.ServerResponse; | ||
}): Promise<void>; | ||
postRouting(pluginContext: exegesis.ExegesisPluginContext): Promise<void>; | ||
postSecurity(pluginContext: exegesis.ExegesisPluginContext): Promise<void>; | ||
postController(context: exegesis.ExegesisContext): Promise<void>; | ||
postResponseValidation(context: exegesis.ExegesisContext): Promise<void>; | ||
} |
@@ -41,2 +41,9 @@ "use strict"; | ||
} | ||
preRouting(data) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
for (const plugin of this._postRoutingPlugins) { | ||
yield callFn(plugin, 'preRouting', data); | ||
} | ||
}); | ||
} | ||
postRouting(pluginContext) { | ||
@@ -63,4 +70,11 @@ return __awaiter(this, void 0, void 0, function* () { | ||
} | ||
postResponseValidation(context) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
for (const plugin of this._postControllerPlugins) { | ||
yield callFn(plugin, 'postResponseValidation', context); | ||
} | ||
}); | ||
} | ||
} | ||
exports.default = PluginsManager; | ||
//# sourceMappingURL=PluginsManager.js.map |
@@ -11,3 +11,3 @@ "use strict"; | ||
else { | ||
this.stack = (new Error(message)).stack; | ||
this.stack = new Error(message).stack; | ||
} | ||
@@ -14,0 +14,0 @@ } |
@@ -66,3 +66,3 @@ "use strict"; | ||
validateDefaultResponses: compiledOptions.validateDefaultResponses, | ||
originalOptions: options | ||
originalOptions: options, | ||
}); | ||
@@ -69,0 +69,0 @@ })); |
@@ -33,3 +33,3 @@ "use strict"; | ||
else { | ||
throw new Error("Invalid parameters to Oas3CompileContext constructor"); | ||
throw new Error('Invalid parameters to Oas3CompileContext constructor'); | ||
} | ||
@@ -36,0 +36,0 @@ this.jsonPointer = jsonPtr.encodePointer(this.path); |
@@ -77,3 +77,5 @@ "use strict"; | ||
} | ||
else if (operation && operation.bodyRequired && operation.validRequestContentTypes) { | ||
else if (operation && | ||
operation.bodyRequired && | ||
operation.validRequestContentTypes) { | ||
throw new errors_1.HttpBadRequestError(`Missing content-type. ` + | ||
@@ -89,3 +91,3 @@ `Expected one of: ${operation.validRequestContentTypes}`); | ||
serverParams, | ||
queryString: parsedUrl.query || undefined | ||
queryString: parsedUrl.query || undefined, | ||
}); | ||
@@ -101,4 +103,3 @@ }; | ||
operation.operationId; | ||
const controllerModule = exegesisControllerName && | ||
this._options.controllers[exegesisControllerName]; | ||
const controllerModule = exegesisControllerName && this._options.controllers[exegesisControllerName]; | ||
const controller = operationId && controllerModule && controllerModule[operationId]; | ||
@@ -119,3 +120,3 @@ const authenticate = (context) => { | ||
controller, | ||
authenticate | ||
authenticate, | ||
}; | ||
@@ -122,0 +123,0 @@ } |
@@ -78,3 +78,3 @@ "use strict"; | ||
this.operationId = oaOperation[extensions_1.EXEGESIS_OPERATION_ID] || oaOperation.operationId; | ||
this.securityRequirements = (oaOperation.security || context.openApiDoc.security || []); | ||
this.securityRequirements = oaOperation.security || context.openApiDoc.security || []; | ||
this._securitySchemes = new SecuritySchemes_1.default(context.openApiDoc); | ||
@@ -104,4 +104,3 @@ this._responses = new Responses_1.default(context.childContext('responses'), oaOperation.responses); | ||
} | ||
const localParameters = (this.oaOperation.parameters || []) | ||
.map((parameter, index) => new Parameter_1.default(context.childContext(['parameters', '' + index]), parameter)); | ||
const localParameters = (this.oaOperation.parameters || []).map((parameter, index) => new Parameter_1.default(context.childContext(['parameters', '' + index]), parameter)); | ||
const allParameters = parentParameters.concat(localParameters); | ||
@@ -142,3 +141,3 @@ this._parameters = allParameters.reduce((result, parameter) => { | ||
path: rawPathParams ? parameterParsers_1.parseParameterGroup(this._parameters.path, rawPathParams) : {}, | ||
cookie: {} | ||
cookie: {}, | ||
}; | ||
@@ -181,5 +180,6 @@ } | ||
const info = this._securitySchemes.getInfo(schemeName); | ||
const result = (yield promise_breaker_1.default.call(authenticator, null, exegesisContext, info)) || | ||
{ type: 'missing', status: 401 }; | ||
if (result.type !== 'success' && result.type !== 'invalid' && result.type !== 'missing') { | ||
const result = (yield promise_breaker_1.default.call(authenticator, null, exegesisContext, info)) || { type: 'missing', status: 401 }; | ||
if (result.type !== 'success' && | ||
result.type !== 'invalid' && | ||
result.type !== 'missing') { | ||
throw new Error(`Invalid result ${result.type} from authenticator for ${schemeName}`); | ||
@@ -204,3 +204,3 @@ } | ||
message: `Authenticated using '${schemeName}' but missing ` + | ||
`required scopes: ${missingScopes.join(', ')}.` | ||
`required scopes: ${missingScopes.join(', ')}.`, | ||
}; | ||
@@ -278,3 +278,4 @@ } | ||
else if (securityRequirementResult.type === 'authenticated') { | ||
firstAuthenticatedResult = firstAuthenticatedResult || securityRequirementResult.result; | ||
firstAuthenticatedResult = | ||
firstAuthenticatedResult || securityRequirementResult.result; | ||
} | ||
@@ -295,3 +296,3 @@ else if (securityRequirementResult.type === 'missing' || | ||
/* istanbul ignore this */ | ||
throw new Error("Invalid result from `_checkSecurityRequirement()`"); | ||
throw new Error('Invalid result from `_checkSecurityRequirement()`'); | ||
} | ||
@@ -312,4 +313,3 @@ if (exegesisContext.isResponseFinished()) { | ||
else { | ||
const authSchemes = this.securityRequirements | ||
.map(requirement => { | ||
const authSchemes = this.securityRequirements.map(requirement => { | ||
const schemes = Object.keys(requirement); | ||
@@ -316,0 +316,0 @@ return schemes.length === 1 ? schemes[0] : `(${schemes.join(' + ')})`; |
@@ -19,3 +19,3 @@ "use strict"; | ||
cookie: 'form', | ||
header: 'simple' | ||
header: 'simple', | ||
}; | ||
@@ -27,3 +27,3 @@ function getDefaultExplode(style) { | ||
const style = self.oaParameter.style || DEFAULT_STYLE[self.oaParameter.in]; | ||
const explode = (self.oaParameter.explode === null || self.oaParameter.explode === undefined) | ||
const explode = self.oaParameter.explode === null || self.oaParameter.explode === undefined | ||
? getDefaultExplode(style) | ||
@@ -37,3 +37,3 @@ : self.oaParameter.explode; | ||
allowReserved, | ||
schema | ||
schema, | ||
}); | ||
@@ -50,3 +50,3 @@ } | ||
docPath: context.jsonPointer, | ||
path: '' | ||
path: '', | ||
}; | ||
@@ -56,7 +56,9 @@ this.name = resOaParameter.name; | ||
this.oaParameter = resOaParameter; | ||
this.validate = (value) => ({ errors: null, value }); | ||
this.validate = value => ({ errors: null, value }); | ||
// Find the schema for this parameter. | ||
if (resOaParameter.schema) { | ||
const schemaContext = context.childContext('schema'); | ||
const schema = jsonSchema_1.extractSchema(context.openApiDoc, schemaContext.jsonPointer, { resolveRef: context.resolveRef.bind(context) }); | ||
const schema = jsonSchema_1.extractSchema(context.openApiDoc, schemaContext.jsonPointer, { | ||
resolveRef: context.resolveRef.bind(context), | ||
}); | ||
this.parser = generateSchemaParser(this, schema); | ||
@@ -86,3 +88,3 @@ this.validate = validators_1.generateRequestValidator(schemaContext, this.location, resOaParameter.required || false, 'application/x-www-form-urlencoded'); | ||
parser, | ||
uriEncoded: ['query', 'path'].includes(resOaParameter.in) | ||
uriEncoded: ['query', 'path'].includes(resOaParameter.in), | ||
}); | ||
@@ -89,0 +91,0 @@ if (oaMediaType.schema) { |
@@ -39,5 +39,8 @@ "use strict"; | ||
function allowedTypesToMap(allowedTypes) { | ||
return allowedTypes.reduce((m, t) => { m[t] = true; return m; }, {}); | ||
return allowedTypes.reduce((m, t) => { | ||
m[t] = true; | ||
return m; | ||
}, {}); | ||
} | ||
exports.allowedTypesToMap = allowedTypesToMap; | ||
//# sourceMappingURL=common.js.map |
@@ -55,3 +55,3 @@ "use strict"; | ||
`type ${parameterDescriptor.contentType}: ${err.message}`, | ||
location | ||
location, | ||
}); | ||
@@ -136,3 +136,5 @@ } | ||
function parseQueryParameters(params, query) { | ||
const rawValues = querystring_1.default.parse(query || '', '&', '=', { decodeURIComponent: (val) => val }); | ||
const rawValues = querystring_1.default.parse(query || '', '&', '=', { | ||
decodeURIComponent: (val) => val, | ||
}); | ||
return _parseParameterGroup(params, rawValues, query || ''); | ||
@@ -139,0 +141,0 @@ } |
@@ -1,2 +0,2 @@ | ||
import { ParameterParser } from "./types"; | ||
import { ParameterParser } from './types'; | ||
export declare function generatePathStyleParser(schema: any, explode: boolean): ParameterParser; |
@@ -12,3 +12,5 @@ "use strict"; | ||
} | ||
const queryParsedValue = querystring_1.default.parse(value, ';', '=', { decodeURIComponent: (val) => val }); | ||
const queryParsedValue = querystring_1.default.parse(value, ';', '=', { | ||
decodeURIComponent: (val) => val, | ||
}); | ||
return structuredParser(location, queryParsedValue, value, {}); | ||
@@ -15,0 +17,0 @@ } |
@@ -28,5 +28,3 @@ "use strict"; | ||
function simpleStringParser(value) { | ||
return !value | ||
? value | ||
: decodeURIComponent(value); | ||
return !value ? value : decodeURIComponent(value); | ||
} | ||
@@ -36,5 +34,3 @@ exports.simpleStringParser = simpleStringParser; | ||
function simpleArrayParser(value) { | ||
return (value === undefined || value === null) | ||
? value | ||
: value.split(',').map(decodeURIComponent); | ||
return value === undefined || value === null ? value : value.split(',').map(decodeURIComponent); | ||
} | ||
@@ -41,0 +37,0 @@ exports.simpleArrayParser = simpleArrayParser; |
@@ -1,2 +0,2 @@ | ||
import { ParametersMap, ParameterLocation, StringParser } from "../../types"; | ||
import { ParametersMap, ParameterLocation, StringParser } from '../../types'; | ||
/** | ||
@@ -3,0 +3,0 @@ * A descriptor for a parameter that has a "style". |
@@ -20,7 +20,5 @@ "use strict"; | ||
} | ||
const parameters = (oaPath.parameters || []) | ||
.map((p, i) => new Parameter_1.default(context.childContext(['parameters', '' + i]), p)); | ||
const parameters = (oaPath.parameters || []).map((p, i) => new Parameter_1.default(context.childContext(['parameters', '' + i]), p)); | ||
exegesisController = oaPath[extensions_1.EXEGESIS_CONTROLLER] || exegesisController; | ||
this._operations = HTTP_METHODS | ||
.map(method => method.toLowerCase()) | ||
this._operations = HTTP_METHODS.map(method => method.toLowerCase()) | ||
.filter(method => oaPath[method]) | ||
@@ -27,0 +25,0 @@ .reduce((result, method) => { |
@@ -57,3 +57,3 @@ "use strict"; | ||
return result; | ||
}, {}) | ||
}, {}), | ||
}; | ||
@@ -115,3 +115,3 @@ } | ||
rawPathParams, | ||
path | ||
path, | ||
}; | ||
@@ -118,0 +118,0 @@ } |
@@ -37,3 +37,3 @@ "use strict"; | ||
}); | ||
} | ||
}, | ||
}; | ||
@@ -55,3 +55,3 @@ } | ||
const schema = oaMediaType.schema && context.resolveRef(oaMediaType.schema); | ||
if (schema && ('default' in schema)) { | ||
if (schema && 'default' in schema) { | ||
this.parser = generateAddDefaultParser(parser, schema.default); | ||
@@ -58,0 +58,0 @@ } |
@@ -14,3 +14,3 @@ "use strict"; | ||
name: 'body', | ||
docPath: this.context.jsonPointer | ||
docPath: this.context.jsonPointer, | ||
}; | ||
@@ -38,12 +38,16 @@ if (response.content) { | ||
if (body) { | ||
return [{ | ||
return [ | ||
{ | ||
location: this._location, | ||
message: `Response for ${statusCode} is missing content-type.` | ||
}]; | ||
message: `Response for ${statusCode} is missing content-type.`, | ||
}, | ||
]; | ||
} | ||
else if (this._hasResponses) { | ||
return [{ | ||
return [ | ||
{ | ||
location: this._location, | ||
message: `Response for ${statusCode} expects body.` | ||
}]; | ||
message: `Response for ${statusCode} expects body.`, | ||
}, | ||
]; | ||
} | ||
@@ -55,6 +59,8 @@ else { | ||
else if (typeof contentType !== 'string') { | ||
return [{ | ||
return [ | ||
{ | ||
location: this._location, | ||
message: `Invalid content type for ${statusCode} response: ${contentType}` | ||
}]; | ||
message: `Invalid content type for ${statusCode} response: ${contentType}`, | ||
}, | ||
]; | ||
} | ||
@@ -64,12 +70,16 @@ else { | ||
if (body === null || body === undefined) { | ||
return [{ | ||
return [ | ||
{ | ||
location: this._location, | ||
message: `Missing response body for ${statusCode}.` | ||
}]; | ||
message: `Missing response body for ${statusCode}.`, | ||
}, | ||
]; | ||
} | ||
else if (!validator) { | ||
return [{ | ||
return [ | ||
{ | ||
location: this._location, | ||
message: `Unexpected content-type for ${statusCode} response: ${contentType}.` | ||
}]; | ||
message: `Unexpected content-type for ${statusCode} response: ${contentType}.`, | ||
}, | ||
]; | ||
} | ||
@@ -84,6 +94,8 @@ else if (typeof body === 'string' && contentType.startsWith('application/json')) { | ||
catch (err) { | ||
return [{ | ||
return [ | ||
{ | ||
location: this._location, | ||
message: `Could not parse content as JSON.` | ||
}]; | ||
message: `Could not parse content as JSON.`, | ||
}, | ||
]; | ||
} | ||
@@ -90,0 +102,0 @@ } |
@@ -13,3 +13,3 @@ "use strict"; | ||
name: 'body', | ||
docPath: this.context.jsonPointer | ||
docPath: this.context.jsonPointer, | ||
}; | ||
@@ -26,7 +26,9 @@ this._responses = {}; | ||
return { | ||
errors: [{ | ||
errors: [ | ||
{ | ||
location: this._location, | ||
message: `No response defined for status code ${statusCode}.` | ||
}], | ||
isDefault: false | ||
message: `No response defined for status code ${statusCode}.`, | ||
}, | ||
], | ||
isDefault: false, | ||
}; | ||
@@ -40,3 +42,6 @@ } | ||
else { | ||
return { errors: responseObject.validateResponse(statusCode, headers, body), isDefault }; | ||
return { | ||
errors: responseObject.validateResponse(statusCode, headers, body), | ||
isDefault, | ||
}; | ||
} | ||
@@ -43,0 +48,0 @@ } |
@@ -23,4 +23,4 @@ "use strict"; | ||
const REQUEST_TYPE_COERCION_ALLOWED = new mime_1.MimeTypeRegistry({ | ||
"application/x-www-form-urlencoded": true, | ||
"multipart/form-data": true, | ||
'application/x-www-form-urlencoded': true, | ||
'multipart/form-data': true, | ||
}); | ||
@@ -34,3 +34,3 @@ // TODO tests | ||
function assertNever(x) { | ||
throw new Error("Unexpected object: " + x); | ||
throw new Error('Unexpected object: ' + x); | ||
} | ||
@@ -57,4 +57,3 @@ function getParameterDescription(parameterLocation) { | ||
function addCustomFormats(ajv, customFormats) { | ||
return Object.keys(customFormats) | ||
.reduce((result, key) => { | ||
return Object.keys(customFormats).reduce((result, key) => { | ||
const customFormat = customFormats[key]; | ||
@@ -97,3 +96,5 @@ if (typeof customFormat === 'function' || customFormat instanceof RegExp) { | ||
if (resolvedProp.nullable) { | ||
childSchema.additionalProperties = { anyOf: [{ type: 'null' }, childSchema.additionalProperties] }; | ||
childSchema.additionalProperties = { | ||
anyOf: [{ type: 'null' }, childSchema.additionalProperties], | ||
}; | ||
} | ||
@@ -130,3 +131,4 @@ } | ||
if (parameterRequired) { | ||
errors = [{ | ||
errors = [ | ||
{ | ||
message: `Missing required ${getParameterDescription(parameterLocation)}`, | ||
@@ -139,5 +141,6 @@ location: { | ||
docPath: parameterLocation.docPath, | ||
path: '' | ||
} | ||
}]; | ||
path: '', | ||
}, | ||
}, | ||
]; | ||
} | ||
@@ -150,3 +153,3 @@ } | ||
let pathPtr = err.dataPath || ''; | ||
if (pathPtr.startsWith("/value")) { | ||
if (pathPtr.startsWith('/value')) { | ||
pathPtr = pathPtr.slice(6); | ||
@@ -160,5 +163,5 @@ } | ||
docPath: schemaPtr, | ||
path: pathPtr | ||
path: pathPtr, | ||
}, | ||
ajvError: err | ||
ajvError: err, | ||
}; | ||
@@ -187,4 +190,4 @@ }); | ||
properties: { | ||
value: schema | ||
} | ||
value: schema, | ||
}, | ||
}; | ||
@@ -206,3 +209,5 @@ const ajv = new ajv_1.default({ | ||
function generateRequestValidator(schemaContext, parameterLocation, parameterRequired, mediaType) { | ||
const allowTypeCoercion = mediaType ? REQUEST_TYPE_COERCION_ALLOWED.get(mediaType) || false : false; | ||
const allowTypeCoercion = mediaType | ||
? REQUEST_TYPE_COERCION_ALLOWED.get(mediaType) || false | ||
: false; | ||
return generateValidator(schemaContext, parameterLocation, parameterRequired, 'readOnly', allowTypeCoercion); | ||
@@ -209,0 +214,0 @@ } |
@@ -64,3 +64,3 @@ "use strict"; | ||
uriEncoded: true, | ||
schema: parameterSchema | ||
schema: parameterSchema, | ||
}; | ||
@@ -73,3 +73,3 @@ } | ||
allowReserved: encoding.allowReserved || false, | ||
schema: parameterSchema | ||
schema: parameterSchema, | ||
}; | ||
@@ -81,5 +81,5 @@ } | ||
name: parameterName, | ||
docPath: context.childContext(['encoding', parameterName]).jsonPointer | ||
docPath: context.childContext(['encoding', parameterName]).jsonPointer, | ||
}, | ||
parser: parameterParsers_1.generateParser(parameterDescriptor) | ||
parser: parameterParsers_1.generateParser(parameterDescriptor), | ||
}); | ||
@@ -93,3 +93,3 @@ } | ||
return Object.assign(rawResult, parsedResult); | ||
} | ||
}, | ||
}; | ||
@@ -96,0 +96,0 @@ } |
@@ -29,7 +29,7 @@ "use strict"; | ||
type: 'number', | ||
validate: (value) => value >= INT_32_MIN && value <= INT_32_MAX | ||
validate: (value) => value >= INT_32_MIN && value <= INT_32_MAX, | ||
}, | ||
int64: { | ||
type: 'number', | ||
validate: (value) => value >= INT_64_MIN && value <= INT_64_MAX | ||
validate: (value) => value >= INT_64_MIN && value <= INT_64_MAX, | ||
}, | ||
@@ -36,0 +36,0 @@ double: { |
@@ -5,7 +5,7 @@ /// <reference types="node" /> | ||
import * as oas3 from 'openapi3-ts'; | ||
import { Callback, ParametersByLocation, ParametersMap, HttpIncomingMessage } from './basicTypes'; | ||
import { Readable } from 'stream'; | ||
import { ParameterLocations, ParameterLocation, ExegesisOptions } from '.'; | ||
import { ExegesisOptions, ParameterLocation, ParameterLocations } from '.'; | ||
import { Callback, HttpIncomingMessage, ParametersByLocation, ParametersMap } from './basicTypes'; | ||
import { BodyParser } from './bodyParser'; | ||
import { IValidationError, ValidatorFunction, ResponseValidationResult } from './validation'; | ||
import { IValidationError, ResponseValidationResult, ValidatorFunction } from './validation'; | ||
export interface HttpHeaders { | ||
@@ -97,3 +97,3 @@ [header: string]: number | string | string[]; | ||
export interface AuthenticationFailure { | ||
type: "invalid" | "missing"; | ||
type: 'invalid' | 'missing'; | ||
status?: number; | ||
@@ -104,3 +104,3 @@ message?: string; | ||
export interface AuthenticationSuccess { | ||
type: "success"; | ||
type: 'success'; | ||
user?: any; | ||
@@ -113,3 +113,3 @@ roles?: string[] | undefined; | ||
export interface AuthenticatorInfo { | ||
in?: "query" | "header" | "cookie"; | ||
in?: 'query' | 'header' | 'cookie'; | ||
name?: string; | ||
@@ -142,3 +142,3 @@ scheme?: string; | ||
export interface ResolvedOperation { | ||
parseParameters: (() => ParametersByLocation<ParametersMap<any>>); | ||
parseParameters: () => ParametersByLocation<ParametersMap<any>>; | ||
validateParameters: ParsedParameterValidator; | ||
@@ -160,3 +160,10 @@ parameterLocations: ParameterLocations; | ||
api: T; | ||
/** The path of the operation being accessed. e.g. "/users/1234". */ | ||
path: string; | ||
/** | ||
* The "base" of the `path`. `${baseUrl}${path}` represents the full | ||
* URL being accessed. For OAS3, for example you can set a URL like | ||
* `https://myserver.com/v1` in the `Server` object, which would be reflected | ||
* here. | ||
*/ | ||
baseUrl: string; | ||
@@ -188,2 +195,13 @@ } | ||
/** | ||
* Called before routing. Note that the context hasn't been created yet, | ||
* so you just get a raw `req` and `res` object here. | ||
*/ | ||
preRouting?: ((data: { | ||
req: http.IncomingMessage; | ||
res: http.ServerResponse; | ||
}) => void | Promise<void>) | ((data: { | ||
req: http.IncomingMessage; | ||
res: http.ServerResponse; | ||
}, done: Callback<void>) => void); | ||
/** | ||
* Called immediately after the routing phase. Note that this is | ||
@@ -228,2 +246,7 @@ * called before Exegesis verifies routing was valid - the | ||
postController?: ((pluginContext: ExegesisContext) => void | Promise<void>) | ((pluginContext: ExegesisContext, done: Callback<void>) => void); | ||
/** | ||
* Called after the response validation step. This is the last step before | ||
* the response is converted to JSON and written to the output. | ||
*/ | ||
postResponseValidation?: ((pluginContext: ExegesisContext) => void | Promise<void>) | ((pluginContext: ExegesisContext, done: Callback<void>) => void); | ||
} | ||
@@ -230,0 +253,0 @@ export interface ExegesisPlugin { |
import * as oas3 from 'openapi3-ts'; | ||
export { oas3 as oas3 }; | ||
export { oas3 }; | ||
export * from './bodyParser'; | ||
@@ -4,0 +4,0 @@ export * from './basicTypes'; |
@@ -5,3 +5,3 @@ /// <reference types="node" /> | ||
import { ResponseValidationCallback } from './validation'; | ||
import * as http from "http"; | ||
import * as http from 'http'; | ||
/** | ||
@@ -8,0 +8,0 @@ * A function which validates custom formats. |
@@ -1,4 +0,4 @@ | ||
import { ExegesisContext } from "."; | ||
import * as ajv from "ajv"; | ||
export declare type ParameterLocationIn = "path" | "server" | "query" | "cookie" | "header" | "request" | "response"; | ||
import { ExegesisContext } from '.'; | ||
import * as ajv from 'ajv'; | ||
export declare type ParameterLocationIn = 'path' | 'server' | 'query' | 'cookie' | 'header' | 'request' | 'response'; | ||
/** | ||
@@ -77,2 +77,7 @@ * The location of a parameter or property within a request. | ||
errors: IValidationError[] | null; | ||
/** | ||
* In OAS3, you can specify a response schema for different return codes. | ||
* If the status code doesn't have an explicit schema, or if it falls into | ||
* the "default" case, this flag will be true. | ||
*/ | ||
isDefault: boolean; | ||
@@ -79,0 +84,0 @@ } |
/// <reference types="node" /> | ||
import { Readable } from "stream"; | ||
import { Readable } from 'stream'; | ||
export default function bufferToStream(buf: Buffer): Readable; |
@@ -9,3 +9,3 @@ "use strict"; | ||
this.push(null); | ||
} | ||
}, | ||
}); | ||
@@ -12,0 +12,0 @@ } |
@@ -5,6 +5,6 @@ "use strict"; | ||
const contentLength = headers['content-length']; | ||
return !!headers['transfer-encoding'] || | ||
(contentLength && contentLength !== '0' && contentLength !== 0); | ||
return (!!headers['transfer-encoding'] || | ||
(contentLength && contentLength !== '0' && contentLength !== 0)); | ||
} | ||
exports.default = httpHasBody; | ||
//# sourceMappingURL=httpHasBody.js.map |
@@ -23,3 +23,3 @@ "use strict"; | ||
} | ||
else if ((typeof val === 'number') && !isNaN(val)) { | ||
else if (typeof val === 'number' && !isNaN(val)) { | ||
return 'number'; | ||
@@ -62,3 +62,3 @@ } | ||
if (stack.includes(schema)) { | ||
throw new Error("circular definition found"); | ||
throw new Error('circular definition found'); | ||
} | ||
@@ -65,0 +65,0 @@ else { |
@@ -28,6 +28,6 @@ "use strict"; | ||
schemaCount: 0, | ||
rootSubtreeRef: subtreeRef | ||
rootSubtreeRef: subtreeRef, | ||
}; | ||
json_schema_traverse_1.default(result, (schema) => { | ||
if (schema.$ref && typeof (schema.$ref) === 'string') { | ||
if (schema.$ref && typeof schema.$ref === 'string') { | ||
if (ctx.replaced[schema.$ref]) { | ||
@@ -34,0 +34,0 @@ schema.$ref = ctx.replaced[schema.$ref]; |
@@ -42,5 +42,3 @@ "use strict"; | ||
set(mimeType, value) { | ||
const { type, subtype } = isParsedMimeType(mimeType) | ||
? mimeType | ||
: parseMimeType(mimeType); | ||
const { type, subtype } = isParsedMimeType(mimeType) ? mimeType : parseMimeType(mimeType); | ||
if (type === '*' && subtype === '*') { | ||
@@ -60,5 +58,3 @@ this._defaultMimeType = value; | ||
get(mimeType) { | ||
const { type, subtype } = isParsedMimeType(mimeType) | ||
? mimeType | ||
: parseMimeType(mimeType); | ||
const { type, subtype } = isParsedMimeType(mimeType) ? mimeType : parseMimeType(mimeType); | ||
return (this._staticMimeTypes[`${type}/${subtype}`] || | ||
@@ -69,4 +65,3 @@ this._wildcardSubtypes[type] || | ||
getRegisteredTypes() { | ||
const answer = Object.keys(this._staticMimeTypes) | ||
.concat(Object.keys(this._wildcardSubtypes).map(type => `${type}/*`)); | ||
const answer = Object.keys(this._staticMimeTypes).concat(Object.keys(this._wildcardSubtypes).map(type => `${type}/*`)); | ||
if (this._defaultMimeType) { | ||
@@ -73,0 +68,0 @@ answer.push('*/*'); |
/// <reference types="node" /> | ||
import { Readable } from "stream"; | ||
import { Readable } from 'stream'; | ||
export default function stringToStream(str: string, encoding?: string): Readable; |
@@ -9,3 +9,3 @@ "use strict"; | ||
this.push(null); | ||
} | ||
}, | ||
}); | ||
@@ -12,0 +12,0 @@ } |
/// <reference types="node" /> | ||
import { Readable } from "stream"; | ||
import { Readable } from 'stream'; | ||
export declare function isReadable(obj: any): obj is Readable; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
function isReadable(obj) { | ||
return obj && obj.pipe && (typeof obj.pipe === 'function'); | ||
return obj && obj.pipe && typeof obj.pipe === 'function'; | ||
} | ||
exports.isReadable = isReadable; | ||
//# sourceMappingURL=typeUtils.js.map |
202
package.json
{ | ||
"name": "exegesis", | ||
"version": "2.2.3", | ||
"description": "Parses OpenAPI documents", | ||
"main": "lib/index.js", | ||
"types": "lib/index.d.ts", | ||
"files": [ | ||
"lib/**/*" | ||
], | ||
"scripts": { | ||
"test": "npm run build && npm run lint && npm run test:unittest", | ||
"test:pre-commit": "npm run build && npm run lint && npm run test:unittest-pc", | ||
"build": "tsc", | ||
"clean": "rm -rf lib coverage", | ||
"test:unittest": "tsc -p test && nyc mocha 'test/**/*.@(ts|js)'", | ||
"test:unittest-pc": "tsc -p test && mocha --reporter progress 'test/**/*.@(ts|js)'", | ||
"lint": "npm run lint:source && npm run lint:markdown && npm run lint:tests", | ||
"lint:source": "tslint -c tslint.json -t stylish 'src/**/*.ts'", | ||
"lint:tests": "tslint -c test/tslint.json -t stylish 'test/**/*.ts'", | ||
"lint:markdown": "markdownlint **/*.md *.md", | ||
"prepare": "npm run build", | ||
"prepublishOnly": "npm run build && npm test", | ||
"semantic-release": "semantic-release" | ||
}, | ||
"lint-staged": { | ||
"src/**/*.ts": [ | ||
"tslint -c tslint.json -t stylish" | ||
"name": "exegesis", | ||
"version": "2.3.0", | ||
"description": "Parses OpenAPI documents", | ||
"main": "lib/index.js", | ||
"types": "lib/index.d.ts", | ||
"files": [ | ||
"lib/**/*" | ||
], | ||
"test/**/*.ts": [ | ||
"tslint -c test/tslint.json -t stylish" | ||
] | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/exegesis-js/exegesis.git" | ||
}, | ||
"keywords": [ | ||
"OpenAPI", | ||
"swagger", | ||
"OAS3" | ||
], | ||
"author": "Jason Walton", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/exegesis-js/exegesis/issues" | ||
}, | ||
"homepage": "https://github.com/exegesis-js/exegesis#readme", | ||
"devDependencies": { | ||
"@jwalton/semantic-release-config": "^1.0.0", | ||
"@types/body-parser": "^1.16.8", | ||
"@types/chai": "^4.1.7", | ||
"@types/chai-as-promised": "^7.1.0", | ||
"@types/content-type": "^1.1.3", | ||
"@types/deep-freeze": "^0.1.1", | ||
"@types/glob": "^7.1.1", | ||
"@types/json-schema": "^7.0.3", | ||
"@types/lodash": "^4.14.132", | ||
"@types/mocha": "^5.2.6", | ||
"@types/node": "^12.12.2", | ||
"@types/pump": "^1.0.1", | ||
"@types/qs": "^6.5.1", | ||
"@types/semver": "^6.0.0", | ||
"chai": "^4.2.0", | ||
"chai-as-promised": "^7.1.1", | ||
"coveralls": "^3.0.2", | ||
"husky": "^3.0.0", | ||
"lint-staged": "^9.4.0", | ||
"markdownlint-cli": "^0.18.0", | ||
"mocha": "^6.1.4", | ||
"nyc": "^14.0.0", | ||
"semantic-release": "^15.13.12", | ||
"supertest-fetch": "^1.2.2", | ||
"ts-node": "^8.0.2", | ||
"tslint": "^5.12.1", | ||
"typescript": "^3.3.3" | ||
}, | ||
"dependencies": { | ||
"ajv": "^6.9.1", | ||
"body-parser": "^1.18.3", | ||
"content-type": "^1.0.4", | ||
"deep-freeze": "0.0.1", | ||
"events-listener": "^1.1.0", | ||
"glob": "^7.1.3", | ||
"json-ptr": "^1.1.1", | ||
"json-schema-ref-parser": "^7.0.0", | ||
"json-schema-traverse": "^0.4.1", | ||
"lodash": "^4.17.11", | ||
"openapi3-ts": "^1.2.0", | ||
"promise-breaker": "^5.0.0", | ||
"pump": "^3.0.0", | ||
"qs": "^6.6.0", | ||
"raw-body": "^2.3.3", | ||
"semver": "^7.0.0" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "npm run test:pre-commit" | ||
"scripts": { | ||
"test": "npm run build && npm run lint && npm run test:unittest", | ||
"test:pre-commit": "pretty-quick --staged && npm run build && npm run lint && npm run test:unittest-pc", | ||
"build": "tsc", | ||
"clean": "rm -rf lib coverage", | ||
"test:unittest": "tsc -p test && nyc mocha 'test/**/*.@(ts|js)'", | ||
"test:unittest-pc": "tsc -p test && mocha --reporter progress 'test/**/*.@(ts|js)'", | ||
"lint": "npm run lint:source && npm run lint:markdown && npm run lint:tests", | ||
"lint:source": "tslint -c tslint.json -t stylish 'src/**/*.ts'", | ||
"lint:tests": "tslint -c test/tslint.json -t stylish 'test/**/*.ts'", | ||
"lint:markdown": "markdownlint **/*.md *.md", | ||
"prepare": "npm run build", | ||
"prepublishOnly": "npm run build && npm test", | ||
"semantic-release": "semantic-release" | ||
}, | ||
"lint-staged": { | ||
"src/**/*.ts": [ | ||
"tslint -c tslint.json -t stylish" | ||
], | ||
"test/**/*.ts": [ | ||
"tslint -c test/tslint.json -t stylish" | ||
] | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/exegesis-js/exegesis.git" | ||
}, | ||
"keywords": [ | ||
"OpenAPI", | ||
"swagger", | ||
"OAS3" | ||
], | ||
"author": "Jason Walton", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/exegesis-js/exegesis/issues" | ||
}, | ||
"homepage": "https://github.com/exegesis-js/exegesis#readme", | ||
"devDependencies": { | ||
"@jwalton/semantic-release-config": "^1.0.0", | ||
"@types/body-parser": "^1.16.8", | ||
"@types/chai": "^4.1.7", | ||
"@types/chai-as-promised": "^7.1.0", | ||
"@types/content-type": "^1.1.3", | ||
"@types/deep-freeze": "^0.1.1", | ||
"@types/glob": "^7.1.1", | ||
"@types/json-schema": "^7.0.3", | ||
"@types/lodash": "^4.14.132", | ||
"@types/mocha": "^5.2.6", | ||
"@types/node": "^13.1.0", | ||
"@types/pump": "^1.0.1", | ||
"@types/qs": "^6.5.1", | ||
"@types/semver": "^6.0.0", | ||
"chai": "^4.2.0", | ||
"chai-as-promised": "^7.1.1", | ||
"coveralls": "^3.0.2", | ||
"husky": "^4.0.2", | ||
"lint-staged": "^9.4.0", | ||
"markdownlint-cli": "^0.18.0", | ||
"mocha": "^6.1.4", | ||
"nyc": "^15.0.0", | ||
"prettier": "^1.19.1", | ||
"pretty-quick": "^2.0.1", | ||
"semantic-release": "^15.13.12", | ||
"supertest-fetch": "^1.2.2", | ||
"ts-node": "^8.0.2", | ||
"tslint": "^5.12.1", | ||
"typescript": "^3.3.3" | ||
}, | ||
"dependencies": { | ||
"ajv": "^6.9.1", | ||
"body-parser": "^1.18.3", | ||
"content-type": "^1.0.4", | ||
"deep-freeze": "0.0.1", | ||
"events-listener": "^1.1.0", | ||
"glob": "^7.1.3", | ||
"json-ptr": "^1.1.1", | ||
"json-schema-ref-parser": "^7.0.0", | ||
"json-schema-traverse": "^0.4.1", | ||
"lodash": "^4.17.11", | ||
"openapi3-ts": "^1.2.0", | ||
"promise-breaker": "^5.0.0", | ||
"pump": "^3.0.0", | ||
"qs": "^6.6.0", | ||
"raw-body": "^2.3.3", | ||
"semver": "^7.0.0" | ||
}, | ||
"husky": { | ||
"hooks": { | ||
"pre-commit": "npm run test:pre-commit" | ||
} | ||
}, | ||
"engines": { | ||
"node": ">=6.0.0", | ||
"npm": ">5.0.0" | ||
} | ||
}, | ||
"engines": { | ||
"node": ">=6.0.0", | ||
"npm": ">5.0.0" | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
302983
4699
29