@@ -4,8 +4,6 @@ const vm = require('vm');
4
4
const Config = require ( "@cocreate/config" ) ;
5
5
const { URL } = require ( 'url' ) ;
6
6
7
- // const organizations = {};
8
-
9
7
class CoCreateLazyLoader {
10
8
constructor ( server , crud , files ) {
11
9
this . server = server
@@ -75,30 +73,37 @@ class CoCreateLazyLoader {
75
73
76
74
async executeScriptWithTimeout ( name , data ) {
77
75
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
+ }
88
93
}
89
94
}
90
- }
91
95
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
+ }
102
107
103
108
if ( this . modules [ name ] . unload === false || this . modules [ name ] . unload === 'false' )
104
109
return
@@ -144,6 +149,93 @@ class CoCreateLazyLoader {
144
149
return organization . apis [ name ]
145
150
}
146
151
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
+ }
147
239
}
148
240
149
241
function getModuleDependencies ( modulePath ) {
0 commit comments