Comparing version 0.0.6 to 0.0.7
{ | ||
"name": "mapql", | ||
"version": "0.0.6", | ||
"version": "0.0.7", | ||
"description": "A MongoDB inspired ES6 Map() query langauge.", | ||
@@ -8,3 +8,3 @@ "main": "index.js", | ||
"test": "mocha tests/node.js", | ||
"local": "karma start tests/local.karma.js", | ||
"local": "karma start tests/local.karma.js --debug", | ||
"sauce": "karma start tests/sauce.karma.js" | ||
@@ -11,0 +11,0 @@ }, |
@@ -76,2 +76,8 @@ MapQL (WIP) | ||
Current (known) supported [data types](/src/DataTypes.js): | ||
* [Primitives] | ||
* Boolean, Null, Undefined, Number, String, Symbol, Object | ||
* Extended support | ||
* Array, Function, Date, Map, Set, Buffer/Uint8Array, RegExp | ||
Example: `MapQL.find()` | ||
@@ -229,1 +235,2 @@ - | ||
[PhantomJS]: http://phantomjs.org/ | ||
[Primitives]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Data_types |
@@ -61,3 +61,3 @@ /*! | ||
return this.MapQL.constructor.queryOperators[$qo].chain(key, val, $qo); | ||
} catch (error) { | ||
} catch (error) { | ||
return val !== Helpers._null ? { [key] : { [$qo]: val } } : { [$qo]: key }; | ||
@@ -64,0 +64,0 @@ } |
@@ -7,3 +7,4 @@ /*! | ||
// Create a null Symbol as 'null' is a valid Map() key/value. | ||
const _null = Symbol(null); | ||
const _null = Symbol(null), | ||
{ typeToInt, intToType } = require('./DataTypes'); | ||
@@ -47,3 +48,3 @@ /* | ||
function getType (val) { | ||
return Object.prototype.toString.call(val).toLowerCase().match(/(?:\[object (.+)\])/i)[1] | ||
return Object.prototype.toString.call(val).match(/(?:\[object (.+)\])/i)[1] | ||
}; | ||
@@ -53,7 +54,8 @@ | ||
* Test if a variable is the provided type; if type arg is prefixed with `!` test if NOT type. | ||
* If typeOf is true, use 'typeof value' instead of getType. | ||
*/ | ||
function is (val, type) { | ||
function is (val, type, typeOf = false) { | ||
try { | ||
return (/^!/.test(type) !== (getType(val) === type.toLowerCase().replace(/^!/,''))); | ||
} catch (error) { | ||
return (/^!/.test(type) !== ((typeOf ? typeof val : getType(val).toLowerCase()) === type.toLowerCase().replace(/^!/,''))); | ||
} catch (error) { | ||
return false; | ||
@@ -64,2 +66,46 @@ } | ||
/* | ||
* Deep clone Map/MapQL objects. | ||
*/ | ||
function deepClone (obj, _Map = Map) { | ||
if (is(obj, 'null') || is(obj, '!object', true)) { | ||
return obj; | ||
} | ||
switch (obj.constructor.name.toLowerCase()) { | ||
case 'date': | ||
return new Date(obj.getTime()); | ||
case 'map': case 'mapql': | ||
return new _Map(deepClone(Array.from(obj), _Map)); | ||
case 'set': | ||
return new Set(deepClone(Array.from(obj), _Map)); | ||
case 'regexp': | ||
return new RegExp(obj); | ||
case 'array': | ||
return new Array(obj.length).fill(0).map((val, idx) => { | ||
return deepClone(obj[idx], _Map) | ||
}); | ||
case 'object': | ||
return ((cloned) => { | ||
for (let prop in obj) { | ||
if (obj.hasOwnProperty(prop)) { | ||
cloned[prop] = deepClone(obj[prop], _Map); | ||
} | ||
} | ||
return cloned; | ||
})({}); | ||
default: return obj; | ||
} | ||
} | ||
/* | ||
* A small polyfill to get the constructor name for IE11. | ||
*/ | ||
if (Function.prototype.name === undefined && Object.defineProperty !== undefined) { | ||
Object.defineProperty(Function.prototype, 'name', { | ||
get: ()=>{ | ||
try { return /^function\s+([\w\$]+)\s*\(/.exec((this).toString())[1]; } catch (error) { return ''; } | ||
}, set: ()=>{} | ||
}); | ||
} | ||
/* | ||
* Export all of the helper functions. | ||
@@ -76,6 +122,9 @@ */ | ||
}, | ||
is: (val, type) => { | ||
return Array.isArray(type) ? type.every((t) => is(val, t)) : is(val, type); | ||
is: (val, type, typeOf = false, some = false) => { | ||
return Array.isArray(type) ? type[some ? 'some' : 'every']((t) => is(val, t, typeOf)) : is(val, type, typeOf); | ||
}, | ||
getType: getType | ||
getType: getType, | ||
deepClone: deepClone, | ||
typeToInt: typeToInt, | ||
intToType: intToType | ||
}; |
133
src/MapQL.js
@@ -9,6 +9,7 @@ /*! | ||
updateOperators = require('./operators/Update'), | ||
Document = require('./Document'), | ||
MapQLDocument = require('./Document'), | ||
Cursor = require('./Cursor'), | ||
Helpers = require('./Helpers'), | ||
GenerateID = new (require('./GenerateID'))(); | ||
GenerateID = new (require('./GenerateID'))(), | ||
isEqual = require('is-equal'); | ||
@@ -28,2 +29,31 @@ class MapQL extends Map { | ||
/* | ||
* Check if MapQL has a specific key, if strict is false return | ||
* true if the keys are only similar. | ||
*/ | ||
has (key, strict = true) { | ||
if (!strict) { | ||
return [...this.keys()].some((_key) => { | ||
return isEqual(key, _key); | ||
}); | ||
} | ||
return Map.prototype.has.call(this, key); | ||
} | ||
/* | ||
* Get a key if it exists, if strict is false return value if the | ||
* keys are only similar. | ||
*/ | ||
get (key, strict = true) { | ||
if (!strict) { | ||
for (let [_key, value] of [...this.entries()]) { | ||
if (isEqual(key, _key)) { | ||
return value; | ||
} | ||
} | ||
return Helpers._null; | ||
} | ||
return Map.prototype.get.call(this, key); | ||
} | ||
/* | ||
* Convert the query/update object to an Object with an Array | ||
@@ -67,3 +97,3 @@ * of queries or update modifiers. | ||
isDocument (obj) { | ||
return Document.isDocument(obj); | ||
return MapQLDocument.isDocument(obj); | ||
} | ||
@@ -98,3 +128,3 @@ | ||
isQueryOperator (qs = Helpers._null) { | ||
return this.queryOperators.hasOwnProperty(qs) == true; | ||
return this.queryOperators.hasOwnProperty(qs) === true; | ||
} | ||
@@ -113,3 +143,3 @@ | ||
isLogicalOperator (lo = Helpers._null) { | ||
return this.logicalOperators.hasOwnProperty(lo) == true; | ||
return this.logicalOperators.hasOwnProperty(lo) === true; | ||
} | ||
@@ -128,3 +158,3 @@ | ||
isUpdateOperator (uo = Helpers._null) { | ||
return this.updateOperators.hasOwnProperty(uo) == true; | ||
return this.updateOperators.hasOwnProperty(uo) === true; | ||
} | ||
@@ -163,4 +193,5 @@ | ||
if (Helpers.is(queries, '!object')) { | ||
if (this.has(queries)) { | ||
return new Cursor(queries, true).add(new Document(queries, this.get(queries))); | ||
let value; | ||
if ((value = this.get(queries, false)) !== Helpers._null) { | ||
return new Cursor(queries, true).add(new MapQLDocument(queries, value)); | ||
} | ||
@@ -174,3 +205,3 @@ queries = { '$eq' : queries }; | ||
if (this._validate(!bykey ? entry : [entry[0], entry[0]], _queries)) { | ||
cursor.add(new Document(entry[0], entry[1], bykey)); | ||
cursor.add(new MapQLDocument(entry[0], entry[1], bykey)); | ||
if (one) { | ||
@@ -183,3 +214,3 @@ return cursor; | ||
} else { | ||
return new Cursor().add(Document.convert(one ? [[...this.entries()][0]] : [...this.entries()])); | ||
return new Cursor().add(MapQLDocument.convert(one ? [[...this.entries()][0]] : [...this.entries()])); | ||
} | ||
@@ -210,3 +241,3 @@ } | ||
return !!results.length ? resolve(results) : reject(new Error('No entries found.')); | ||
} catch (error) { | ||
} catch (error) { | ||
reject(error); | ||
@@ -286,15 +317,23 @@ } | ||
try { | ||
let _toString = (m) => { | ||
return Helpers.is(m, ['!null', '!object', '!number', '!boolean', '!array']) ? m.toString() : m; | ||
let _export = (m) => { | ||
if (Helpers.is(m, 'set')) { | ||
return [...m].map((k) => [_export(k), Helpers.typeToInt(Helpers.getType(k))]); | ||
} else if (Helpers.is(m, 'map')) { | ||
return [...m].map(([k,v]) => [_export(k), _export(v), Helpers.typeToInt(Helpers.getType(k)), Helpers.typeToInt(Helpers.getType(v))]); | ||
} else if (Helpers.is(m, 'object')) { | ||
for (let key of Object.keys(m)) { | ||
m[key] = [_export(m[key]), Helpers.typeToInt(Helpers.getType(m[key]))]; | ||
} | ||
} else if (Helpers.is(m, 'array')) { | ||
return m.map((value) => { return [_export(value), Helpers.typeToInt(Helpers.getType(value))]; }); | ||
} | ||
return Helpers.is(m, ['!null', '!number', '!boolean', '!object']) ? m.toString() : m; | ||
}, | ||
_export = (m) => { | ||
return Helpers.is(m, 'map') ? [...m].map(([k,v]) => [_export(k), _export(v), Helpers.getType(k), Helpers.getType(v)]) : _toString(m) | ||
}, | ||
exported = _export(this); | ||
exported = _export(Helpers.deepClone(this, MapQL)); | ||
return ((res) => { | ||
return (opts.promise ? Promise.resolve(res) : res); | ||
})(opts.stringify ? JSON.stringify(exported, null, (opts.pretty ? 4 : 0)) : exported); | ||
} catch (error) { | ||
return (opts.promise ? Promise.reject(error) : error); | ||
} catch (error) { | ||
return (opts.promise ? Promise.reject(error) : error); | ||
} | ||
@@ -316,16 +355,6 @@ } | ||
try { | ||
// XXX: Move this (fromType) to a different file for easier editing. | ||
function fromType (entry, type) { | ||
switch (type.toLowerCase()) { | ||
// XXX: Add more data types! | ||
case 'map': return (new MapQL()).import(entry); | ||
case 'function': return Function(`return ${entry}`)(); | ||
case 'array': return Array.from(entry); | ||
default: return entry; | ||
} | ||
} | ||
(Helpers.is(json, 'string') ? JSON.parse(json) : json).map((entry) => { | ||
this.set(fromType(entry[0], entry[2] || ''), fromType(entry[1], entry[3] || '')); | ||
}); | ||
} catch (error) { | ||
} catch (error) { | ||
if (opts.promise) { | ||
@@ -342,4 +371,46 @@ return Promise.reject(error); | ||
/* | ||
* Convert strings to required data type, used in import(). | ||
*/ | ||
let Mapper = (value) => { | ||
return value.map((val) => { | ||
return fromType(val[0], val[1]); | ||
}); | ||
}; | ||
function fromType (entry, type) { | ||
let inttype = Helpers.intToType(type); | ||
switch (inttype) { | ||
case 'Map': | ||
return (new MapQL()).import(entry); // Convert all 'Map()' entries to MapQL. | ||
case 'Set': | ||
return new Set(Mapper(entry)); | ||
// XXX: Function() is a form of eval()! | ||
case 'Function': | ||
return new Function(`return ${entry};`)(); | ||
case 'Array': | ||
return Mapper(entry); | ||
case 'Object': | ||
return ((obj) => { | ||
for (let key of Object.keys(obj)) { | ||
obj[key] = fromType(obj[key][0], obj[key][1]); | ||
} | ||
return obj; | ||
})(entry); | ||
case 'Uint8Array': | ||
case 'Buffer': | ||
try { | ||
if (Uint8Array && Helpers.getType(Uint8Array) === 'function') { | ||
return new Uint8Array(entry); | ||
} | ||
} catch (error) { | ||
return Buffer.from(entry); | ||
} | ||
case 'RegExp': | ||
return RegExp.apply(null, entry.match(/\/(.*?)\/([gimuy])?$/).slice(1)); | ||
default: return entry; | ||
} | ||
} | ||
/* | ||
* Export the module for use! | ||
*/ | ||
module.exports = MapQL; |
@@ -17,5 +17,5 @@ /*! | ||
try { | ||
return bool === (Helpers.dotNotation(keys, entry[1], { defined: true }) !== undefined); | ||
} catch (error) { | ||
return keys === Helpers._null ? (bool === undefined ? true : bool) : false; | ||
return bool === (Helpers.dotNotation(keys, entry[1], { defined: true }) !== undefined); | ||
} catch (error) { | ||
return keys === Helpers._null ? (bool === undefined ? true : bool) : false; | ||
} | ||
@@ -22,0 +22,0 @@ } |
@@ -260,4 +260,4 @@ /*! | ||
data =[ | ||
'[["test0",{"foo":1},"string","object"]]', | ||
'[[{"foo":1},"test1","object","string"]]' | ||
'[["test0",{"foo":[1,3]},4,6]]', | ||
'[[{"foo":[1,3]},"test1",6,4]]' | ||
]; | ||
@@ -277,5 +277,5 @@ describe('#import()', () => { | ||
it('it should export '+data[1], () => { | ||
assert.deepEqual(JSON.parse(MapQL3.export())[0][0], { foo: 1 }); | ||
assert.deepEqual(JSON.parse(MapQL3.export())[0][0], { foo: [1, 3] }); | ||
}); | ||
}); | ||
}); |
@@ -260,4 +260,4 @@ /*! | ||
data =[ | ||
'[["test0",{"foo":1},"string","object"]]', | ||
'[[{"foo":1},"test1","object","string"]]' | ||
'[["test0",{"foo":[1,3]},4,6]]', | ||
'[[{"foo":[1,3]},"test1",6,4]]' | ||
]; | ||
@@ -277,5 +277,5 @@ describe('#import()', () => { | ||
it('it should export '+data[1], () => { | ||
assert.deepEqual(JSON.parse(MapQL3.export())[0][0], { foo: 1 }); | ||
assert.deepEqual(JSON.parse(MapQL3.export())[0][0], { foo: [1, 3] }); | ||
}); | ||
}); | ||
}); |
@@ -30,2 +30,4 @@ IMPORTANT: Need to document ALL the things! | ||
* Document import/export feature. | ||
* Add more support for extended data types. | ||
* https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays | ||
* Everything else. | ||
@@ -32,0 +34,0 @@ * Work on the TODO! |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
557629
35
7664
235