lambda-router
Advanced tools
Comparing version 2.6.0 to 2.7.0
@@ -7,2 +7,6 @@ # Change Log / Release Notes | ||
## [2.7.0] - 2019-06-19 | ||
### Added | ||
- `assumeJson` option | ||
## [2.6.0] - 2019-06-19 | ||
@@ -9,0 +13,0 @@ ### Added |
{ | ||
"name": "lambda-router", | ||
"version": "2.6.0", | ||
"version": "2.7.0", | ||
"description": "A router to simplify AWS Lambda Functions.", | ||
@@ -14,7 +14,7 @@ "main": "src/index.js", | ||
"test:coverage": "nyc --check-coverage --lines 90 npm run test:unit && npm run report", | ||
"test": "npm run style && npm run test:unit", | ||
"test:unit": "blue-tape \"test/**/**.spec.js\" | tap-spec", | ||
"test": "npm run check && npm run test:unit", | ||
"test:unit": "blue-tape \"test/**/**.spec.js\" | tap-nirvana", | ||
"test:unit:watch": "npm run test:unit -s & chokidar 'src/**/*.js' 'test/**/*.spec.js' --polling -c \"npm run test:unit -s\"", | ||
"test:watch": "npm run test:coverage -s & chokidar 'src/**/*.js' 'test/**/*.spec.js' --polling -c \"npm run test:coverage -s\"", | ||
"test:ci": "npm run style && blue-tape test/**/**.spec.js | tap-xunit > xunit.xml && blue-tape test/**/**.int.js | tap-xunit > xunit.xml && npm run test:coverage && npm run report:ci", | ||
"test:ci": "npm run check && blue-tape test/**/**.spec.js | tap-xunit > xunit.xml && blue-tape test/**/**.int.js | tap-xunit > xunit.xml && npm run test:coverage && npm run report:ci", | ||
"report": "nyc report --reporter=html", | ||
@@ -24,4 +24,5 @@ "report:ci": "npm run report", | ||
"test:coverage:open": "npm run test:coverage && npm run report:open", | ||
"style": "standard \"src/**/*.js\" | snazzy", | ||
"style:fix": "standard \"src/**/*.js\" --fix", | ||
"style": "prettier --config package.json --write \"{src,test}/**/*.js\"", | ||
"lint": "eslint -c package.json \"{src,test}/**/*.js\"", | ||
"check": "npm run style && npm run lint", | ||
"jsdoc:generate": "jsdoc ./src/index.js -d ./docs/" | ||
@@ -47,4 +48,5 @@ }, | ||
"devDependencies": { | ||
"@kyeotic/eslint-config": "^0.9.0", | ||
"aws-sdk": "^2.4.8", | ||
"babel-eslint": "^6.1.2", | ||
"babel-eslint": "^10.0.2", | ||
"blue-tape": "^0.2.0", | ||
@@ -55,6 +57,16 @@ "chokidar-cli": "^1.2.0", | ||
"nyc": "latest", | ||
"snazzy": "^5.0.0", | ||
"standard": "8.1.0", | ||
"tap-spec": "^4.1.1" | ||
"prettier": "^1.18.2", | ||
"tap-nirvana": "^1.1.0" | ||
}, | ||
"prettier": { | ||
"tabWidth": 2, | ||
"semi": false, | ||
"singleQuote": true, | ||
"printWidth": 100 | ||
}, | ||
"eslintConfig": { | ||
"extends": [ | ||
"@kyeotic/eslint-config/node" | ||
] | ||
} | ||
} |
@@ -16,3 +16,3 @@ 'use strict' | ||
function Router ({ | ||
function Router({ | ||
logger, | ||
@@ -27,2 +27,3 @@ extractPathParameters = true, | ||
parseBody = true, | ||
assumeJson = false, | ||
decodeEvent = true | ||
@@ -60,3 +61,4 @@ } = {}) { | ||
if (context.response) { | ||
let message = 'context.response has already been assigned. Lambda-router reserves this property for custom responses.' | ||
let message = | ||
'context.response has already been assigned. Lambda-router reserves this property for custom responses.' | ||
logger.error(message) | ||
@@ -82,5 +84,6 @@ return Promise.reject(new Error(message)) | ||
let hasBody = event.body && typeof event.body === 'string' | ||
let contentType = event.headers && (event.headers['content-type'] || event.headers['Content-Type']) | ||
let jsonBody = hasBody && event.headers && contentType === 'application/json' | ||
let urlEncodedBody = hasBody && event.headers && contentType === 'application/x-www-form-urlencoded' | ||
let contentType = | ||
event.headers && (event.headers['content-type'] || event.headers['Content-Type']) | ||
let jsonBody = hasBody && (contentType === 'application/json' || (!contentType && assumeJson)) | ||
let urlEncodedBody = hasBody && contentType === 'application/x-www-form-urlencoded' | ||
@@ -101,3 +104,9 @@ // Parse and decode | ||
logger.error('route error', error.toString(), error.stack) | ||
return createResponse(400, { message: 'Malformed request' }, defaultHeaders, route.path, requestPath) | ||
return createResponse( | ||
400, | ||
{ message: 'Malformed request' }, | ||
defaultHeaders, | ||
route.path, | ||
requestPath | ||
) | ||
} | ||
@@ -109,8 +118,8 @@ | ||
let result = await (route | ||
? route.handler(event, context) | ||
: unknownRouteHandler(event, context, requestPath, httpMethod)) | ||
? route.handler(event, context) | ||
: unknownRouteHandler(event, context, requestPath, httpMethod)) | ||
if (result && result._isCustomResponse === CUSTOM_RESPONSE) { | ||
statusCode = result.statusCode | ||
body = result.body | ||
headers = {...defaultHeaders, ...result.headers} | ||
headers = { ...defaultHeaders, ...result.headers } | ||
} else { | ||
@@ -141,5 +150,9 @@ statusCode = 200 | ||
put: add.bind(null, 'PUT'), | ||
'delete': add.bind(null, 'DELETE'), | ||
unknown: (handler) => { unknownRouteHandler = handler }, | ||
formatError: (handler) => { onErrorFormat = handler }, | ||
delete: add.bind(null, 'DELETE'), | ||
unknown: handler => { | ||
unknownRouteHandler = handler | ||
}, | ||
formatError: handler => { | ||
onErrorFormat = handler | ||
}, | ||
route | ||
@@ -149,3 +162,3 @@ } | ||
function customResponse (context, statusCode, body, headers) { | ||
function customResponse(context, statusCode, body, headers) { | ||
let response = { | ||
@@ -167,3 +180,3 @@ statusCode, | ||
function getRoute (routes, event, eventPath, method, tokenizePathParts) { | ||
function getRoute(routes, event, eventPath, method, tokenizePathParts) { | ||
let route = routes.find(r => { | ||
@@ -189,3 +202,3 @@ return eventPath === r.path && method === r.method | ||
function doPathPartsMatch (eventPath, route) { | ||
function doPathPartsMatch(eventPath, route) { | ||
const eventPathParts = eventPath.split('/') | ||
@@ -219,3 +232,3 @@ const routePathParts = route.path.split('/') | ||
function defaultUnknownRoute (event, context, path, method) { | ||
function defaultUnknownRoute(event, context, path) { | ||
let error = new Error(`No route specified for path: ${path}`) | ||
@@ -226,3 +239,3 @@ error.statusCode = 404 | ||
function createResponse (statusCode, body, headers, endpoint, uri) { | ||
function createResponse(statusCode, body, headers, endpoint, uri) { | ||
return { | ||
@@ -236,3 +249,3 @@ endpoint, | ||
function createProxyResponse (statusCode, body, headers = {}) { | ||
function createProxyResponse(statusCode, body, headers = {}) { | ||
if (headers['Content-Type'] === undefined) headers['Content-Type'] = 'application/json' | ||
@@ -242,3 +255,3 @@ // output follows the format described here | ||
return { | ||
statusCode: statusCode, | ||
statusCode, | ||
body: typeof body === 'object' ? JSON.stringify(body) : body, | ||
@@ -249,10 +262,11 @@ headers: { ...headers } | ||
function getTraceId (event, context) { | ||
const traceId = event.headers && | ||
(event.headers['X-Trace-Id'] || | ||
event.headers['X-TRACE-ID'] || | ||
event.headers['x-trace-id'] || | ||
event.headers['X-Correlation-Id'] || | ||
event.headers['X-CORRELATION-ID'] || | ||
event.headers['x-correlation-id']) || | ||
function getTraceId(event, context) { | ||
const traceId = | ||
(event.headers && | ||
(event.headers['X-Trace-Id'] || | ||
event.headers['X-TRACE-ID'] || | ||
event.headers['x-trace-id'] || | ||
event.headers['X-Correlation-Id'] || | ||
event.headers['X-CORRELATION-ID'] || | ||
event.headers['x-correlation-id'])) || | ||
context.awsRequestId || | ||
@@ -264,7 +278,10 @@ uuid() | ||
function decodeProperties (obj) { | ||
return obj && Object.keys(obj).reduce((r, key) => { | ||
r[key] = decodeURIComponent(obj[key]) | ||
return r | ||
}, {}) | ||
function decodeProperties(obj) { | ||
return ( | ||
obj && | ||
Object.keys(obj).reduce((r, key) => { | ||
r[key] = decodeURIComponent(obj[key]) | ||
return r | ||
}, {}) | ||
) | ||
} |
@@ -1,2 +0,1 @@ | ||
'use strict' | ||
@@ -6,2 +5,3 @@ const assert = require('assert') | ||
const logLevels = ['DEBUG', 'INFO', 'WARN', 'ERROR'] | ||
// eslint-disable-next-line no-empty-function | ||
const noop = () => {} | ||
@@ -14,6 +14,14 @@ | ||
} else { | ||
func = logger.minimumLogLevel !== undefined ? (console[prop] || console.log).bind(console) : noop | ||
func = | ||
logger.minimumLogLevel !== undefined | ||
? // eslint-disable-next-line no-console | ||
(console[prop] || console.log).bind(console) | ||
: noop | ||
} | ||
return (...args) => { | ||
if (logger.minimumLogLevel !== undefined && logLevels.indexOf(logger.minimumLogLevel) > logLevels.indexOf(prop.toUpperCase())) return | ||
if ( | ||
logger.minimumLogLevel !== undefined && | ||
logLevels.indexOf(logger.minimumLogLevel) > logLevels.indexOf(prop.toUpperCase()) | ||
) | ||
return | ||
return func(...args) | ||
@@ -23,6 +31,9 @@ } | ||
function loggerWrapper (loggerArg) { | ||
function loggerWrapper(loggerArg) { | ||
const logger = loggerArg || {} | ||
if (logger.minimumLogLevel !== undefined) { | ||
assert(logLevels.indexOf(logger.minimumLogLevel) !== -1, `"minimumLogLevel" must be one of: ${logLevels.join(', ')} or "undefined"`) | ||
assert( | ||
logLevels.indexOf(logger.minimumLogLevel) !== -1, | ||
`"minimumLogLevel" must be one of: ${logLevels.join(', ')} or "undefined"` | ||
) | ||
} | ||
@@ -29,0 +40,0 @@ |
29942
283