275 lines
6.6 KiB
JavaScript
275 lines
6.6 KiB
JavaScript
'use strict';
|
|
const fs = require('fs');
|
|
|
|
function Parser(options) {
|
|
var self = this;
|
|
|
|
options = options || {};
|
|
|
|
function debug(message) {
|
|
if (self.params.debug_mode) {
|
|
console.log(`[DEBUG] ${message}`);
|
|
}
|
|
}
|
|
|
|
this.defaults = {
|
|
path : './data.json',
|
|
query_delim : '/',
|
|
debug_mode : false
|
|
}
|
|
|
|
this.params = Object.assign({}, self.defaults, options);
|
|
|
|
this.data = null;
|
|
|
|
this.test = {
|
|
'valid_deal' : function(query) {
|
|
return self.get.deals(query)
|
|
.then(function(data) {
|
|
if (query == "") return false;
|
|
if (data.length > 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
})
|
|
},
|
|
'valid_cluster' : function(query) {
|
|
return self.test.has_hosts(query)
|
|
},
|
|
'valid_host' : function(query) {
|
|
return self.test.has_hosts(query)
|
|
},
|
|
'has_hosts' : function(query) {
|
|
return self.get.hosts(query)
|
|
.then(host_list => {
|
|
if (query == "") return false;
|
|
debug("Host list: "+host_list);
|
|
if (host_list.length > 0) {
|
|
return true;
|
|
}
|
|
return false;
|
|
})
|
|
},
|
|
'is_object' : function(obj) {
|
|
return (typeof obj === 'object' && obj !== null);
|
|
}
|
|
}
|
|
|
|
this.xform = {
|
|
'query_str_to_arr' : function(str = "") {
|
|
if (!str || str == "" || str == '') {
|
|
debug("Transforming empty search string.");
|
|
return [];
|
|
}
|
|
var arr = str.split(self.params.query_delim);
|
|
var split_str=""
|
|
arr.forEach(term => {
|
|
split_str = split_str + " " + term;
|
|
})
|
|
arr = split_str.split(" ");
|
|
arr = arr.filter(term => term != '.');
|
|
arr = arr.filter(term => term != '');
|
|
debug("Query arr: "+arr);
|
|
return arr;
|
|
}
|
|
}
|
|
|
|
this.reduce = {
|
|
'once' : function(data = {},name = "") {
|
|
const addressed = self.address(data,[...name]);
|
|
return addressed.data;
|
|
},
|
|
'fuzzy' : function(data = {},names = []) {
|
|
if (!Array.isArray(names) || names.length < 1) {
|
|
return data;
|
|
}
|
|
var name = names.shift();
|
|
var result = self.reduce.once(data,name);
|
|
names.forEach(name => { result = [...result.map(tree => {
|
|
const matches = self.reduce.once(tree,name)
|
|
debug(matches);
|
|
return matches;
|
|
})]})
|
|
result.filter(obj => obj);
|
|
return result;
|
|
},
|
|
'exact' : function(data = {},names = []) {
|
|
if (!Array.isArray(names) || names.length < 1) {
|
|
return data;
|
|
}
|
|
const addressed = self.address(data,names);
|
|
debug("Reduced exact data: "+addressed);
|
|
return addressed.data;
|
|
}
|
|
}
|
|
|
|
this.address = function(data = {},names = []) {
|
|
if (!names || names.length < 1 || !data || data == {}) {
|
|
debug("nope");
|
|
return { paths: [['.']], data: [data] };
|
|
}
|
|
var match_paths = new Array();
|
|
var match_data = new Array();
|
|
var branches = new Array({
|
|
root: ".",
|
|
data: data
|
|
});
|
|
for(var i=0; i < branches.length; i++) {
|
|
const data = branches[i].data;
|
|
const root = branches[i].root;
|
|
for (const [name,value] of Object.entries(data)) {
|
|
if (self.test.is_object(value)) {
|
|
branches.push({
|
|
root: [...root,name],
|
|
data: value
|
|
});
|
|
}
|
|
if (name == names[0]) {
|
|
var match = data;
|
|
names.forEach(term => {
|
|
debug("Searching for term: "+term);
|
|
if (match && match[term]) {
|
|
match = match[term];
|
|
}
|
|
else { match = undefined }
|
|
});
|
|
if (match) {
|
|
const match_path=[...root]
|
|
match_paths.push(match_path)
|
|
match_data.push(match)
|
|
debug("match found:" +match_path+"; "+match);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return { paths: match_paths, data: match_data };
|
|
}
|
|
|
|
this.get = {
|
|
'raw' : function(){
|
|
return new Promise(function(resolve, reject){
|
|
if(!self.data){
|
|
fs.readFile(
|
|
self.params.path,
|
|
function(err, data) {
|
|
if(err) reject(err);
|
|
try {
|
|
JSON.parse(data);
|
|
self.data = JSON.parse(data)
|
|
resolve(self.data)
|
|
} catch(err){
|
|
reject(err)
|
|
}
|
|
}
|
|
)
|
|
} else {
|
|
resolve(self.data);
|
|
}
|
|
})
|
|
},
|
|
'reduced' : function(names = [],ascent = [],descent = []) {
|
|
return self.get.raw().then(entire_data => {
|
|
debug(`ascent: ${ascent}`);
|
|
debug(`names: ${names}`);
|
|
debug(`descent: ${descent}`);
|
|
if (names.length+ascent.length+descent.length<1) {
|
|
return entire_data;
|
|
}
|
|
const domain = self.reduce.fuzzy(entire_data,ascent);
|
|
const fence = self.reduce.exact(domain,names);
|
|
const product = self.reduce.fuzzy(fence,descent);
|
|
return product;
|
|
//return self.reduce.exact(entire_data,names);
|
|
})
|
|
},
|
|
'addressed' : function(names) {
|
|
return self.get.raw().then(entire_data => {
|
|
debug(`Addressing raw: ${JSON.stringify(names)}`);
|
|
return self.address(entire_data,names);
|
|
})
|
|
},
|
|
'deals' : function(query){
|
|
return self.get.addressed(
|
|
[...(self.xform.query_str_to_arr(query)),"repo"]
|
|
).then(addressed => { return addressed.paths; })
|
|
},
|
|
'hosts' : function(query){
|
|
return self.get.addressed(
|
|
[...(self.xform.query_str_to_arr(query))]
|
|
).then(cluster_data => {
|
|
debug("Cluster search data: "
|
|
+JSON.stringify(cluster_data))
|
|
const host_matches = cluster_data.data.map(data =>{
|
|
debug("Data in cluster: "+JSON.stringify(data))
|
|
const hosts = self.address(
|
|
data,
|
|
["remote","host"]
|
|
);
|
|
return hosts.paths;
|
|
})
|
|
return host_matches;
|
|
})
|
|
},
|
|
'host_list': function(query) {
|
|
return self.get.hosts(query).then(paths => {
|
|
const host_list = paths.map(path_list => {
|
|
const return_queries = path_list.map(path_arr => {
|
|
var query_str = "";
|
|
path_arr = path_arr.filter(e => e != '.');
|
|
path_arr.forEach(e => { query_str += e+" "; })
|
|
return query_str.trim();
|
|
})
|
|
return return_queries;
|
|
})
|
|
return host_list;
|
|
})
|
|
},
|
|
'root' : function(query){
|
|
return self.get.addressed(
|
|
[...(self.xform.query_str_to_arr(query))]
|
|
).then(addressed => { return addressed.paths; })
|
|
},
|
|
'path' : function(query) {
|
|
return self.get.root(query).then(roots => {
|
|
var paths = new Array();
|
|
debug(`Roots found: ${roots}`);
|
|
roots.forEach (
|
|
function(root, i, array) {
|
|
var str = "";
|
|
debug(`Formatting ${root}`);
|
|
root.forEach(
|
|
function(key,j,arr) {
|
|
debug(`${j}: ${key}`);
|
|
str = str + "/" + key;
|
|
}
|
|
)
|
|
debug(str);
|
|
var query_arr = query.split(" ");
|
|
query_arr.forEach(
|
|
function(term,j,arr) {
|
|
str = str + "/" + term;
|
|
})
|
|
str = str.slice(3)
|
|
paths.push(str);
|
|
}
|
|
);
|
|
return paths;
|
|
})
|
|
},
|
|
'cluster_data' : function(query) {
|
|
return self.get.reduced(
|
|
self.xform.query_str_to_arr(query),
|
|
["clusters"],
|
|
["ports","ssh"]
|
|
).then(data => { return data; })
|
|
},
|
|
'data' : function(query) {
|
|
return self.get.reduced(
|
|
self.xform.query_str_to_arr(query)
|
|
).then(data => { return data; })
|
|
}
|
|
}
|
|
};
|
|
|
|
module.exports = Parser;
|