Comparing version 1.3.0 to 1.4.0
{ | ||
"name": "jembadb", | ||
"version": "1.3.0", | ||
"version": "1.4.0", | ||
"description": "Json Embeddable Appendable Database", | ||
@@ -5,0 +5,0 @@ "main": "./src/index.js", |
# JembaDb | ||
JembaDb - tiny Json Embeddable Appendable Database | ||
JembaDb - tiny Json Embedded Appending Database |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const JembaDb = require('./JembaDb'); | ||
@@ -2,0 +4,0 @@ const JembaDbThread = require('./JembaDbThread'); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const fs = require('fs').promises; | ||
@@ -434,9 +436,11 @@ | ||
(!) table: 'tableName', | ||
count: Boolean, | ||
where: `@@index('field1', 10, 20)`, | ||
distinct: 'fieldName' || Array, | ||
count: Boolean, | ||
group: {byField: 'fieldName' || Array, byExpr: '(r) => groupingValue', countField: 'fieldName'}, | ||
map: '(r) => ({id1: r.id, ...})', | ||
where: `@@index('field1', 10, 20)`, | ||
sort: '(a, b) => a.id - b.id', | ||
limit: 10, | ||
offset: 10, | ||
joinById: {table: 'tableName', on: 'fieldNameToJoinOn', out: 'fieldNameToPutJoinResult', map: '(r) => r.name'} || Array, | ||
} | ||
@@ -451,11 +455,56 @@ result = Array | ||
const checkTable = async(table) => { | ||
if (await this.tableExists({table})) { | ||
throw new Error(`Table '${table}' has not been opened yet`); | ||
} else { | ||
throw new Error(`Table '${table}' does not exist`); | ||
} | ||
}; | ||
const table = this.table.get(query.table); | ||
if (table) { | ||
return await table.select(query); | ||
//select | ||
const resultRows = await table.select(query); | ||
//joinById | ||
if (query.joinById) { | ||
const joinList = (Array.isArray(query.joinById) ? query.joinById : [query.joinById]); | ||
for (const join of joinList) { | ||
if (!join.table) | ||
throw new Error(`'joinById.table' parameter is required`); | ||
if (!join.on) | ||
throw new Error(`'joinById.on' parameter is required`); | ||
const joinTable = this.table.get(join.table); | ||
if (joinTable) { | ||
const on = join.on; | ||
const ids = resultRows.map((r) => r[on]); | ||
const joinRows = await joinTable.select({where: `@@id(${this.esc(ids)})`}); | ||
let mapFunc = null; | ||
if (join.map) { | ||
mapFunc = new Function(`'use strict'; return ${join.map}`)(); | ||
} | ||
const idMap = new Map(); | ||
for (const row of joinRows) { | ||
idMap.set(row.id, (mapFunc ? mapFunc(row) : row)); | ||
} | ||
const out = (join.out ? join.out : `table_${join.table}`); | ||
for (const row of resultRows) { | ||
row[out] = idMap.get(row[on]); | ||
} | ||
} else { | ||
await checkTable(joinTable); | ||
} | ||
} | ||
} | ||
return resultRows; | ||
} else { | ||
if (await this.tableExists({table: query.table})) { | ||
throw new Error(`Table '${query.table}' has not been opened yet`); | ||
} else { | ||
throw new Error(`Table '${query.table}' does not exist`); | ||
} | ||
await checkTable(query.table); | ||
} | ||
@@ -462,0 +511,0 @@ } |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const { parentPort } = require('worker_threads'); | ||
@@ -2,0 +4,0 @@ |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const { Worker } = require('worker_threads'); | ||
@@ -2,0 +4,0 @@ const utils = require('./utils'); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
class LockQueue { | ||
@@ -2,0 +4,0 @@ constructor(queueSize) { |
120
src/Table.js
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const fs = require('fs').promises; | ||
@@ -423,6 +425,7 @@ const utils = require('./utils'); | ||
query = { | ||
count: Boolean, | ||
where: `@@index('field1', 10, 20)`, | ||
distinct: 'fieldName' || Array, | ||
count: Boolean, | ||
group: {byField: 'fieldName' || Array, byExpr: '(r) => groupingValue', countField: 'fieldName'}, | ||
map: '(r) => ({id1: r.id, ...})', | ||
where: `@@index('field1', 10, 20)`, | ||
sort: '(a, b) => a.id - b.id', | ||
@@ -439,5 +442,6 @@ limit: 10, | ||
let ids;//iterator | ||
//where condition | ||
if (query.where) { | ||
const where = this.prepareWhere(query.where); | ||
const whereFunc = new Function(`return ${where}`)(); | ||
const whereFunc = new Function(`'use strict'; return ${where}`)(); | ||
@@ -449,23 +453,55 @@ ids = await whereFunc(this.reducer); | ||
let found = []; | ||
//grouping | ||
let inGroup = () => false; | ||
const groupMap = new Map(); | ||
const doCount = query.group && query.group.countField; | ||
let distinct = () => true; | ||
if (query.distinct) { | ||
const distFields = (Array.isArray(query.distinct) ? query.distinct : [query.distinct]); | ||
const dist = new Map(); | ||
distinct = (row) => { | ||
let uniq = ''; | ||
for (const field of distFields) { | ||
const value = row[field]; | ||
uniq += `${(value === undefined ? '___' : '')}${field}:${value}`; | ||
if (query.distinct || query.group) { | ||
if (query.distinct && query.group) | ||
throw new Error(`One of query.distinct or query.qroup params expected, but not both`); | ||
let groupByField = null; | ||
let groupByExpr = null; | ||
if (query.distinct) | ||
groupByField = (Array.isArray(query.distinct) ? query.distinct : [query.distinct]); | ||
if (query.group) { | ||
if (query.group.byField && query.group.byExpr) | ||
throw new Error(`One of query.qroup.byField or query.qroup.byExpr params expected, but not both`); | ||
if (query.group.byField) { | ||
groupByField = (Array.isArray(query.group.byField) ? query.group.byField : [query.group.byField]); | ||
} else if (query.group.byExpr) { | ||
groupByExpr = new Function(`'use strict'; return ${query.group.byExpr}`)(); | ||
} | ||
} | ||
if (dist.has(uniq)) | ||
return false; | ||
dist.set(uniq, true); | ||
return true; | ||
//returns (count - 1) group size | ||
inGroup = (row) => { | ||
let groupingValue = ''; | ||
if (groupByField) { | ||
for (const field of groupByField) { | ||
const value = JSON.stringify(row[field]); | ||
groupingValue += value.length + value; | ||
} | ||
} else if (groupByExpr) { | ||
groupingValue = groupByExpr(row); | ||
} | ||
if (groupMap.has(groupingValue)) { | ||
if (doCount) { | ||
const count = groupMap.get(groupingValue); | ||
groupMap.set(groupingValue, count + 1); | ||
return count; | ||
} | ||
return 1; | ||
} | ||
groupMap.set(groupingValue, 1); | ||
return 0; | ||
}; | ||
} | ||
if (!query.where && !query.distinct && query.count) {//some optimization | ||
//selection | ||
let found = []; | ||
if (!query.where && !query.distinct && !query.group && query.count) {//minor optimization | ||
found = [{count: this.rowsInterface.getAllIdsSize()}]; | ||
@@ -476,3 +512,3 @@ } else {//full running | ||
if (row && distinct(row)) { | ||
if (row && !inGroup(row)) { | ||
found.push(row); | ||
@@ -487,5 +523,15 @@ } | ||
found = utils.cloneDeep(found);//for safu | ||
//grouping count field | ||
if (doCount) { | ||
for (const row of found) { | ||
row[query.group.countField] = inGroup(row); | ||
} | ||
} | ||
//mapping | ||
let result = []; | ||
if (query.map) { | ||
const mapFunc = new Function(`return ${query.map}`)(); | ||
const mapFunc = new Function(`'use strict'; return ${query.map}`)(); | ||
@@ -499,14 +545,16 @@ for (const row of found) { | ||
//sorting | ||
if (query.sort) { | ||
const sortFunc = new Function(`return ${query.sort}`)(); | ||
const sortFunc = new Function(`'use strict'; return ${query.sort}`)(); | ||
result.sort(sortFunc); | ||
} | ||
if (query.hasOwnProperty('limit') || query.hasOwnProperty('offset')) { | ||
//limits&offset | ||
if (utils.hasProp(query, 'limit') || utils.hasProp(query, 'offset')) { | ||
const offset = query.offset || 0; | ||
const limit = (query.hasOwnProperty('limit') ? query.limit : result.length); | ||
const limit = (utils.hasProp(query, 'limit') ? query.limit : result.length); | ||
result = result.slice(offset, offset + limit); | ||
} | ||
return utils.cloneDeep(result); | ||
return result; | ||
} | ||
@@ -547,5 +595,2 @@ | ||
for (const newRow of newRows) { | ||
if (newRow.hasOwnProperty('___meta')) | ||
throw new Error(`Use of field with name '___meta' is forbidden`); | ||
if (newRow.id === undefined) { | ||
@@ -626,3 +671,3 @@ newRow.id = this.autoIncrement; | ||
} | ||
const modFunc = new Function(`return ${query.mod}`)(); | ||
const modFunc = new Function(`'use strict'; return ${query.mod}`)(); | ||
@@ -633,3 +678,3 @@ //where | ||
const where = this.prepareWhere(query.where); | ||
const whereFunc = new Function(`return ${where}`)(); | ||
const whereFunc = new Function(`'use strict'; return ${where}`)(); | ||
@@ -652,3 +697,3 @@ ids = await whereFunc(this.reducer); | ||
if (query.sort) { | ||
const sortFunc = new Function(`return ${query.sort}`)(); | ||
const sortFunc = new Function(`'use strict'; return ${query.sort}`)(); | ||
oldRows.sort(sortFunc); | ||
@@ -658,5 +703,5 @@ } | ||
if (query.hasOwnProperty('limit') || query.hasOwnProperty('offset')) { | ||
if (utils.hasProp(query, 'limit') || utils.hasProp(query, 'offset')) { | ||
const offset = query.offset || 0; | ||
const limit = (query.hasOwnProperty('limit') ? query.limit : newRows.length); | ||
const limit = (utils.hasProp(query, 'limit') ? query.limit : newRows.length); | ||
newRows = newRows.slice(offset, offset + limit); | ||
@@ -681,5 +726,2 @@ oldRows = oldRows.slice(offset, offset + limit); | ||
if (newRow.hasOwnProperty('___meta')) | ||
throw new Error(`Use of field with name '___meta' is forbidden`); | ||
newRowsStr.push(JSON.stringify(newRow));//because of stringify errors | ||
@@ -740,3 +782,3 @@ } | ||
const where = this.prepareWhere(query.where); | ||
const whereFunc = new Function(`return ${where}`)(); | ||
const whereFunc = new Function(`'use strict'; return ${where}`)(); | ||
@@ -761,9 +803,9 @@ ids = await whereFunc(this.reducer); | ||
if (query.sort) { | ||
const sortFunc = new Function(`return ${query.sort}`)(); | ||
const sortFunc = new Function(`'use strict'; return ${query.sort}`)(); | ||
oldRows.sort(sortFunc); | ||
} | ||
if (query.hasOwnProperty('limit') || query.hasOwnProperty('offset')) { | ||
if (utils.hasProp(query, 'limit') || utils.hasProp(query, 'offset')) { | ||
const offset = query.offset || 0; | ||
const limit = (query.hasOwnProperty('limit') ? query.limit : newRows.length); | ||
const limit = (utils.hasProp(query, 'limit') ? query.limit : newRows.length); | ||
newRows = newRows.slice(offset, offset + limit); | ||
@@ -770,0 +812,0 @@ oldRows = oldRows.slice(offset, offset + limit); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
class TableFlag { | ||
@@ -2,0 +4,0 @@ constructor(checkCode) { |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
class TableHash { | ||
@@ -2,0 +4,0 @@ //opts.type = 'string' || 'number' || 'number_as_string' |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const utils = require('./utils'); | ||
@@ -2,0 +4,0 @@ |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const fs = require('fs').promises; | ||
@@ -2,0 +4,0 @@ const path = require('path'); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const fs = require('fs').promises; | ||
@@ -2,0 +4,0 @@ const path = require('path'); |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
class TableRowsMem { | ||
@@ -2,0 +4,0 @@ constructor() { |
@@ -0,1 +1,3 @@ | ||
'use strict'; | ||
const fsCB = require('fs'); | ||
@@ -139,2 +141,5 @@ const fs = fsCB.promises; | ||
function hasProp(obj, prop) { | ||
return Object.prototype.hasOwnProperty.call(obj, prop); | ||
} | ||
@@ -153,2 +158,3 @@ module.exports = { | ||
inflate, | ||
hasProp | ||
}; |
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
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
131695
3443
10