Skip to content

Commit 386fbe1

Browse files
authored
Merge pull request #36 from jeremydaly/0.5.0
0.5.0
2 parents 509bb23 + 9b7449b commit 386fbe1

27 files changed

+1849
-1699
lines changed

.travis.yml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,3 @@ language: node_js
22

33
node_js:
44
- "8"
5-
- "7"
6-
- "6"

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2017 Jeremy Daly
3+
Copyright (c) 2017-2018 Jeremy Daly
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 184 additions & 123 deletions
Large diffs are not rendered by default.

index.js

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

10-
const REQUEST = require('./request.js') // Response object
11-
const RESPONSE = require('./response.js') // Response object
12-
const Promise = require('bluebird') // Promise library
10+
const REQUEST = require('./lib/request.js') // Response object
11+
const RESPONSE = require('./lib/response.js') // Response object
1312

1413
// Create the API class
1514
class API {
@@ -51,47 +50,24 @@ class API {
5150
// Executed after the callback
5251
this._finally = () => {}
5352

54-
// Promise placeholder for final route promise resolution
55-
this._promise = function() { console.log('no promise to resolve') }
56-
this._reject = function() { console.log('no promise to reject') }
57-
5853
// Global error status
5954
this._errorStatus = 500
6055

61-
// Testing flag
56+
// Testing flag (disables logging)
6257
this._test = false
6358

6459
} // end constructor
6560

66-
// GET: convenience method
67-
get(path, handler) {
68-
this.METHOD('GET', path, handler)
69-
}
7061

71-
// POST: convenience method
72-
post(path, handler) {
73-
this.METHOD('POST', path, handler)
74-
}
7562

76-
// PUT: convenience method
77-
put(path, handler) {
78-
this.METHOD('PUT', path, handler)
79-
}
63+
// Convenience methods (path, handler)
64+
get(p,h) { this.METHOD('GET',p,h) }
65+
post(p,h) { this.METHOD('POST',p,h) }
66+
put(p,h) { this.METHOD('PUT',p,h) }
67+
patch(p,h) { this.METHOD('PATCH',p,h) }
68+
delete(p,h) { this.METHOD('DELETE',p,h) }
69+
options(p,h) { this.METHOD('OPTIONS',p,h) }
8070

81-
// PATCH: convenience method
82-
patch(path, handler) {
83-
this.METHOD('PATCH', path, handler)
84-
}
85-
86-
// DELETE: convenience method
87-
delete(path, handler) {
88-
this.METHOD('DELETE', path, handler)
89-
}
90-
91-
// OPTIONS: convenience method
92-
options(path, handler) {
93-
this.METHOD('OPTIONS', path, handler)
94-
}
9571

9672
// METHOD: Adds method and handler to routes
9773
METHOD(method, path, handler) {
@@ -124,112 +100,88 @@ class API {
124100
this._routes,
125101
(i === route.length-1 ? { ['__'+method.toUpperCase()]: { vars: pathVars, handler: handler, route: '/'+parsedPath.join('/') } } : {}),
126102
route.slice(0,i+1)
127-
);
103+
)
128104

129105
} // end for loop
130106

131107
} // end main METHOD function
132108

133109

