@@ -3,56 +3,97 @@ const eventEmitter = new EventEmitter();
3
3
const fs = require ( 'fs' ) . promises ;
4
4
const path = require ( 'path' ) ;
5
5
const vm = require ( 'vm' ) ;
6
-
7
- const scriptsDirectory = './scripts' ;
6
+ const Config = require ( "@cocreate/config" ) ;
8
7
9
8
class CoCreateLazyLoader {
10
9
constructor ( crud ) {
11
10
this . wsManager = crud . wsManager
12
11
this . crud = crud
12
+ this . exclusion = { ...require . cache } ;
13
+ this . modules = { } ;
13
14
this . init ( )
14
15
}
15
16
16
- init ( ) {
17
- // TODO: check CoCreate.config.js using config
18
- const lazyLoadConfig = Config ( 'lazyload' )
19
- if ( ! lazyLoadConfig )
17
+ async init ( ) {
18
+ // Function to create the scripts directory if it doesn't exist
19
+ async function createScriptsDirectory ( ) {
20
+ try {
21
+ const scriptsDirectory = './scripts' ;
22
+ await fs . mkdir ( scriptsDirectory , { recursive : true } ) ;
23
+ console . log ( `Scripts directory created at ${ scriptsDirectory } ` ) ;
24
+ } catch ( error ) {
25
+ console . error ( 'Error creating scripts directory:' , error ) ;
26
+ throw error ; // Halt execution if directory creation fails
27
+ }
28
+ }
29
+
30
+ // Call this function at the start of your application
31
+ createScriptsDirectory ( ) ;
32
+
33
+ const config = await Config ( 'lazyload' , false , false )
34
+ if ( ! config )
20
35
return
21
36
22
- for ( let key of Object . keys ( lazyLoadConfig . lazyload ) ) {
23
- let moduleConfig = lazyLoadConfig . lazyload [ key ] ;
37
+ for ( let key of Object . keys ( config . lazyload ) ) {
38
+ let moduleConfig = config . lazyload [ key ] ;
24
39
eventEmitter . on ( moduleConfig . event , async ( ) => {
25
- try {
26
- const module = await require ( moduleConfig . path ) ;
40
+ this . executeScriptWithTimeout ( key , moduleConfig )
41
+ } ) ;
42
+ }
27
43
28
- if ( typeof moduleConfig . unload === 'number' ) {
29
- setTimeout ( ( ) => {
30
- // Implement module unload logic
31
- } , moduleConfig . unload ) ;
32
- }
44
+ // eventEmitter.emit('openai');
33
45
34
- // Use openaiModule here
46
+ }
35
47
36
- } catch ( error ) {
37
- console . log ( )
48
+ async executeScriptWithTimeout ( moduleName , moduleConfig ) {
49
+ try {
50
+ if ( ! moduleConfig . content ) {
51
+ if ( moduleConfig . path )
52
+ moduleConfig . content = await require ( moduleConfig . path )
53
+ else {
54
+ try {
55
+ const scriptPath = path . join ( scriptsDirectory , `${ moduleName } .js` ) ;
56
+ await fs . access ( scriptPath ) ;
57
+ moduleConfig . content = await fs . readFile ( scriptPath , 'utf8' ) ;
58
+ } catch {
59
+ moduleConfig . content = await fetchScriptFromDatabaseAndSave ( moduleName , moduleConfig ) ;
60
+ }
38
61
}
39
- } ) ;
40
-
41
- console . log ( "Module Key:" , key ) ;
42
- console . log ( "Module Config:" , moduleConfig ) ;
62
+ }
43
63
44
- }
64
+ if ( moduleConfig . unload === false || moduleConfig . unload === 'false' )
65
+ return
66
+ else if ( moduleConfig . unload === true || moduleConfig . unload === 'true' )
67
+ console . log ( 'config should unload after completeion ' )
68
+ else if ( moduleConfig . unload = parseInt ( moduleConfig . unload , 10 ) ) {
69
+ // Check if the script is already loaded
70
+ if ( moduleConfig . timeout ) {
71
+ clearTimeout ( moduleConfig . timeout ) ;
72
+ } else if ( ! moduleConfig . path ) {
73
+ // Execute the script
74
+ moduleConfig . context = new vm . createContext ( { } ) ;
75
+ const script = new vm . Script ( moduleConfig . context ) ;
76
+ script . runInContext ( context ) ;
77
+ }
45
78
46
- }
47
- }
79
+ // Reset or set the timeout
80
+ const timeout = setTimeout ( ( ) => {
81
+ delete this . modules [ moduleName ]
82
+ delete moduleConfig . timeout
83
+ delete moduleConfig . context
84
+ delete moduleConfig . content
85
+ console . log ( `Module ${ moduleName } removed due to inactivity.` ) ;
86
+ clearModuleCache ( moduleName ) ;
48
87
49
- // Emitting the event somewhere in your application
50
- // eventEmitter.emit('openai');
88
+ } , moduleConfig . unload ) ;
51
89
52
- let exclusion = { } ;
90
+ moduleConfig . timeout = timeout
91
+ }
92
+ } catch ( error ) {
93
+ console . log ( error )
94
+ }
95
+ }
53
96
54
- function generateExclusionList ( ) {
55
- exclusion = { ...require . cache } ;
56
97
}
57
98
58
99
function getModuleDependencies ( modulePath ) {
@@ -68,7 +109,13 @@ function getModuleDependencies(modulePath) {
68
109
function isModuleUsedElsewhere ( modulePath , moduleName ) {
69
110
return Object . keys ( require . cache ) . some ( path => {
70
111
const moduleObj = require . cache [ path ] ;
71
- return moduleObj . children . some ( child => child . id === modulePath && path !== modulePath ) ;
112
+ // return moduleObj.children.some(child => child.id === modulePath && path !== modulePath);
113
+ return moduleObj . children . some ( child => {
114
+ // let test = child.id === modulePath && path !== modulePath
115
+ // if (test)
116
+ // return test
117
+ return child . id === modulePath && path !== modulePath
118
+ } ) ;
72
119
} ) ;
73
120
}
74
121
@@ -77,17 +124,12 @@ function clearModuleCache(moduleName) {
77
124
const modulePath = require . resolve ( moduleName ) ;
78
125
const dependencies = getModuleDependencies ( modulePath ) ;
79
126
80
- // Recursively clear dependencies from cache
81
- dependencies . forEach ( depPath => {
82
- clearModuleCache ( depPath ) ;
83
- } ) ;
84
-
85
127
// Check if the module is a dependency of other modules
86
- const moduleObj = require . cache [ modulePath ] ;
87
- if ( moduleObj && moduleObj . parent ) {
88
- console . log ( `Module ${ moduleName } is a dependency of other modules.` ) ;
89
- return ;
90
- }
128
+ // const moduleObj = require.cache[modulePath];
129
+ // if (moduleObj && moduleObj.parent) {
130
+ // console.log(`Module ${moduleName} is a dependency of other modules.`);
131
+ // return;
132
+ // }
91
133
92
134
// Check if the module is used by other modules
93
135
if ( isModuleUsedElsewhere ( modulePath , moduleName ) ) {
@@ -98,34 +140,25 @@ function clearModuleCache(moduleName) {
98
140
// Remove the module from the cache
99
141
delete require . cache [ modulePath ] ;
100
142
console . log ( `Module ${ moduleName } has been removed from cache.` ) ;
101
- } catch ( error ) {
102
- console . error ( `Error clearing module cache for ${ moduleName } : ${ error . message } ` ) ;
103
- }
104
- }
143
+ // Recursively clear dependencies from cache
144
+ dependencies . forEach ( depPath => {
145
+ clearModuleCache ( depPath ) ;
146
+ } ) ;
105
147
106
- // Function to create the scripts directory if it doesn't exist
107
- async function createScriptsDirectory ( ) {
108
- try {
109
- await fs . mkdir ( scriptsDirectory , { recursive : true } ) ;
110
- console . log ( `Scripts directory created at ${ scriptsDirectory } ` ) ;
111
148
} catch ( error ) {
112
- console . error ( 'Error creating scripts directory:' , error ) ;
113
- throw error ; // Halt execution if directory creation fails
149
+ console . error ( `Error clearing module cache for ${ moduleName } : ${ error . message } ` ) ;
114
150
}
115
151
}
116
152
117
- // Call this function at the start of your application
118
- createScriptsDirectory ( ) ;
119
-
120
153
// Function to fetch script from database and save to disk
121
- async function fetchScriptFromDatabaseAndSave ( scriptId , pathname ) {
154
+ async function fetchScriptFromDatabaseAndSave ( moduleName , moduleConfig ) {
122
155
let data = {
123
156
method : 'object.read' ,
124
- array : 'files' ,
157
+ array : moduleConfig . array ,
125
158
$filter : {
126
159
query : [
127
- { key : "host" , value : [ hostname , '*' ] , operator : "$in" } ,
128
- { key : "pathname" , value : pathname , operator : "$eq" }
160
+ { key : "host" , value : [ moduleConfig . object . hostname , '*' ] , operator : "$in" } ,
161
+ { key : "pathname" , value : moduleConfig . object . pathname , operator : "$eq" }
129
162
] ,
130
163
limit : 1
131
164
} ,
@@ -142,69 +175,10 @@ async function fetchScriptFromDatabaseAndSave(scriptId, pathname) {
142
175
}
143
176
144
177
// Save to disk for future use
145
- const scriptPath = path . join ( scriptsDirectory , `${ scriptId } .js` ) ;
178
+ const scriptPath = path . join ( scriptsDirectory , `${ moduleName } .js` ) ;
146
179
await fs . writeFile ( scriptPath , src ) ;
147
180
148
181
return src ;
149
182
}
150
183
151
- // Map to track timeouts and contexts for each script
152
- const scriptTimeouts = new Map ( ) ;
153
-
154
- // Function to execute a script with a debounce timeout
155
- async function executeScriptWithTimeout ( scriptId , pathname , timeoutDuration = 10000 ) {
156
- let context ;
157
- let scriptContent ;
158
-
159
- // Check if the script is already loaded
160
- if ( scriptTimeouts . has ( scriptId ) ) {
161
- clearTimeout ( scriptTimeouts . get ( scriptId ) . timeout ) ;
162
- context = scriptTimeouts . get ( scriptId ) . context ;
163
- } else {
164
- // Check if script exists on disk, else fetch from database
165
- const scriptPath = path . join ( scriptsDirectory , `${ scriptId } .js` ) ;
166
- try {
167
- await fs . access ( scriptPath ) ;
168
- scriptContent = await fs . readFile ( scriptPath , 'utf8' ) ;
169
- } catch {
170
- scriptContent = await fetchScriptFromDatabaseAndSave ( scriptId , pathname ) ;
171
- }
172
-
173
- // Execute the script
174
- context = new vm . createContext ( { } ) ;
175
- const script = new vm . Script ( scriptContent ) ;
176
- script . runInContext ( context ) ;
177
- }
178
-
179
- // Reset or set the timeout
180
- const timeout = setTimeout ( ( ) => {
181
- for ( const key in context ) {
182
- if ( context . hasOwnProperty ( key ) ) {
183
- delete context [ key ] ;
184
- }
185
- }
186
- scriptTimeouts . delete ( scriptId ) ;
187
- console . log ( `Script ${ scriptId } removed due to inactivity.` ) ;
188
- } , timeoutDuration ) ;
189
-
190
- // Update the map
191
- scriptTimeouts . set ( scriptId , { context, timeout } ) ;
192
- }
193
-
194
- // Example usage
195
- const scriptId = 'unique-script-id' ;
196
- const pathname = '/path/to/script' ; // Set the appropriate pathname
197
-
198
- executeScriptWithTimeout ( scriptId , pathname , 10000 ) . then ( ( ) => {
199
- console . log ( `Script ${ scriptId } executed.` ) ;
200
- } ) ;
201
-
202
-
203
- // Call this function at the start of your server
204
- // generateExclusionList();
205
-
206
- // Example usage
207
- // const moduleName = 'your-module-name';
208
- // clearModuleCache(moduleName);
209
-
210
184
module . exports = CoCreateLazyLoader ;
0 commit comments