33const chalk = require ( 'chalk' ) ;
44const path = require ( 'path' ) ;
55const _ = require ( 'lodash' ) ;
6+ const { getReqRes } = require ( './httpReqRes' ) ;
67
78const tryToRequirePaths = ( paths ) => {
89 let loaded ;
@@ -19,10 +20,10 @@ const tryToRequirePaths = (paths) => {
1920 return loaded ;
2021} ;
2122
23+ const jsonContentType = 'application/json' ;
24+
2225module . exports = {
2326 async invokeLocalNodeJs ( functionObj , event , customContext ) {
24- let hasResponded = false ;
25-
2627 // index.js and function.js are the two files supported by default by a cloud-function
2728 // TODO add the file pointed by the main key of the package.json
2829 const paths = [ 'index.js' , 'function.js' ] . map ( ( fileName ) =>
@@ -41,27 +42,41 @@ module.exports = {
4142
4243 this . addEnvironmentVariablesToProcessEnv ( functionObj ) ;
4344
44- function handleError ( err ) {
45- let errorResult ;
46- if ( err instanceof Error ) {
47- errorResult = {
48- errorMessage : err . message ,
49- errorType : err . constructor . name ,
50- stackTrace : err . stack && err . stack . split ( '\n' ) ,
51- } ;
52- } else {
53- errorResult = {
54- errorMessage : err ,
55- } ;
56- }
45+ const eventType = Object . keys ( functionObj . events [ 0 ] ) [ 0 ] ;
5746
58- this . serverless . cli . consoleLog ( chalk . red ( JSON . stringify ( errorResult , null , 4 ) ) ) ;
59- process . exitCode = 1 ;
47+ switch ( eventType ) {
48+ case 'event' :
49+ return this . handleEvent ( cloudFunction , event , customContext ) ;
50+ case 'http' :
51+ return this . handleHttp ( cloudFunction , event , customContext ) ;
52+ default :
53+ throw new Error ( `${ eventType } is not supported` ) ;
6054 }
55+ } ,
56+ handleError ( err , resolve ) {
57+ let errorResult ;
58+ if ( err instanceof Error ) {
59+ errorResult = {
60+ errorMessage : err . message ,
61+ errorType : err . constructor . name ,
62+ stackTrace : err . stack && err . stack . split ( '\n' ) ,
63+ } ;
64+ } else {
65+ errorResult = {
66+ errorMessage : err ,
67+ } ;
68+ }
69+
70+ this . serverless . cli . consoleLog ( chalk . red ( JSON . stringify ( errorResult , null , 4 ) ) ) ;
71+ resolve ( ) ;
72+ process . exitCode = 1 ;
73+ } ,
74+ handleEvent ( cloudFunction , event , customContext ) {
75+ let hasResponded = false ;
6176
6277 function handleResult ( result ) {
6378 if ( result instanceof Error ) {
64- handleError . call ( this , result ) ;
79+ this . handleError . call ( this , result ) ;
6580 return ;
6681 }
6782 this . serverless . cli . consoleLog ( JSON . stringify ( result , null , 4 ) ) ;
@@ -72,26 +87,68 @@ module.exports = {
7287 if ( ! hasResponded ) {
7388 hasResponded = true ;
7489 if ( err ) {
75- handleError . call ( this , err ) ;
90+ this . handleError ( err , resolve ) ;
7691 } else if ( result ) {
7792 handleResult . call ( this , result ) ;
7893 }
94+ resolve ( ) ;
7995 }
80- resolve ( ) ;
8196 } ;
8297
8398 let context = { } ;
8499
85100 if ( customContext ) {
86101 context = customContext ;
87102 }
88-
89- const maybeThennable = cloudFunction ( event , context , callback ) ;
90- if ( maybeThennable ) {
91- return Promise . resolve ( maybeThennable ) . then ( callback . bind ( this , null ) , callback . bind ( this ) ) ;
103+ try {
104+ const maybeThennable = cloudFunction ( event , context , callback ) ;
105+ if ( maybeThennable ) {
106+ Promise . resolve ( maybeThennable ) . then ( callback . bind ( this , null ) , callback . bind ( this ) ) ;
107+ }
108+ } catch ( error ) {
109+ this . handleError ( error , resolve ) ;
92110 }
111+ } ) ;
112+ } ,
113+ handleHttp ( cloudFunction , event ) {
114+ const { expressRequest, expressResponse : response } = getReqRes ( ) ;
115+ const request = Object . assign ( expressRequest , event ) ;
116+
117+ return new Promise ( ( resolve ) => {
118+ const endCallback = ( data ) => {
119+ if ( data && Buffer . isBuffer ( data ) ) {
120+ data = data . toString ( ) ;
121+ }
122+ const headers = response . getHeaders ( ) ;
123+ const bodyIsJson =
124+ headers [ 'content-type' ] && headers [ 'content-type' ] . includes ( jsonContentType ) ;
125+ if ( data && bodyIsJson ) {
126+ data = JSON . parse ( data ) ;
127+ }
128+ this . serverless . cli . consoleLog (
129+ JSON . stringify (
130+ {
131+ status : response . statusCode ,
132+ headers,
133+ body : data ,
134+ } ,
135+ null ,
136+ 4
137+ )
138+ ) ;
139+ resolve ( ) ;
140+ } ;
93141
94- return maybeThennable ;
142+ Object . assign ( response , { end : endCallback } ) ; // Override of the end method which is always called to send the response of the http request
143+
144+ try {
145+ const maybeThennable = cloudFunction ( request , response ) ;
146+ if ( maybeThennable ) {
147+ Promise . resolve ( maybeThennable ) . catch ( ( error ) => this . handleError ( error , resolve ) ) ;
148+ }
149+ } catch ( error ) {
150+ this . handleError ( error , resolve ) ;
151+ }
95152 } ) ;
96153 } ,
97154
0 commit comments