1 | var path = require('path'); |
||
2 | var Promise = require('bluebird'); |
||
3 | var fs = Promise.promisifyAll(require('fs-extra')); |
||
4 | var logger=require('AppFramework.js').logger; |
||
5 | |||
6 | /* Closure private functions for script */ |
||
7 | function getFilter(ext) { |
||
8 | return function(filename) { |
||
9 | return filename.match(new RegExp('\\.' + ext + '$', 'i')); |
||
10 | }; |
||
11 | } |
||
12 | |||
13 | |||
14 | class PluginLoader |
||
0 ignored issues
–
show
Backwards Compatibility
introduced
by
![]() |
|||
15 | { |
||
16 | constructor(dir, shareDir, deps, options) |
||
17 | { |
||
18 | // State variables updated by the resource finding functions |
||
19 | var result = { |
||
20 | assets: [], |
||
21 | scripts: [], |
||
22 | styles: [], |
||
23 | plugins: [], |
||
24 | applets: [], |
||
25 | webcomponents: [] |
||
26 | }; |
||
27 | var rawdata = {}; |
||
28 | var publicAssets; |
||
29 | var filter = options.filter; |
||
30 | var required = options.required; |
||
31 | var cacheFile = options.cacheFile; |
||
32 | var pluginName; |
||
33 | var extend = require('util')._extend; |
||
34 | //These functions are intended to be bound to the overall state of the loadPlugins method |
||
35 | |||
36 | var instantiatePlugins = function instantiatePlugins(plugins) |
||
37 | { |
||
38 | return Promise.map(plugins, function(plugin) |
||
39 | { |
||
40 | logger.debug( "PLUGIN MAP LOAD:" + plugin ); |
||
41 | |||
42 | return Promise.try( () => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
43 | { |
||
44 | var newdeps = extend({},deps); |
||
45 | newdeps.logger = deps.logger.child({plugin:plugin}); |
||
46 | deps.logger.monitor(newdeps.logger,path.join(dir, plugin, 'logging.json')); |
||
47 | try{ |
||
48 | return require(path.join(dir, plugin))(plugin, deps); |
||
49 | } catch(ex){ |
||
50 | logger.error(ex); |
||
51 | throw ex; |
||
52 | } |
||
53 | } ) |
||
54 | .then( ( pluginInstance ) => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
55 | { |
||
56 | // Check to see if plugin's index.js was loaded |
||
57 | if( pluginInstance === undefined ) |
||
58 | { |
||
59 | throw new Error('Plugin:' + plugin + ' is invalid, does not return a plugin object'); |
||
60 | } |
||
61 | |||
62 | pluginInstance.name = plugin; |
||
63 | pluginInstance._raw = rawdata[plugin]; |
||
64 | result.plugins.push( pluginInstance ); |
||
65 | } ); |
||
66 | }); |
||
67 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
68 | |||
69 | var derivePluginNamesfromCrawlingFoldersAsync = function derivePluginNamesfromCrawlingFoldersAsync() { |
||
70 | return fs.readdirAsync(dir) |
||
71 | .filter(function(file) { |
||
72 | // Apply an optional filter function if it exists |
||
73 | if (filter !== undefined && filter(file) === false) { |
||
74 | return false; |
||
75 | } |
||
76 | return true; |
||
77 | }) |
||
78 | .then(function(dirs){ |
||
79 | return dirs; |
||
80 | }) |
||
81 | .filter(function(file){ |
||
82 | // Check to see if the file is a directory |
||
83 | return fs.statAsync(path.join(dir, file)) |
||
84 | .then(function(stat) { |
||
85 | return stat.isDirectory(); |
||
86 | }) |
||
87 | .catch(function(err) { |
||
88 | return false; |
||
89 | }); |
||
90 | }) |
||
91 | .then(function(dirs){ |
||
92 | return dirs; |
||
93 | }) |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
94 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
95 | |||
96 | var findAppletsAsync = function findAppletsAsync(){ |
||
97 | return fs.readdirAsync(path.join(dir, pluginName)) |
||
98 | .filter(getFilter('ejs')) |
||
99 | .each(function(ejs) { |
||
100 | result.applets.push(dir + '/' + pluginName + '/' + ejs); |
||
101 | var ejsicon = path.join(dir, pluginName, ejs + '.icon'); |
||
102 | // Handle ejs files, with and without icons |
||
103 | return fs.statAsync(ejsicon) |
||
104 | .then(function() { |
||
105 | // Push applet with ejs and icon |
||
106 | rawdata[pluginName].applets.push({ |
||
107 | path: dir + '/' + pluginName + '/' + ejs, |
||
108 | icon: ejsicon |
||
109 | }); |
||
110 | }) |
||
111 | .catch(function(err) { |
||
112 | // Icon file didn't exist, just push ejs |
||
113 | rawdata[pluginName].applets.push({ |
||
114 | path: dir + '/' + pluginName + '/' + ejs |
||
115 | }); |
||
116 | }); |
||
117 | }) |
||
118 | .catch(function(err) {}); |
||
119 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
120 | |||
121 | var findPublicWebFoldersAsync = function findPublicWebFoldersAsync(){ |
||
122 | publicAssets = path.join(dir, pluginName, 'public'); |
||
123 | return fs.statAsync(publicAssets) |
||
124 | .then(function() { |
||
125 | // Add public assets to a static route |
||
126 | result.assets.push({ |
||
127 | path: shareDir + '/' + pluginName, |
||
128 | assets: publicAssets |
||
129 | }); |
||
130 | rawdata[pluginName].assets.push({ |
||
131 | path: shareDir + '/' + pluginName, |
||
132 | assets: publicAssets |
||
133 | }); |
||
134 | }) |
||
135 | .catch(function(err) {}); |
||
136 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
137 | |||
138 | var findPublicJSResourcesAsync = function findPublicJSResourcesAsync(){ |
||
139 | var js = path.join(publicAssets, 'js'); |
||
140 | return fs.statAsync(js) |
||
141 | .then(function() { |
||
142 | return fs.readdirAsync(js) |
||
143 | .filter(getFilter('js')) |
||
144 | .each(function(script) { |
||
145 | // Add js assets |
||
146 | result.scripts.push(shareDir + '/' + pluginName + '/js/' + script); |
||
147 | rawdata[pluginName].scripts.push(shareDir + '/' + pluginName + '/js/' + script); |
||
148 | }); |
||
149 | }) |
||
150 | .catch(function(err) {}); |
||
151 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
152 | |||
153 | var findPublicCSSResoucesAsync = function findPublicCSSResoucesAsync(){ |
||
154 | var css = path.join(publicAssets, 'css'); |
||
155 | return fs.statAsync(css) |
||
156 | .then(function() { |
||
157 | return fs.readdirAsync(css) |
||
158 | .filter(getFilter('css')) |
||
159 | .each(function(style) { |
||
160 | // Add css assets |
||
161 | result.styles.push(shareDir + '/' + pluginName + '/css/' + style); |
||
162 | rawdata[pluginName].styles.push(shareDir + '/' + pluginName + '/css/' + style); |
||
163 | }); |
||
164 | }) |
||
165 | .catch(function(err) {}); |
||
166 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
167 | |||
168 | var findWebcomponentResourcesAsync = function findWebcomponentResourcesAsync(){ |
||
169 | var wcAssets = path.join(dir, pluginName, 'public/webcomponents'); |
||
170 | return fs.statAsync(wcAssets) |
||
171 | .then(function() { |
||
172 | result.assets.push({ |
||
173 | path: 'components' + '/' + pluginName, |
||
174 | assets: wcAssets |
||
175 | }); |
||
176 | rawdata[pluginName].assets.push({ |
||
177 | path: 'components' + '/' + pluginName, |
||
178 | assets: wcAssets |
||
179 | }); |
||
180 | return fs.readdirAsync(wcAssets) |
||
181 | .filter(getFilter('html')) |
||
182 | .each(function(wc) { |
||
183 | // Add wc assets |
||
184 | // TODO: Make clear documentation that the filename must = the component name as a convention OR |
||
185 | // update this code to parse the wc file and pull out the is: property |
||
186 | result.webcomponents.push({ |
||
187 | path: path.join('components/', pluginName, wc) |
||
188 | }); |
||
189 | }); |
||
190 | }) |
||
191 | .catch(function(err) {}); |
||
192 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
193 | |||
194 | var findBowerResourcesAsync = function findBowerResourcesAsync(){ |
||
195 | var bowerAssets = path.join(dir, pluginName, 'public/bower_components'); |
||
196 | return fs.statAsync(bowerAssets) |
||
197 | .then(function() { |
||
198 | result.assets.push({ |
||
199 | path: 'components', |
||
200 | assets: bowerAssets |
||
201 | }); |
||
202 | rawdata[pluginName].assets.push({ |
||
203 | path: 'components', |
||
204 | assets: bowerAssets |
||
205 | }); |
||
206 | }) |
||
207 | .catch(function(err) {}); |
||
208 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
209 | |||
210 | /** |
||
211 | * Return an array of resources in each plugin folder |
||
212 | */ |
||
213 | this.crawlPluginFolders= function crawlPluginFolders() { |
||
214 | |||
215 | |||
216 | // State variables updated by the resource finding functions |
||
217 | result = { |
||
218 | assets: [], |
||
219 | scripts: [], |
||
220 | styles: [], |
||
221 | plugins: [], |
||
222 | applets: [], |
||
223 | webcomponents: [] |
||
224 | }; |
||
225 | rawdata = {}; |
||
226 | publicAssets = ""; |
||
227 | |||
228 | return derivePluginNamesfromCrawlingFoldersAsync() |
||
229 | .then(function(r){ |
||
230 | return r; |
||
231 | }) |
||
232 | .each(function(_pluginName){ |
||
233 | pluginName = _pluginName |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
234 | //given the plugin, find all related assets and update function shared state variables |
||
235 | //by binding to this, we should have access to the function scrope |
||
236 | rawdata[pluginName]={ |
||
237 | assets: [], |
||
238 | scripts: [], |
||
239 | styles: [], |
||
240 | plugins: [], |
||
241 | applets: [], |
||
242 | webcomponents: [] |
||
243 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
244 | return Promise.all( |
||
245 | [ |
||
246 | findAppletsAsync(), |
||
247 | findPublicWebFoldersAsync(), |
||
248 | findPublicJSResourcesAsync(), |
||
249 | findPublicCSSResoucesAsync(), |
||
250 | findWebcomponentResourcesAsync(), |
||
251 | findBowerResourcesAsync() |
||
252 | ] |
||
253 | ) |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
254 | }) |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
255 | |||
256 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
257 | |||
258 | this.loadPluginsAsync = function(loadedPlugins) |
||
259 | { |
||
260 | var self=this; |
||
261 | return Promise.try(function(){ |
||
262 | var cache = {}; |
||
263 | try{ |
||
264 | //TODO: When in production, make sure that updates to the environme |
||
265 | if (process.env.IGNORE_CACHE == "true") { |
||
266 | throw new Error("Only load cache in production") |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
267 | } |
||
268 | cache = require(cacheFile); |
||
269 | result = cache.result; |
||
270 | rawdata = cache.rawdata; |
||
271 | return cache.plugins; |
||
272 | }catch(e){ |
||
273 | //regenerate the cache if missing |
||
274 | return self.crawlPluginFolders() |
||
275 | .then(function(plugins){ |
||
276 | cache.result = result; |
||
277 | cache.plugins = plugins; |
||
278 | cache.rawdata = rawdata; |
||
279 | fs.writeFile(cacheFile, JSON.stringify(cache), 'utf8'); |
||
280 | return plugins; |
||
281 | }) |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
282 | } |
||
283 | |||
284 | |||
285 | }) |
||
286 | .then(function(plugins){ |
||
287 | return instantiatePlugins(plugins) //intentionally kick off without a callback |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
288 | }) |
||
289 | .then(function(){ |
||
290 | return result; |
||
291 | }) |
||
292 | .then( (plugins) => |
||
0 ignored issues
–
show
'arrow function syntax (=>)' is only available in ES6 (use 'esversion: 6').
Generally using ECMAScript 6 specific syntax is fine if you are sure that it is already supported by all engines which are supposed to run this code. Further Reading: ![]() |
|||
293 | { |
||
294 | loadedPlugins = loadedPlugins.concat( [ plugins ] ); |
||
295 | return loadedPlugins; |
||
296 | }) |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
297 | } |
||
0 ignored issues
–
show
There should be a semicolon.
Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers. Further Readings: ![]() |
|||
298 | |||
299 | } |
||
300 | |||
301 | flushCache(){ |
||
302 | |||
303 | } |
||
304 | |||
305 | } |
||
306 | |||
307 | |||
308 | |||
309 | module.exports = function(dir, shareDir, deps, options) |
||
310 | { |
||
311 | return new PluginLoader(dir, shareDir, deps, options); |
||
312 | }; |