js-lightning
Version:
Direct Javascript to Web interpreted server inspired by PHP
261 lines (219 loc) • 6.55 kB
JavaScript
const commonFunctions = {
universalAddToPrototype: (commonFunctions, functionObject) => {
let methods = [];
let documentation = [];
let methodName;
let testList = [];
functionObject.forEach((functionItem, inx) => {
methodName = inx;
const supportedTypeList = functionItem.supportedTypeList
.map(item => item.toString().replace(/^function (.*?)\(.*$/, '$1'))
.join(', ')
.replace(/, $/, '');
if (functionItem.test && typeof functionItem.test == 'function') {
testList.push({ methodName, test: functionItem.test });
}
methods.push(methodName);
documentation.push({
name: methodName,
description: `${methodName}: ${functionItem.description}`,
supportedTypeList
});
functionItem.supportedTypeList.forEach(target => {
if (typeof target.prototype[methodName] == 'undefined') {
Object.defineProperty(target.prototype, methodName, {
value: functionItem.method(commonFunctions),
writable: false,
enumerable: false
});
}
});
});
const testActual=methodName=>(args) => {
const tmp = testList.reduce((passingTests, testItem, inx) => {
if (typeof(args.methodList)!='undefined' && args.methodList.length>0 && !args.methodList.includes(methodName)){
return true;
}
const result=passingTests && testItem.test(args) ? true : false;
if (args.listTests){
console.log(`${methodName} ${result?'passed':'failed'}`);
}
return result //calls test method passed from functional module
}, true);
return tmp;
};
const test = testActual(methodName);
return {
methods,
documentation,
test
};
},
callerName: (calledFromQtLib = false, options={}) => {
if (typeof(options)!='object'){
throw(`qtools-functional-library.js internal error: options must be an object, got '${options}'`);
}
options.suffixCallStackDepth=options.suffixCallStackDepth?options.suffixCallStackDepth:3;
const index = calledFromQtLib ? options.suffixCallStackDepth : 2; //the 1 might need adjusting once this is made available to applications
return new Error().stack
.split(/\n/)[index]
.trim()
.replace(/at new moduleFunction/, "called from")
.replace(/Object\.<anonymous>/, 'not_in_function');
},
toType: function(obj) {
if (obj instanceof Map) {
return 'map';
}
if (obj instanceof Set) {
return 'set';
}
if (typeof obj == 'string') {
return 'string';
}
if (typeof obj == 'number') {
return 'number';
}
if (typeof obj == 'obj' && typeof length == 'number') {
return 'array';
}
if (obj === null) {
return 'null';
}
if (typeof obj == 'undefined') {
return 'undefined';
}
if (typeof obj == 'string') {
return 'string';
}
return {}.toString
.call(obj)
.match(/\s([a-z|A-Z]+)/)[1]
.toLowerCase();
},
byObjectProperty: function(fieldName, transformer) {
//called: resultArray=someArray.sort(qtools.byObjectProperty('somePropertyName'));
//based on closure of fieldName
var fullNameSort;
return (fullNameSort = function(a, b) {
var localFieldName = fieldName;
var localTransformer = transformer;
//for debug
if (typeof fieldName == 'function') {
var aa = a;
var bb = b;
transformer = fieldName;
} else {
var aa = a.qtGetSurePath(fieldName);
var bb = b.qtGetSurePath(fieldName);
}
if (typeof transformer == 'function') {
aa = transformer(aa);
bb = transformer(bb);
} else if (transformer) {
switch (transformer) {
case 'caseInsensitive':
aa = aa.toLowerCase();
bb = bb.toLowerCase();
break;
default:
console.log(
'qt.byObjectProperty says, No such transformer as: ' + transformer
);
break;
}
}
if (!bb && !aa) {
return 0;
}
if (!bb) {
return -1;
}
if (!aa) {
return 1;
}
if (aa > bb) {
return 1;
}
if (aa < bb) {
return -1;
}
return 0;
});
},
isSupportedType: (input, supportedTypeList) =>
supportedTypeList.reduce((result, supportedTypeItem) => {
return (
result || Object.getPrototypeOf(input) === supportedTypeItem.prototype
); //instoanceof does not work for strings and numbers
}, false)
};
// Array.prototype.remove = function(from, to) {
// var rest = this.slice((to || from) + 1 || this.length);
// this.length = from < 0 ? this.length + from : from;
// return this.push.apply(this, rest);
// };
String.prototype.toCamelCase = function(delimiter, pascalCase) {
var firstCharFunction = pascalCase
? function(v) {
return v.toUpperCase();
}
: function(v) {
return v.toLowerCase();
};
delimiter = delimiter ? delimiter : ' ';
return this.split(delimiter)
.map(function(word) {
var first = word.substring(0, 1);
word = word.replace(new RegExp(first), first.toUpperCase());
return word;
})
.join('')
.replace(/^(.)/, firstCharFunction);
};
const docList = [];
const testList = [];
const addMorePrototypes = () => {
const fs = require('fs');
const path = require('path');
const libDir = path.join(path.dirname(module.filename), 'lib');
const dirList = fs.readdirSync(libDir);
dirList.forEach(item => {
if (item.match(/^qtools/)) {
const moduleGen = require(path.join(libDir, item));
const module = new moduleGen({ commonFunctions });
const result = module.addToPrototype();
result.documentation && docList.push(result.documentation);
result.test && testList.push(result.test);
}
});
};
addMorePrototypes();
const helpActual = docList => (queryString = '') => {
//someday turn this into a report instead of a JSON dump, add support for item.suppressHelpListing for qtLog_AddCallableMethods
let outList;
if (!queryString) {
outList = docList;
} else {
outList = docList.filter(item => {
const regex = new RegExp(queryString, 'i');
const result = JSON.stringify(item).match(regex);
return result;
});
}
// const util=require('util');
// util.inspect(docList, { depth: null, maxArrayLength: null }).qtDump('qtFuncionalLib Documentation');
return outList;
};
const testActual = testList => (args={}) => {
return testList.reduce((result, test) => {
if (typeof test == 'function') {
result = test(args) && result; //executes the framework testItem.test() above
}
return result;
}, true);
};
commonFunctions.qtLog_AddCallableMethods("what part of 'not for civilian use' is unclear?");
commonFunctions.help = helpActual(docList);
commonFunctions.test = testActual(testList);
module.exports = commonFunctions;