UNPKG

7.58 kBJavaScriptView Raw
1var fs = require('fs'),
2 path = require('path'),
3 helpers = require('./helpers'),
4 async = require('async'),
5 _ = require ('underscore'),
6 logger = require('./logger')();
7
8/**
9 * Filters will be applied to a certain type to decide if that
10 * item should be included in the list to be returned.
11 * You can match extensions, do sanity checks (valid JSON), etc.
12 */
13var filters = {
14 "dashboards" : function (dashboardPath){
15 try {
16 var contentJSON = JSON.parse(fs.readFileSync(dashboardPath));
17 return (contentJSON.enabled !== false);
18 }
19 catch (e){
20 logger.error ('## ERROR ## ' + dashboardPath + ' has an invalid format or file doesn\'t exist\n');
21 return false;
22 }
23 }
24};
25
26module.exports = {
27
28 /**
29 * Returns relative path to packages path based on item type.
30 * The main purpose of this function is to be able to handle the different way
31 * widgets and jobs paths are resolved compared to the way dashboards paths are.
32 *
33 * @param {string} name item name to match. It can be namespaced. i.e: atlassian#widget1, widget1
34 * @param {string} itemType item type in plural. ('dashboards', 'jobs', 'widgets')
35 * @param {string} extension : filter result by extension
36 *
37 * @return {string} relative path to item: jobs/job1/job1.js
38 */
39
40 //TODO: refactor to remove the extension paramater
41
42 resolve_location : function (name, itemType, extension){
43 var use_directory_level = ((itemType==="widgets") || (itemType==="jobs"));
44 if (use_directory_level){
45 // jobs/job1/job1.js
46 return path.join(itemType, name, name + extension);
47 }
48 else{
49 // dashboards/dashboard.json
50 return path.join(itemType, name + extension);
51 }
52 },
53
54 /**
55 * Get the items that match the particular filter.
56 *
57 * @param {[string]} items : list of file paths
58 * @param {string} name item name to match. It can be namespaced. i.e: atlassian#widget1, widget1
59 * @param {string} itemType item type in plural. ('dashboards', 'jobs', 'widgets')
60 * @param {string} extension : filter result by extension
61 */
62
63 resolve_candidates : function(items, name, itemType, extension){
64 var searchCriteria = "";
65 if (name.indexOf("#") > -1){
66 var packageName = name.split("#")[0];
67 var itemParsedName = name.split("#")[1];
68 //package/jobs/job1/job1.js
69 searchCriteria = path.join(packageName, this.resolve_location(itemParsedName, itemType, extension));
70 }
71 else{
72 //jobs/job1/job1.js
73 searchCriteria = this.resolve_location(name, itemType, extension);
74 }
75
76 searchCriteria = path.sep + searchCriteria;
77
78 return items.filter(function(item){ return item.indexOf(searchCriteria) > -1; });
79 },
80
81 /**
82 * Return first candidate found matching name, type and extension
83 *
84 * @param {[string]} packagesPath : list of directories to find packages in.
85 * @param {string} itemName item name to match. It can be namespaced. i.e: atlassian#widget1, widget1
86 * @param {string} itemType item type in plural. ('dashboards', 'jobs', 'widgets')
87 * @param {string} extension : filter result by extension
88 */
89
90 get_first: function (packagesPath, itemName, itemType, extension, callback) {
91 var thiz = this;
92 this.get(packagesPath, itemType, extension, function(err, items){
93 if (err){ return callback(err); }
94
95 var candidates = thiz.resolve_candidates(items, itemName, itemType, extension);
96 callback(null, candidates.length ? candidates[0] : null);
97 });
98 },
99
100
101 /**
102 * Return list of items found in any package within packagesPath
103 *
104 * @param {[string]} packagesPath : list of directories to find packages in.
105 * @param {string} itemType item type in plural. ('dashboards', 'jobs', 'widgets')
106 * @param {string} extension : filter result by extension
107 */
108
109 get : function (packagesPath, itemType, extension, callback) {
110 this.getByPackage(packagesPath, itemType, extension, function (err, results){
111 if (err){ return callback(err);}
112 var items = [];
113 results.forEach(function(package){
114 items = items.concat(package.items);
115 });
116 callback(err, items);
117 });
118 },
119
120 /**
121 * Return list of items found in any package within packagesPath
122 * Items are returned separated by package
123 *
124 * @param {[string]} packagesPath : list of directories to find packages in.
125 * @param {string} itemType item type in plural. ('dashboards', 'jobs', 'widgets')
126 * @param {string} extension : filter result by extension
127 */
128
129 getByPackage : function (packagesPath, itemType, extension, callback) {
130
131 var thiz = this;
132
133 if (!Array.isArray(packagesPath)){
134 packagesPath = [packagesPath];
135 }
136
137 function readItemsFromPackageDir (dir, cb){
138 var package = {dir : dir};
139
140 var itemDir = path.join(dir, itemType);
141 if (!fs.existsSync(itemDir)){
142 package.items = [];
143 return cb(null, package);
144 }
145
146 // this functions parses:
147 // - packages/default/<itemType>/*
148 // - packages/otherpackages/<itemType>/*
149 // for dashboards, or:
150 // - packages/default/<itemType>/*/*.js
151 // - packages/otherpackages/<itemType>/*/*.js
152 // for jobs and widgets
153 fs.readdir(itemDir, function(err, items){
154 if (err){ return cb (err); }
155
156 var selected_items = [];
157 items.forEach(function(item_name){
158 var item = path.join(itemDir, item_name);
159 var stat = fs.statSync(item);
160 if (stat.isDirectory()){
161 // /job/job1/job1.js
162 item = path.join(item, item_name + extension);
163 }
164
165 if (path.extname(item) === extension){
166 if (fs.existsSync(item)){
167 selected_items.push(item);
168 }
169 }
170 });
171
172 if (filters[itemType]){ // change to use custom filters for itemType
173 selected_items = selected_items.filter(filters[itemType]);
174 }
175
176 package.items = selected_items;
177 return cb(null, package);
178 });
179 }
180
181
182 // this function read all the packages from the provided directory packagesPath:
183 // - packages/default/*
184 // - packages/otherpackages/*
185 // and calls readItemsFromPackageDir for every one of them
186
187 function fillPackages (packagesPath, cb){
188 fs.readdir(packagesPath, function(err, allPackagesDir){
189 if (err){ return cb(err); }
190
191 // convert to absolute path
192 allPackagesDir = allPackagesDir.map(function(partialDir){
193 return path.join(packagesPath, partialDir);});
194
195 // get only valid directories
196 allPackagesDir = allPackagesDir.filter(function(dir){
197 return fs.statSync(dir).isDirectory();});
198
199 // read items from every package and flatten results
200 async.map (allPackagesDir, readItemsFromPackageDir, function(err, results){
201 if (err){
202 return cb(err);
203 }
204 cb(err, _.flatten(results));
205 });
206 });
207 }
208
209 // loop over all the packages paths, call fillPackages to get the right files on them
210 // and then flatten the results in a single array
211 async.map (packagesPath.filter(fs.existsSync), fillPackages, function(err, results){
212 if (err){ return callback(err); }
213 callback(null, _.flatten(results));
214 });
215 }
216};
\No newline at end of file