@@ -3,56 +3,97 @@ const eventEmitter = new EventEmitter();
33const fs = require ( 'fs' ) . promises ;
44const path = require ( 'path' ) ;
55const vm = require ( 'vm' ) ;
6-
7- const scriptsDirectory = './scripts' ;
6+ const Config = require ( "@cocreate/config" ) ;
87
98class CoCreateLazyLoader {
109 constructor ( crud ) {
1110 this . wsManager = crud . wsManager
1211 this . crud = crud
12+ this . exclusion = { ...require . cache } ;
13+ this . modules = { } ;
1314 this . init ( )
1415 }
1516
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 )
2035 return
2136
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 ] ;
2439 eventEmitter . on ( moduleConfig . event , async ( ) => {
25- try {
26- const module = await require ( moduleConfig . path ) ;
40+ this . executeScriptWithTimeout ( key , moduleConfig )
41+ } ) ;
42+ }
2743
28- if ( typeof moduleConfig . unload === 'number' ) {
29- setTimeout ( ( ) => {
30- // Implement module unload logic
31- } , moduleConfig . unload ) ;
32- }
44+ // eventEmitter.emit('openai');
3345
34- // Use openaiModule here
46+ }
3547
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+ }
3861 }
39- } ) ;
40-
41- console . log ( "Module Key:" , key ) ;
42- console . log ( "Module Config:" , moduleConfig ) ;
62+ }
4363
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+ }
4578
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 ) ;
4887
49- // Emitting the event somewhere in your application
50- // eventEmitter.emit('openai');
88+ } , moduleConfig . unload ) ;
5189
52- let exclusion = { } ;
90+ moduleConfig . timeout = timeout
91+ }
92+ } catch ( error ) {
93+ console . log ( error )
94+ }
95+ }
5396
54- function generateExclusionList ( ) {
55- exclusion = { ...require . cache } ;
5697}
5798
5899function getModuleDependencies ( modulePath ) {
@@ -68,7 +109,13 @@ function getModuleDependencies(modulePath) {
68109function isModuleUsedElsewhere ( modulePath , moduleName ) {
69110 return Object . keys ( require . cache ) . some ( path => {
70111 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+ } ) ;
72119 } ) ;
73120}
74121
@@ -77,17 +124,12 @@ function clearModuleCache(moduleName) {
77124 const modulePath = require . resolve ( moduleName ) ;
78125 const dependencies = getModuleDependencies ( modulePath ) ;
79126
80- // Recursively clear dependencies from cache
81- dependencies . forEach ( depPath => {
82- clearModuleCache ( depPath ) ;
83- } ) ;
84-
85127 // 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+ // }
91133
92134 // Check if the module is used by other modules
93135 if ( isModuleUsedElsewhere ( modulePath , moduleName ) ) {
@@ -98,34 +140,25 @@ function clearModuleCache(moduleName) {
98140 // Remove the module from the cache
99141 delete require . cache [ modulePath ] ;
100142 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+ } ) ;
105147
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 } ` ) ;
111148 } 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 } ` ) ;
114150 }
115151}
116152
117- // Call this function at the start of your application
118- createScriptsDirectory ( ) ;
119-
120153// Function to fetch script from database and save to disk
121- async function fetchScriptFromDatabaseAndSave ( scriptId , pathname ) {
154+ async function fetchScriptFromDatabaseAndSave ( moduleName , moduleConfig ) {
122155 let data = {
123156 method : 'object.read' ,
124- array : 'files' ,
157+ array : moduleConfig . array ,
125158 $filter : {
126159 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" }
129162 ] ,
130163 limit : 1
131164 } ,
@@ -142,69 +175,10 @@ async function fetchScriptFromDatabaseAndSave(scriptId, pathname) {
142175 }
143176
144177 // Save to disk for future use
145- const scriptPath = path . join ( scriptsDirectory , `${ scriptId } .js` ) ;
178+ const scriptPath = path . join ( scriptsDirectory , `${ moduleName } .js` ) ;
146179 await fs . writeFile ( scriptPath , src ) ;
147180
148181 return src ;
149182}
150183
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-
210184module . exports = CoCreateLazyLoader ;
0 commit comments