Comparing version 1.3.2 to 2.0.0
@@ -10,8 +10,15 @@ { | ||
"args": [ | ||
"${workspaceFolder}/test/encode_test.js" | ||
"${workspaceFolder}/tests/encode2_test.js" | ||
], | ||
"internalConsoleOptions": "openOnSessionStart" | ||
} | ||
/* { | ||
"type": "node", | ||
"request": "launch", | ||
"name": "Jasmine Tests", | ||
"program": "${workspaceFolder}/src/testParser.js", | ||
"internalConsoleOptions": "openOnSessionStart" | ||
} */ | ||
] | ||
} |
@@ -27,1 +27,5 @@ ## Thanks | ||
* https://github.com/Roshanjossey/first-contributions | ||
* Please refrain to work on multiple cards. As your friends and colleagues to attempt rest cards | ||
* Please claim the issue and clear your doubts before raising PR. So other users will not start working on the same issue. | ||
* Mention the issue number either in PR detail or in commit message. | ||
* Keep increasing the level of challenge. |
{ | ||
"name": "nimnjs", | ||
"version": "1.3.2", | ||
"version": "2.0.0", | ||
"description": "Schema aware compression of JS object/JSON data. 60% more compressed than json", | ||
@@ -25,8 +25,8 @@ "main": "src/nimn.js", | ||
"type": "git", | ||
"url": "https://github.com/nimndata/nimnjs-node.git" | ||
"url": "https://github.com/nimndata/nimnjs.git" | ||
}, | ||
"bugs": { | ||
"url": "https://github.com/nimndata/nimnjs-node/issues" | ||
"url": "https://github.com/nimndata/nimnjs/issues" | ||
}, | ||
"homepage": "https://github.com/nimndata/nimnjs-node", | ||
"homepage": "https://github.com/nimndata/nimnjs", | ||
"dependencies": { | ||
@@ -33,0 +33,0 @@ "nimn-date-parser": "^1.0.0", |
@@ -99,3 +99,11 @@ # nimnjs-node | ||
## Users | ||
List of applications and projects using Nimn. (Raise an issue to submit yours) | ||
<a href="https://github.com/NaturalIntelligence/imglab" title="imglab" ><img src="https://github.com/NaturalIntelligence/imglab/blob/master/img/imglab_logo.png?raw=true" width="80px" style="margin:4px;"></a> | ||
<a href="https://github.com/NaturalIntelligence/Stubmatic" title="stubmatic" ><img src="https://camo.githubusercontent.com/ff711425dc2286cd215637b7114eb43e571f001d/68747470733a2f2f6e61747572616c696e74656c6c6967656e63652e6769746875622e696f2f537475626d617469632f696d672f737475626d617469635f6c6f676f2e706e673f7261773d74727565" width="80px" style="margin:4px;" ></a> | ||
<a href="https://github.com/muneem4node/muneem" title="Muneem" ><img src="https://github.com/muneem4node/muneem/raw/master/static/muneem.png?raw=true" width="80px" style="margin:4px;" ></a> | ||
<a href="https://github.com/funcards/match-it/" title="Match it" ><img src="https://github.com/funcards/match-it/raw/master/static/img/matchit_logo.png?raw=true" width="80px" style="margin:4px;" ></a> | ||
<a href="https://github.com/NaturalIntelligence/fast-xml-parser" title="Fast XML Parser" ><img src="https://github.com/NaturalIntelligence/fast-xml-parser/raw/master/static/img/fxp_logo.png?raw=true" width="80px" style="margin:4px;" ></a> | ||
### Worth to mention | ||
@@ -102,0 +110,0 @@ |
442
src/nimn.js
@@ -1,95 +0,381 @@ | ||
var boolean = require("./parsers/boolean"); | ||
var numParser = require("./parsers/number"); | ||
var chars = require("./chars").chars; | ||
var appCharsArr = require("./chars").charsArr; | ||
var helper = require("./helper"); | ||
var schemaMarker = require("./schemaMarker"); | ||
var Decoder = require("./decoder"); | ||
var Encoder = require("./encoder"); | ||
var DataHandler = require("./DataHandler"); | ||
var char = function (a){ | ||
return String.fromCharCode(a); | ||
} | ||
function nimn() { | ||
this.handledChars = [];//appCharsArr.slice(); | ||
this.dataHandlers = {}; | ||
this.addDataHandler("boolean",null,null,boolean.charset,true); | ||
//this.addDataHandler("boolean",boolean.parse,boolean.parseBack,boolean.charset,true); | ||
this.addDataHandler("string"); | ||
this.addDataHandler("number",numParser.parse, numParser.parseBack); | ||
this.addDataHandler("date"); | ||
var range = { | ||
start : char(175), | ||
end : char(187), | ||
} | ||
const chars= { | ||
nilChar : char(176), | ||
nilPremitive : char(175), | ||
/** | ||
* This method should be called once all the data handlers are registered. | ||
* It updates internal schema based on given schema. | ||
* | ||
* @example | ||
* { | ||
* "field1" : "string", | ||
* "field2" : "date", | ||
* "field3" : { | ||
* "field4" : "number" | ||
* }, | ||
* "field5" : [ "image"], | ||
* "field6" : [{ "field7" : "boolean"}] | ||
* } | ||
* @param {*} schema | ||
* @returns {void} | ||
*/ | ||
nimn.prototype.addSchema= function(schema){ | ||
this.schema = JSON.parse(JSON.stringify(schema)); | ||
new schemaMarker(this.dataHandlers).markNextPossibleChars(this.schema); | ||
//helper.validateSchema(schema,this.dataHandlers); | ||
this.encoder = new Encoder(this.schema,this.dataHandlers,this.handledChars); | ||
missingChar : char(186), | ||
missingPremitive : char(184), | ||
emptyChar : char(178), | ||
emptyPremitive: char(177),//empty Premitive | ||
boundaryChar : char(179), | ||
objStart: char(182), | ||
objEnd: char(180), | ||
arrStart: char(187), | ||
arrEnd: char(185), | ||
yes: char(181), | ||
no: char(183), | ||
} | ||
/** | ||
* You can update existnig handler od add new using this method. | ||
* "string", "number", "boolean", and "date" are handled by default. | ||
* | ||
* charset should be set when given type should be treated as enum or fixed set of values | ||
* @example | ||
* //to map | ||
* nimnInstance.addDataHandler("status",null,null,{ "R": "running", "S" : "stop", "I", "ready to run"},false) | ||
* @example | ||
* //just for identification | ||
* nimnInstance.addDataHandler("image"); | ||
* @example | ||
* //to compress more | ||
* nimnInstance.addDataHandler("date", datecompressor.parse, datecompressor.parseBack); | ||
* @param {string} type | ||
* @param {function} parseWith - will be used by encoder to encode given type's value | ||
* @param {function} parseBackWith - will be used by decoder to decode given type's value | ||
* @param {Object} charset - map of charset and fixed values | ||
* @param {boolean} [noBoundaryChar=false] - if true encoder will not separate given type's value with boundary char | ||
*/ | ||
nimn.prototype.addDataHandler = function(type,parseWith,parseBackWith,charset,noBoundaryChar){ | ||
var dataHandler = new DataHandler(type,/* parseWith,parseBackWith, */charset,noBoundaryChar); | ||
if(parseWith) dataHandler.parse = parseWith; | ||
if(parseBackWith) dataHandler.parseBack = parseBackWith; | ||
var DataType = { | ||
BOOLEAN : 1, | ||
LIST : 2, | ||
MAP : 3, | ||
STRING : 4, | ||
NUMBER : 5, | ||
} | ||
//unque charset don't require boundary char. Hence check them is they are already added | ||
if(noBoundaryChar && charset){ | ||
var keys = Object.keys(charset); | ||
/* var decodeNimnChar = {}; | ||
decodeNimnChar[char(175)] = null; | ||
decodeNimnChar[char(184)] = undefined; | ||
decodeNimnChar[char(177)] = ""; | ||
decodeNimnChar[char(181)] = true; | ||
decodeNimnChar[char(183)] = false; */ | ||
for(var k in keys){ | ||
var ch = keys[k]; | ||
if(this.handledChars.indexOf(ch) !== -1 || appCharsArr.indexOf(ch) !== -1){ | ||
throw Error("DataHandler Error: "+ ch +" is not allowed. Either it is reserved or being used by another data handler"); | ||
/* var booleanValues = {}; | ||
booleanValues[undefined] = chars.missingPremitive; | ||
booleanValues[null] = chars.nilPremitive; | ||
booleanValues[true] = chars.yes; | ||
booleanValues[false] = chars.no; | ||
var stringValues = {}; | ||
stringValues[undefined] = chars.missingPremitive; | ||
stringValues[null] = chars.nilPremitive; | ||
stringValues[""] = chars.emptyPremitive; | ||
var numberValues = {}; | ||
numberValues[undefined] = chars.missingPremitive; | ||
numberValues[null] = chars.nilPremitive; */ | ||
function BooleanType(fName, defaultVal){ | ||
this._name = fName; | ||
this._type = DataType.BOOLEAN; | ||
this._decodeChar = {}; | ||
this._decodeChar[char(175)] = null; | ||
this._decodeChar[char(184)] = defaultVal; | ||
this._decodeChar[char(181)] = true; | ||
this._decodeChar[char(183)] = false; | ||
this._encode = function(v){ | ||
if(v){ | ||
return chars.yes; | ||
}else if(v === false){ | ||
return chars.no; | ||
}else if(v === undefined){ | ||
return chars.missingPremitive; | ||
}else if(v === null){ | ||
return chars.nilPremitive; | ||
} | ||
//return booleanValues[v]; | ||
}; | ||
this._decode = function(v,i){ | ||
return { | ||
index: i+1, | ||
value: this._decodeChar[ v[i] ] | ||
} | ||
}; | ||
} | ||
function StringType(fName, defaultVal, shouldSanitize){ | ||
this._name = fName; | ||
this._type = DataType.STRING; | ||
this._sanitize = shouldSanitize ? sanitize : doNothing; | ||
this._removeBackspace = shouldSanitize ? removeBackspace : doNothing; | ||
this._decodeChar = {}; | ||
this._decodeChar[char(175)] = null; | ||
this._decodeChar[char(184)] = defaultVal; | ||
this._decodeChar[char(177)] = ""; | ||
this._encode = function (v){ | ||
if(v){ | ||
return this._sanitize(v); | ||
}else if(v === undefined){ | ||
return chars.missingPremitive; | ||
}else if(v === null){ | ||
return chars.nilPremitive; | ||
}else if(v === ""){ | ||
return chars.emptyPremitive; | ||
} | ||
//return stringValues[v] || sanitize(v); | ||
}; | ||
this._decode = function(v,i){ | ||
if( inRange(v[i])){ | ||
return { | ||
index: i+1, | ||
value: this._decodeChar[ v[i] ] | ||
} | ||
}else{ | ||
var nextIndex = read(v,i); | ||
return { index: nextIndex, value: this._removeBackspace( v.substring(i,nextIndex) )}; | ||
} | ||
}; | ||
} | ||
function NumberType(fName, defaultVal){ | ||
this._name = fName; | ||
this._type = DataType.NUMBER; | ||
this._decodeChar = {}; | ||
this._decodeChar[char(175)] = null; | ||
this._decodeChar[char(184)] = defaultVal; | ||
this._encode = function(v){ | ||
if(v === undefined){ | ||
return chars.missingPremitive; | ||
}else if(v === null){ | ||
return chars.nilPremitive; | ||
}else { | ||
return v; | ||
} | ||
//return numberValues[v] || v; | ||
}; | ||
this._decode = function(v,i){ | ||
if( inRange(v[i]) ){ | ||
return { | ||
index: i+1, | ||
value: this._decodeChar[ v[i] ] | ||
} | ||
}else{ | ||
var nextIndex = read(v,i); | ||
var val = v.substring(i,nextIndex); | ||
if(val.indexOf(".") === -1){ | ||
val = Number.parseInt(val); | ||
}else{ | ||
this.handledChars.push(ch); | ||
val = Number.parseFloat(val); | ||
} | ||
return { index: nextIndex, value: val}; | ||
} | ||
}; | ||
} | ||
function MapType(fName){ | ||
this._name = fName; | ||
this._type = DataType.MAP; | ||
this._keys = []; | ||
this._len = 0; | ||
this._encode = function(v){ | ||
if(v === undefined){ | ||
return chars.missingChar; | ||
}else if(v === null){ | ||
return chars.nilChar; | ||
}else if(Object.keys(v).length === 0){ | ||
return chars.emptyChar; | ||
}else { | ||
var str = this._keys[0]._encode( v[ this._keys[0]._name ] ); | ||
var wasNimnChar = startsWithNimnChar(str,this._keys[0]); | ||
for(var i=1; i < this._len; i++){ | ||
var newStr = this._keys[i]._encode( v[ this._keys[i]._name ] ); | ||
var isNimnChar = startsWithNimnChar(newStr,this._keys[i]); | ||
if( isNimnChar || wasNimnChar ){ | ||
str += newStr; | ||
}else{ | ||
str += `${chars.boundaryChar}${newStr}`; | ||
} | ||
wasNimnChar = isNimnChar; | ||
} | ||
return `${chars.objStart}${str}${chars.objEnd}`; | ||
} | ||
}; | ||
this._decode = function(v,i){ | ||
if(v[i] === chars.emptyChar){ | ||
return {index: i+1, value: {} }; | ||
}else if(v[i] === chars.missingChar){ | ||
return {index: i+1, value: undefined }; | ||
}else if(v[i] === chars.nilChar){ | ||
return {index: i+1, value: null } | ||
}else if(v[i] === chars.objStart){ | ||
i++; | ||
var currentObj = {}; | ||
var str = this._keys[0]._decode( v,i ); | ||
i = str.index; | ||
if(str.value !== undefined){ | ||
currentObj[ this._keys[ 0 ]._name ] = str.value; | ||
} | ||
for(var key_i=1; key_i < this._len && v[i] !== chars.objEnd; key_i++){ | ||
var keyVal ; | ||
if(v[i] === chars.boundaryChar){ | ||
keyVal = this._keys[ key_i ]._decode( v,i +1 ); | ||
}else{ | ||
keyVal = this._keys[ key_i ]._decode( v,i ); | ||
} | ||
i = keyVal.index; | ||
if(keyVal.value !== undefined){ | ||
currentObj[ this._keys[ key_i ]._name ] = keyVal.value; | ||
} | ||
} | ||
return { | ||
index : i+1, | ||
value: currentObj | ||
} | ||
}else{ | ||
throw Error("Invalid character at position " + i); | ||
} | ||
}; | ||
} | ||
function ListType(fName){ | ||
this._name = fName; | ||
this._type = DataType.LIST; | ||
this._item = null; | ||
this._encode = function (v){ | ||
if(v === undefined){ | ||
return chars.missingChar; | ||
}else if(v === null){ | ||
return chars.nilChar; | ||
}else if(v.length === 0){ | ||
return chars.emptyChar; | ||
}else { | ||
var len = v.length; | ||
var str = this._item._encode( v[ 0 ] ); | ||
var wasNimnChar = startsWithNimnChar(str,this._item); | ||
for(var i=1; i < len; i++){ | ||
var newStr = this._item._encode( v[ i ] ); | ||
var isNimnChar = startsWithNimnChar(newStr,this._item); | ||
if( isNimnChar || wasNimnChar ){ | ||
str += newStr; | ||
}else{ | ||
str += `${chars.boundaryChar}${newStr}`; | ||
} | ||
wasNimnChar = isNimnChar; | ||
} | ||
return `${chars.arrStart}${str}${chars.arrEnd}`; | ||
} | ||
}; | ||
this._decode = function(v,i){ | ||
if(v[i] === chars.emptyChar){ | ||
return {index: i+1, value: []}; | ||
}else if(v[i] === chars.missingChar){ | ||
return {index: i+1, value: undefined }; | ||
}else if(v[i] === chars.nilChar){ | ||
return {index: i+1, value: null } | ||
}else if(v[i] === chars.arrStart){ | ||
i++; | ||
var currentArr = []; | ||
var str = this._item._decode( v,i ); | ||
i = str.index; | ||
if(str.value !== undefined) | ||
currentArr.push(str.value); | ||
for( ; v[i] !== chars.arrEnd ;){ | ||
var itemVal; | ||
if(v[i] === chars.boundaryChar){ | ||
itemVal = this._item._decode( v,i +1 ); | ||
}else{ | ||
itemVal = this._item._decode( v,i ); | ||
} | ||
i = itemVal.index; | ||
if(itemVal.value !== undefined) | ||
currentArr.push(itemVal.value); | ||
} | ||
return { | ||
index : i+1, | ||
value: currentArr | ||
} | ||
}else{ | ||
throw Error("Invalid character at position " + i); | ||
} | ||
}; | ||
} | ||
function buildSchema(schema, shouldSanitize){ | ||
if(shouldSanitize !== false){ | ||
shouldSanitize = true; | ||
} | ||
this.dataHandlers[type] = dataHandler; | ||
if(schema.type === "map"){ | ||
var mapSchema = new MapType(schema.name); | ||
mapSchema._keys = []; | ||
mapSchema._len = schema.detail.length; | ||
for(var i=0; i < mapSchema._len; i++){ | ||
mapSchema._keys.push( buildSchema(schema.detail[i], shouldSanitize ) ); | ||
} | ||
return mapSchema; | ||
}else if(schema.type === "list"){ | ||
var listSchema = new ListType(schema.name); | ||
listSchema._item = buildSchema(schema.detail, shouldSanitize); | ||
return listSchema; | ||
}else if(schema.type === "boolean"){ | ||
return new BooleanType(schema.name, schema.default); | ||
}else if(schema.type === "string"){ | ||
return new StringType(schema.name, schema.default, shouldSanitize); | ||
}else{//number | ||
return new NumberType(schema.name, schema.default); | ||
} | ||
} | ||
nimn.prototype.encode = function(jObj){ | ||
return this.encoder.encode(jObj); | ||
function parse(schema, jsObj){ | ||
return schema._encode(jsObj); | ||
} | ||
nimn.prototype.decode= function(encodedVal){ | ||
var decoder = new Decoder(this.schema,this.dataHandlers); | ||
return decoder.decode(encodedVal); | ||
function parseBack(schema, nimnData){ | ||
return schema._decode(nimnData,0).value; | ||
} | ||
module.exports = nimn; | ||
function startsWithNimnChar(str, type){ | ||
return type._type < 4 || ( str.length === 1 && inRange(str) ); | ||
} | ||
//var nimnCharRegx = new RegExp("([\xAF\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7\xB8\xB9\xBA\xBB])", 'g'); | ||
var nimnCharRegx = new RegExp("[^\]([\xAF-\xBB])", 'g'); | ||
/* function sanitize(v){ | ||
return v.replace(nimnCharRegx,'\\$1'); | ||
//return v; | ||
} */ | ||
function inRange(v){ | ||
return v >= range.start && v <= range.end; | ||
} | ||
function read(str,from,to){ | ||
to = to || str.length; | ||
for(;from < to;from++){ | ||
if( inRange(str[ from ]) && str[ from -1 ] !== "\\"){ | ||
return from; | ||
} | ||
} | ||
return to; | ||
} | ||
function sanitize(str){ | ||
var newStr = ""; | ||
for(var i=0;i < str.length;i++){ | ||
if( inRange( str[ i] ) ){ | ||
newStr += `\\${str[ i]}` | ||
}else{ | ||
newStr += str[ i]; | ||
} | ||
} | ||
return newStr; | ||
} | ||
function removeBackspace(str){ | ||
var newStr = ""; | ||
for(var i=0;i < str.length;i++){ | ||
if( str[ i ] === "\\" && inRange( str[ i +1 ] )){ | ||
continue; | ||
} | ||
newStr += str[ i ]; | ||
} | ||
return newStr; | ||
} | ||
function doNothing(a){ | ||
return a; | ||
} | ||
exports.buildSchema = buildSchema; | ||
exports.stringify = parse; | ||
exports.parse = parseBack; | ||
exports.chars = chars; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
118
22568
8
366
1