UNPKG

datacraft

Version:

LINQ-like JavaScript object query library. No dependencies. Works in all environments.

1 lines 5.16 kB
function clone(source,target,breakCircular,trace){if(source===null||source===undefined||source.valueOf()===source&&source.constructor!==Object&&!Array.isArray(source))return target=source;let seed,key,prop,circularReference;if(!target){if(source.constructor===Date)seed=source.getTime();else if(!(Array.isArray(source)||source.constructor===Object))seed=source}target=target||new source.constructor(seed);trace=trace||new WeakMap;for(key in source){prop=source[key];if(!(key in source)||!Object.prototype.hasOwnProperty.call(source,key)||!Object.getOwnPropertyDescriptor(source,key).writable)continue;circularReference=trace.get(prop);if(circularReference){if(!breakCircular){target[key]=circularReference;continue}else{target[key]="[Circular]";continue}}if(prop!==null&&prop!==undefined&&(Array.isArray(prop)||prop.constructor===Object)){trace.set(prop,target[key]=Array.isArray(prop)?Object.assign([],target[key]):Object.assign({},target[key]))}target[key]=clone(prop,target[key],breakCircular,trace)}return target}function validate(obj,allowedFields,requiredFields){const objectKeys=new Set(Object.keys(obj));if(allowedFields){const allowedSet=new Set(allowedFields);objectKeys.forEach(k=>{if(!allowedSet.has(k)){throw new Error("Field '"+k+"' is not an allowed property of validated object.")}})}if(requiredFields){const requiredSet=new Set(requiredFields);requiredSet.forEach(r=>{if(!objectKeys.has(r)){throw new Error("Required field '"+r+"' is not present in validated object.")}})}return true}class DataSet{constructor(options){this.entries=[];this.options={allowedFields:null,requiredFields:null};if(options){validate(options,Object.keys(this.options));this.options=clone(options,this.options)}}insert(inData){if(Array.isArray(inData)){inData.forEach(v=>{if(this.options.allowedFields||this.options.requiredFields){validate(v,this.options.allowedFields,this.options.requiredFields)}this.entries.push(v)})}else{throw new TypeError("DataSet: Parameter to insert must be an array.")}return this}update(o,whereFn){if(this.options.allowedFields||this.options.requiredFields){validate(o,this.options.allowedFields,this.options.requiredFields)}this.toArray(whereFn).forEach(e=>{let oCopy=clone(o,e);e=oCopy});return this}drop(fieldName){this.entries.forEach(e=>delete e[fieldName]);return this}join(oDs,target,conditionCb){this.entries.forEach(localObj=>{const matches=[];oDs.entries.forEach(remoteObj=>{if(conditionCb(localObj,remoteObj)){matches.push(remoteObj)}});localObj[target]=matches});return this}joinFirst(oDs,target,conditionCb){this.entries.forEach(localObj=>{oDs.entries.forEach(remoteObj=>{if(conditionCb(localObj,remoteObj)){localObj[target]=remoteObj}})});return this}copy(){return new DataSet(clone(this.entries))}reduce(conditionCb){this.entries=this.filter(conditionCb);return this}toArray(conditionCb){return conditionCb?this.entries.filter(conditionCb):this.entries}first(conditionCb){const result=this.filter(conditionCb);return result.length>=1?result[0]:undefined}groupBy(groupByFieldsInput,outputFieldName){let groupByFields=Array.isArray(groupByFieldsInput)?groupByFieldsInput:[groupByFieldsInput],outputMap={},output=[];this.entries.forEach(localObj=>{let currentOutputObj=outputMap;groupByFields.forEach(f=>{let fieldValue=localObj[f]!==undefined?localObj[f]:"undefined";if(currentOutputObj[fieldValue]===undefined){currentOutputObj[fieldValue]={field:f,value:fieldValue,children:{}}}currentOutputObj=currentOutputObj[fieldValue].children});if(Array.isArray(currentOutputObj[outputFieldName])){currentOutputObj[outputFieldName].push(localObj)}else{currentOutputObj[outputFieldName]=[localObj]}});const rebuildResults=(currentLevel,trail)=>{trail=Object.assign({},trail)||{};Object.values(currentLevel).forEach(currentItem=>{if(Array.isArray(currentItem)){trail[outputFieldName]=currentItem;output.push(trail)}else{trail[currentItem.field]=currentItem.value;rebuildResults(currentItem.children,trail)}})};rebuildResults(outputMap);return new DataSet(output)}total(outputFieldName){let newEntry={};newEntry[outputFieldName]=this.entries;return new DataSet([newEntry])}avg(field,outputFieldName,mapCb){this.entries.forEach(e=>{const data=e[field].map(mapCb);e[outputFieldName]=data.reduce((a,b)=>a+b,0)/data.length});return this}sum(field,outputFieldName,mapCb){this.entries.forEach(e=>{e[outputFieldName]=e[field].map(mapCb).reduce((a,b)=>a+b,0)});return this}min(field,outputFieldName,mapCb){this.entries.forEach(e=>{e[outputFieldName]=Math.min(...e[field].map(mapCb))});return this}max(field,outputFieldName,mapCb){this.entries.forEach(e=>{e[outputFieldName]=Math.max(...e[field].map(mapCb))});return this}countd(field,outputFieldName,mapCb){this.entries.forEach(e=>{const data=e[field].map(mapCb);e[outputFieldName]=new Set(data).size});return this}count(field,outputFieldName,mapCb){this.entries.forEach(e=>{e[outputFieldName]=e[field].map(mapCb).length});return this}calc(outputFieldName,calcCb){this.entries.forEach(e=>{e[outputFieldName]=calcCb(e)});return this}autonumber(outputFieldName){let current=0;this.entries.forEach(e=>{e[outputFieldName]=current++});return this}}export{DataSet,clone,DataSet as default,validate};