Skip to content

Commit cd09fbc

Browse files
authored
Merge pull request #60 from jeremydaly/v0.8.0
v0.8.0
2 parents 9f47703 + e80422f commit cd09fbc

22 files changed

+3645
-192
lines changed

README.md

Lines changed: 428 additions & 29 deletions
Large diffs are not rendered by default.

index.js

Lines changed: 82 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
/**
44
* Lightweight web framework for your serverless applications
55
* @author Jeremy Daly <[email protected]>
6-
* @version 0.7.0
6+
* @version 0.8.0
77
* @license MIT
88
*/
99

1010
const REQUEST = require('./lib/request.js') // Resquest object
1111
const RESPONSE = require('./lib/response.js') // Response object
1212
const UTILS = require('./lib/utils.js') // Require utils library
13+
const LOGGER = require('./lib/logger.js') // Require logger library
1314
const prettyPrint = require('./lib/prettyPrint') // Pretty print for debugging
1415

1516
// Create the API class
@@ -24,16 +25,36 @@ class API {
2425
this._callbackName = props && props.callback ? props.callback.trim() : 'callback'
2526
this._mimeTypes = props && props.mimeTypes && typeof props.mimeTypes === 'object' ? props.mimeTypes : {}
2627

28+
// Set sampling info
29+
this._sampleCounts = {}
30+
31+
// Init request counter
32+
this._requestCount = 0
33+
34+
// Track init date/time
35+
this._initTime = Date.now()
36+
37+
// Logging levels
38+
this._logLevels = {
39+
trace: 10,
40+
debug: 20,
41+
info: 30,
42+
warn: 40,
43+
error: 50,
44+
fatal: 60
45+
}
46+
47+
// Configure logger
48+
this._logger = LOGGER.config(props && props.logger,this._logLevels)
49+
2750
// Prefix stack w/ base
2851
this._prefix = this.parseRoute(this._base)
2952

3053
// Stores route mappings
3154
this._routes = {}
3255

33-
// Default callback
34-
this._cb = function() {
35-
console.log('No callback specified') // eslint-disable-line no-console
36-
}
56+
// Init callback
57+
this._cb
3758

3859
// Middleware stack
3960
this._middleware = []
@@ -47,12 +68,9 @@ class API {
4768
// Executed after the callback
4869
this._finally = () => {}
4970

50-
// Global error status
71+
// Global error status (used for response parsing errors)
5172
this._errorStatus = 500
5273

53-
// Testing flag (disables logging)
54-
this._test = false
55-
5674
} // end constructor
5775

5876

@@ -71,6 +89,10 @@ class API {
7189
// METHOD: Adds method and handler to routes
7290
METHOD(method, path, handler) {
7391

92+
if (typeof handler !== 'function') {
93+
throw new Error(`No route handler specified for ${method} method on ${path} route.`)
94+
}
95+
7496
// Ensure method is an array
7597
let methods = Array.isArray(method) ? method : method.split(',')
7698

@@ -126,8 +148,8 @@ class API {
126148

127149
// Set the event, context and callback
128150
this._event = event
129-
this._context = this.context = context
130-
this._cb = cb
151+
this._context = this.context = typeof context === 'object' ? context : {}
152+
this._cb = cb ? cb : undefined
131153

132154
// Initalize request and response objects
133155
let request = new REQUEST(this)
@@ -136,7 +158,7 @@ class API {
136158
try {
137159

138160
// Parse the request
139-
request.parseRequest()
161+
await request.parseRequest()
140162

141163
// Loop through the middleware and await response
142164
for (const mw of this._middleware) {
@@ -175,15 +197,18 @@ class API {
175197
}
176198

177199
} catch(e) {
178-
this.catchErrors(e,response)
200+
await this.catchErrors(e,response)
179201
}
180202

203+
// Return the final response
204+
return response._response
205+
181206
} // end run function
182207

183208

184209

185210
// Catch all async/sync errors
186-
async catchErrors(e,response) {
211+
async catchErrors(e,response,code,detail) {
187212

188213
// Error messages should never be base64 encoded
189214
response._isBase64 = false
@@ -193,13 +218,21 @@ class API {
193218

194219
let message
195220

221+
let info = {
222+
detail,
223+
statusCode: response._statusCode,
224+
coldStart: response._request.coldStart,
225+
stack: this._logger.stack && e.stack || undefined
226+
}
227+
196228
if (e instanceof Error) {
197-
response.status(this._errorStatus)
229+
response.status(code ? code : this._errorStatus)
198230
message = e.message
199-
!this._test && console.log(e) // eslint-disable-line no-console
231+
this.log.fatal(message, info)
200232
} else {
233+
response.status(code)
201234
message = e
202-
!this._test && console.log('API Error:',e) // eslint-disable-line no-console
235+
this.log.error(message, info)
203236
}
204237

205238
// If first time through, process error middleware
@@ -227,34 +260,55 @@ class API {
227260

228261

229262
// Custom callback
230-
async _callback(err, res, response) {
263+
async _callback(err,res,response) {
231264

232265
// Set done status
233266
response._state = 'done'
234267

235268
// Execute finally
236269
await this._finally(response._request,response)
237270

271+
// Output logs
272+
response._request._logs.forEach(log => {
273+
console.log(JSON.stringify(this._logger.detail ? // eslint-disable-line no-console
274+
this._logger.format(log,response._request,response) : log))
275+
})
276+
277+
// Generate access log
278+
if ((this._logger.access || response._request._logs.length > 0) && this._logger.access !== 'never') {
279+
let access = Object.assign(
280+
this._logger.log('access',undefined,response._request,response._request.context),
281+
{ statusCode: res.statusCode, coldStart: response._request.coldStart, count: response._request.requestCount }
282+
)
283+
console.log(JSON.stringify(this._logger.format(access,response._request,response))) // eslint-disable-line no-console
284+
}
285+
238286
// Execute the primary callback
239-
this._cb(err,res)
287+
typeof this._cb === 'function' && this._cb(err,res)
240288

241289
} // end _callback
242290

243291

244292

245293
// Middleware handler
246-
use(path,handler) {
294+
use(path) {
247295

248-
let fn = typeof path === 'function' ? path : handler
296+
// Extract routes
249297
let routes = typeof path === 'string' ? Array.of(path) : (Array.isArray(path) ? path : [])
250298

251-
if (fn.length === 3) {
252-
this._middleware.push([routes,fn])
253-
} else if (fn.length === 4) {
254-
this._errors.push(fn)
255-
} else {
256-
throw new Error('Middleware must have 3 or 4 parameters')
299+
// Add func args as middleware
300+
for (let arg in arguments) {
301+
if (typeof arguments[arg] === 'function') {
302+
if (arguments[arg].length === 3) {
303+
this._middleware.push([routes,arguments[arg]])
304+
} else if (arguments[arg].length === 4) {
305+
this._errors.push(arguments[arg])
306+
} else {
307+
throw new Error('Middleware must have 3 or 4 parameters')
308+
}
309+
}
257310
}
311+
258312
} // end use
259313

260314

@@ -276,7 +330,7 @@ class API {
276330
// Recursive function to create routes object
277331
setRoute(obj, value, path) {
278332
if (typeof path === 'string') {
279-
let path = path.split('.')
333+
path = path.split('.')
280334
}
281335

282336
if (path.length > 1){

0 commit comments

Comments
 (0)