134-
// RUN: This runs the routes
135-
run(event,context,cb) { // TODO: Make this dynamic
136-
137-
this.startTimer('total')
138110

139-
this._done = false
111+
// RUN: This runs the routes
112+
async run(event,context,cb) {
140113

141114
// Set the event, context and callback
142115
this._event = event
143116
this._context = context
144117
this._cb = cb
145118

146-
// Initalize response object
147-
let response = new RESPONSE(this)
148-
let request = {}
119+
try {
120+
// Initalize response and request objects
121+
this.response = new RESPONSE(this)
122+
this.request = new REQUEST(this)
149123

150-
Promise.try(() => { // Start a promise
124+
// Loop through the middleware and await response
125+
for (const mw of this._middleware) {
126+
await new Promise(r => { mw(this.request,this.response,() => { r() }) })
127+
} // end for
151128

152-
// Initalize the request object
153-
request = new REQUEST(this)
129+
// Execute the primary handler
130+
await this.handler(this.request,this.response)
154131

155-
// Execute the request
156-
return this.execute(request,response)
132+
} catch(e) {
133+
this.catchErrors(e)
134+
}
157135

158-
}).catch((e) => {
136+
} // end run function
159137

160-
// Error messages should never be base64 encoded
161-
response._isBase64 = false
162138

163-
// Strip the headers (TODO: find a better way to handle this)
164-
response._headers = {}
165139

166-
let message;
140+
// Catch all async/sync errors
141+
async catchErrors(e) {
167142

168-
if (e instanceof Error) {
169-
response.status(this._errorStatus)
170-
message = e.message
171-
!this._test && console.log(e)
172-
} else {
173-
message = e
174-
!this._test && console.log('API Error:',e)
175-
}
143+
// Error messages should never be base64 encoded
144+
this.response._isBase64 = false
176145

177-
// Execute error middleware
178-
if (this._errors.length > 0) {
179-
180-
// Init stack queue
181-
let queue = []
182-
183-
// Loop through the middleware and queue promises
184-
for (let i in this._errors) {
185-
queue.push(() => {
186-
return new Promise((resolve, reject) => {
187-
this._promise = () => { resolve() } // keep track of the last resolve()
188-
this._reject = (e) => { reject(e) } // keep track of the last reject()
189-
this._errors[i](e,request,response,() => { resolve() }) // execute the errors with the resolve callback
190-
}) // end promise
191-
}) // end queue
192-
} // end for
193-
194-
// Return Promise.each serialially
195-
return Promise.each(queue, function(queue_item) {
196-
return queue_item()
197-
}).then(() => {
198-
response.json({'error':message})
199-
})
146+
// Strip the headers (TODO: find a better way to handle this)
147+
this.response._headers = {}
200148

201-
} else {
202-
response.json({'error':message})
203-
}
149+
let message;
204150

205-
}).finally(() => {
206-
this._finally(request,response)
207-
})
208-
} // end run function
151+
if (e instanceof Error) {
152+
this.response.status(this._errorStatus)
153+
message = e.message
154+
!this._test && console.log(e)
155+
} else {
156+
message = e
157+
!this._test && console.log('API Error:',e)
158+
}
209159

160+
// Execute error middleware
161+
for (const err of this._errors) {
162+
// Promisify error middleware
163+
await new Promise(r => { err(e,this.request,this.response,() => { r() }) })
164+
} // end for
210165

211-
// Custom callback
212-
_callback(err, res) {
166+
this.response.json({'error':message})
213167

214-
// Resolve any outstanding promise
215-
this._promise()
168+
} // end catch
216169

217-
this._done = true
218170

219-
this.endTimer('total')
220171

221-
if (res) {
222-
if (this._debug) {
223-
console.log(this._procTimes)
224-
}
225-
}
172+
// Custom callback
173+
async _callback(err, res) {
174+
175+
// Execute finally
176+
await this._finally(this.request,this.response)
226177

227178
// Execute the primary callback
228179
this._cb(err,res)
229180

230181
} // end _callback
231182

232183

184+
233185
// Middleware handler
234186
use(fn) {
235187
if (fn.length === 3) {
@@ -241,79 +193,12 @@ class API {
241193
}
242194
} // end use
243195

244-
// Finally function
196+
197+
// Finally handler
245198
finally(fn) {
246199
this._finally = fn
247200
}
248201

249-
// Process
250-
execute(req,res) {
251-
252-
// Init stack queue
253-
let queue = []
254-
255-
// If execute is called after the app is done, just return out
256-
if (this._done) { return; }
257-
258-
// If there is middleware
259-
if (this._middleware.length > 0) {
260-
// Loop through the middleware and queue promises
261-
for (let i in this._middleware) {
262-
queue.push(() => {
263-
return new Promise((resolve, reject) => {
264-
this._promise = () => { resolve() } // keep track of the last resolve()
265-
this._reject = (e) => { reject(e) } // keep track of the last reject()
266-
this._middleware[i](req,res,() => { resolve() }) // execute the middleware with the resolve callback
267-
}) // end promise
268-
}) // end queue
269-
} // end for
270-
} // end if
271-
272-
// Push the main execution path to the queue stack
273-
queue.push(() => {
274-
return new Promise((resolve, reject) => {
275-
this._promise = () => { resolve() } // keep track of the last resolve()
276-
this._reject = (e) => { reject(e) } // keep track of the last reject()
277-
this.handler(req,res) // execute the handler with no callback
278-
})
279-
})
280-
281-
// Return Promise.each serialially
282-
return Promise.each(queue, function(queue_item) {
283-
return queue_item()
284-
})
285-
286-
} // end execute
287-
288-
289-
290-
//-------------------------------------------------------------------------//
291-
// TIMER FUNCTIONS
292-
//-------------------------------------------------------------------------//
293-
294-
// Returns the calculated processing times from all stopped timers
295-
getTimers(timer) {
296-
if (timer) {
297-
return this._procTimes[timer]
298-
} else {
299-
return this._procTimes
300-
}
301-
} // end getTimers
302-
303-
// Starts a timer for debugging purposes
304-
startTimer(name) {
305-
this._timers[name] = Date.now()
306-
} // end startTimer
307-
308-
// Ends a timer and calculates the total processing time
309-
endTimer(name) {
310-
try {
311-
this._procTimes[name] = (Date.now()-this._timers[name]) + ' ms'
312-
delete this._timers[name]
313-
} catch(e) {
314-
console.error('Could not end timer: ' + name)
315-
}
316-
} // end endTimer
317202

318203

319204
//-------------------------------------------------------------------------//
@@ -324,20 +209,20 @@ class API {
324209
return path.trim().replace(/^\/(.*?)(\/)*$/,'$1').split('/').filter(x => x.trim() !== '')
325210
}
326211

327-
212+
// Recursive function to create routes object
328213
setRoute(obj, value, path) {
329214
if (typeof path === "string") {
330215
let path = path.split('.')
331216
}
332217

333218
if (path.length > 1){
334219
let p = path.shift()
335-
if (obj[p] === null) { // || typeof obj[p] !== 'object') {
220+
if (obj[p] === null) {
336221
obj[p] = {}
337222
}
338223
this.setRoute(obj[p], value, path)
339224
} else {
340-
if (obj[path[0]] === null) { // || typeof obj[path[0]] !== 'object') {
225+
if (obj[path[0]] === null) {
341226
obj[path[0]] = value
342227
} else {
343228
obj[path[0]] = Object.assign(value,obj[path[0]])
@@ -386,7 +271,9 @@ class API {
386271

387272
} // end register
388273

274+
389275
} // end API class
390276

391-
// Export the API class
277+
278+
// Export the API class as a new instance
392279
module.exports = opts => new API(opts)
File renamed without changes.

0 commit comments

Comments
 (0)