@@ -4,8 +4,6 @@ const vm = require('vm');
44const Config = require ( "@cocreate/config" ) ;
55const { URL } = require ( 'url' ) ;
66
7- // const organizations = {};
8-
97class CoCreateLazyLoader {
108 constructor ( server , crud , files ) {
119 this . server = server
@@ -75,30 +73,37 @@ class CoCreateLazyLoader {
7573
7674 async executeScriptWithTimeout ( name , data ) {
7775 try {
78- if ( ! this . modules [ name ] . content ) {
79- if ( this . modules [ name ] . path )
80- this . modules [ name ] . content = await require ( this . modules [ name ] . path )
81- else {
82- try {
83- const scriptPath = path . join ( scriptsDirectory , `${ name } .js` ) ;
84- await fs . access ( scriptPath ) ;
85- this . modules [ name ] . content = await fs . readFile ( scriptPath , 'utf8' ) ;
86- } catch {
87- this . modules [ name ] . content = await fetchScriptFromDatabaseAndSave ( name , this . modules [ name ] , data ) ;
76+ if ( this . modules [ name ] . initialize ) {
77+ if ( data . req )
78+ data = await this . webhooks ( data )
79+ else
80+ data = await this . api ( this . modules [ name ] , data )
81+ } else {
82+ if ( ! this . modules [ name ] . content ) {
83+ if ( this . modules [ name ] . path )
84+ this . modules [ name ] . content = await require ( this . modules [ name ] . path )
85+ else {
86+ try {
87+ const scriptPath = path . join ( scriptsDirectory , `${ name } .js` ) ;
88+ await fs . access ( scriptPath ) ;
89+ this . modules [ name ] . content = await fs . readFile ( scriptPath , 'utf8' ) ;
90+ } catch {
91+ this . modules [ name ] . content = await fetchScriptFromDatabaseAndSave ( name , this . modules [ name ] , data ) ;
92+ }
8893 }
8994 }
90- }
9195
92- if ( this . modules [ name ] . content ) {
93- data . apis = await this . getApiKey ( data . organization_id , name )
94- data . crud = this . crud
95- data = await this . modules [ name ] . content . send ( data )
96- delete data . apis
97- delete data . crud
98- if ( data . socket )
99- this . wsManager . send ( data )
100- } else
101- return
96+ if ( this . modules [ name ] . content ) {
97+ data . apis = await this . getApiKey ( data . organization_id , name )
98+ data . crud = this . crud
99+ data = await this . modules [ name ] . content . send ( data )
100+ delete data . apis
101+ delete data . crud
102+ if ( data . socket )
103+ this . wsManager . send ( data )
104+ } else
105+ return
106+ }
102107
103108 if ( this . modules [ name ] . unload === false || this . modules [ name ] . unload === 'false' )
104109 return
@@ -144,6 +149,93 @@ class CoCreateLazyLoader {
144149 return organization . apis [ name ]
145150 }
146151
152+ async api ( config , data ) {
153+ try {
154+ const methodPath = data . method . split ( '.' )
155+ const name = methodPath . shift ( )
156+
157+ const apis = await this . getApiKey ( data . organization_id , name )
158+ if ( apis . error )
159+ return data . error = apis . error
160+
161+ const environment = data . environment || 'production' ;
162+ const key = apis [ environment ] ;
163+ if ( ! key )
164+ return data . error = `Missing ${ name } key in organization apis object`
165+
166+ const service = require ( config . path ) ;
167+ const instance = new service [ config . initialize ] ( key ) ;
168+
169+ let method = instance
170+ for ( let i = 0 ; i < methodPath . length ; i ++ ) {
171+ method = method [ methodPath [ i ] ]
172+ if ( method === undefined ) {
173+ return data . error = `Method ${ methodPath [ i ] } not found using ${ data . method } .`
174+ }
175+ }
176+
177+ if ( typeof method !== 'function' )
178+ return data . error = `Method ${ data . method } is not a function.`
179+
180+ return data . postmark = await method . apply ( instance , [ data [ name ] ] ) ;
181+ } catch ( error ) {
182+ return data . error = error . message
183+ }
184+ }
185+
186+ async webhooks ( config , data ) {
187+ try {
188+ const apis = await this . getApiKey ( data . organization_id , name )
189+ if ( apis . error )
190+ return data . error = apis . error
191+
192+ let environment = data . environment || 'production' ;
193+ if ( data . host . startsWith ( 'dev.' ) || data . host . startsWith ( 'test.' ) )
194+ environment = 'test'
195+
196+ const key = apis [ environment ] ;
197+ if ( ! key )
198+ return data . error = `Missing ${ name } key in organization apis object`
199+
200+ let name = data . req . url . split ( '/' ) ;
201+ name = name [ 3 ] || name [ 2 ] || name [ 1 ]
202+
203+ // TODO: webhook secert could be a key pair
204+ const webhookSecret = data . apis [ environment ] . webhooks [ name ] ;
205+ if ( webhookSecret !== req . headers [ name ] )
206+ return data . error = `Webhook secret failed for ${ name } . Unauthorized access attempt.` ;
207+
208+ let rawBody = '' ;
209+ await new Promise ( ( resolve , reject ) => {
210+ data . req . on ( 'data' , chunk => {
211+ rawBody += chunk . toString ( ) ;
212+ } ) ;
213+ data . req . on ( 'end' , ( ) => {
214+ resolve ( ) ;
215+ } ) ;
216+ data . req . on ( 'error' , ( err ) => {
217+ reject ( err ) ;
218+ } ) ;
219+ } ) ;
220+
221+ // TODO: if decrypt and validation is builtin to service
222+ // const service = require(config.path);
223+ // const instance = new service[config.initialize](key);
224+
225+ // TODO: event may need to be handle by a built in service function
226+ const event = JSON . parse ( rawBody )
227+ // TODO: using request.method and event.type get object and send socket.onMessage for proccessing
228+
229+ data . res . writeHead ( 200 , { 'Content-Type' : 'application/json' } ) ;
230+ data . res . end ( JSON . stringify ( { message : 'Webhook received and processed' } ) ) ;
231+ return data
232+ } catch ( error ) {
233+ data . error = error . message
234+ data . res . writeHead ( 400 , { 'Content-Type' : 'text/plain' } ) ;
235+ data . res . end ( `Webhook Error: ${ err . message } ` ) ;
236+ return data
237+ }
238+ }
147239}
148240
149241function getModuleDependencies ( modulePath ) {
0 commit comments