json-faker
Version:
This application creates json with fake contextual data. It takes input as a template.
242 lines (214 loc) • 8.11 kB
JavaScript
var faker = require('faker');
var fs = require('fs');
class JsonFaker {
constructor() {
this.validValueTypes = ['object', 'json', 'jsonString'];
this.fileList = [];
this.userTemplate = {};
}
process(content, userTemplate) {
this.userTemplate = userTemplate;
var inputType = this._getInputType(content);
if (!this.validValueTypes.includes(inputType)) return 'Invalid input data';
if (inputType === 'json') this.fileList.push(content);
var jsonObj = this._getJsonObj(content, inputType);
if (jsonObj === 'Invalid input') return jsonObj;
var getReturnData = this._generateMock(jsonObj);
return getReturnData;
};
post(inputArg) {
return this._createResponse(inputArg);
};
put(inputArg) {
return this._createResponse(inputArg);
};
delete(inputArg) {
return this._createResponse(inputArg);
};
_createResponse(inputObj) {
if (typeof inputObj !== 'object') inputObj = {
message: 'Invalid input'
};
else inputObj['id'] = faker.random.uuid();
return inputObj;
};
_getInputType(input) {
if(input == null) return null;
if (typeof input === 'string') {
input = this._processTemplate(input, typeof input);
var fileExtension = input.split('.').pop();
if (fileExtension === 'json') { // file type json
return fileExtension;
} else if (this._IsJsonString(input)) { // input string json object
return 'jsonString';
} else return 'string';
} else if (input.constructor === Array) return 'array';
else return typeof input;
};
_getJsonObj(input, inputType) {
if (inputType === 'object') return input;
var getContents = this._processTemplate(input, inputType);
if (inputType === 'json') {
try {
return JSON.parse(getContents);
} catch (e) {
return 'Invalid input';
}
}
if (inputType === 'jsonString') {
return JSON.parse(getContents);
}
};
_readArray(inputArray) {
var newArray = [];
var self = this;
inputArray.forEach(function(element) {
var valueType = self._getInputType(element);
if (valueType === 'number') newArray.push(element);
if (valueType === 'string') {
let stringProcess = self._stringProcessing(element);
newArray.push(self._getFakerData(stringProcess));
}
if (valueType === 'object') newArray.push(self._generateMock(element));
});
return newArray;
};
_generateMock(inputJson) {
var returnData = {};
var self = this;
for (var property in inputJson) {
if (inputJson.hasOwnProperty(property)) {
var valueType = self._getInputType(inputJson[property]);
if (valueType === null) returnData[property] = null;
else if (valueType === 'string') {
let stringProcess = self._stringProcessing(inputJson[property]);
returnData[property] = self._getFakerData(stringProcess);
} else if (valueType === 'number') {
returnData[property] = inputJson[property];
} else if (valueType === 'object') {
returnData[property] = self._generateMock(inputJson[property]);
} else if (valueType === 'array') {
returnData[property] = self._readArray(inputJson[property]);
}
}
}
return returnData;
};
_getFakerData(inputValue) {
if (this._isFaker(inputValue)) {
return this._createFakerData(inputValue);
} else return inputValue;
};
_createFakerData(inputValue) {
var regExp = /(.*)\((.*)\)\)?/;
/*
Example
input => '@faker.name.findName('someArg')
output =>
[ '@faker.name.findName(\'someArg\')',
'@faker.name.findName',
'\'someArg\'',
index: 0,
input: '@faker.name.findName(\'someArg\')' ]
*/
var [, fakerDef, funcArg] = inputValue.match(regExp);
var getStructure = fakerDef.split('.');
var returnData;
if (getStructure[1] === 'file') {
funcArg = funcArg.replace(/'/g, '');
if (this.fileList.includes(funcArg)) return 'infinit loop()';
else this.fileList.push(funcArg);
var jsonObj = this._getJsonObj(funcArg, 'json');
if (jsonObj === 'Invalid input') {
this.fileList.pop(); // removing file from array after processing
return jsonObj;
}
returnData = this._generateMock(jsonObj);
this.fileList.pop(); // removing file from array after processing
return returnData;
} else {
if (funcArg[0] === '[') { // checking if it is array
funcArg = funcArg.replace(/'/g, '"');
funcArg = JSON.parse(funcArg);
}
if (funcArg[0] === '{') { // checking if it is object
try {
funcArg = JSON.parse(funcArg);
} catch (err) {
// since JSON.parse threw an error, assume parameters was actually a string
funcArg = funcArg;
}
}
returnData = faker[getStructure[1]][getStructure[2]](funcArg);
}
return returnData;
};
_isFaker(inputValue) {
if (inputValue.split('.')[0] === '@faker') return true;
else return false;
};
_processTemplate(input, inputType) {
if (inputType === 'json') {
input = this._readTemplateFile(input);
}
return this._repeatString(input);
};
_repeatString(input) {
/*
regEx = /{{repeat\s+(\d+)}}([\s\S]*?){{\/repeat}}/g
{{repeat - a literal char sequence
\s+ - 1+ whitespaces
(\d+) - Group 1: one or more digits
}} - literal }}
([\s\S]*?) - Group 2, any 0+ characters, as few as possible up to the first
{{\/repeat}} - literal {{/repeat}}.
*/
var res;
var self = this;
if (typeof input === 'string') {
res = input.replace(/{{repeat\s+(\d+)}}([\s\S]*?){{\/repeat}}/g, function($0, $1, $2) {
return self._fillArray($2.trim(), parseInt($1, 10)).join(', ');
});
}
return res;
};
_readTemplateFile(path) {
try {
var data = fs.readFileSync(path);
return data.toString();
} catch (e) {
return 'Invalid Input';
}
};
_stringProcessing(inputString) {
var self = this;
inputString = this._repeatString(inputString);
var result = inputString.replace(/\{{(.+?)\}}/gmi, function(match, textInside) {
var objectProp = textInside.split('.');
if (objectProp[0] === '@faker') return self._createFakerData(textInside);
else {
var obj = self.userTemplate;
while (objectProp.length && (obj = obj[objectProp.shift()]));
return obj;
}
});
return result;
};
_IsJsonString(str) {
if (!isNaN(Number(str))) return false;
try {
JSON.parse(str);
} catch (e) {
return false;
}
return true;
}
_fillArray(s, num) {
var arr = [];
for (var i = 0; i < num; i++) {
arr.push(s);
}
return arr;
}
}
module.exports = new JsonFaker();