json-fs-query 2.1.1 → 2.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +8 -0
- package/browser/jsonFsQuery.js +41 -19
- package/browser/jsonFsQuery.min.js +1 -1
- package/dist/data/queries/sortBy.d.ts +6 -0
- package/dist/data/queries/sortBy.js +13 -4
- package/dist/data/queries/sortBy.min.js +1 -1
- package/dist/data/queries/where.js +8 -6
- package/dist/data/queries/where.min.js +1 -1
- package/dist/data/utilities/parsers/findSortClauses.d.ts +1 -0
- package/dist/data/utilities/runQuery.js +18 -7
- package/dist/data/utilities/runQuery.min.js +1 -1
- package/package.json +1 -1
|
@@ -1,2 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sort by each clause in turn: missing, then null, then the values, compared by the field's declared type when the
|
|
3
|
+
* clause has one (see compareAs), so a string field sorts as text ('10' before '9') and an int field as numbers.
|
|
4
|
+
* @param dataSet
|
|
5
|
+
* @param sortClauses
|
|
6
|
+
*/
|
|
1
7
|
export declare const sortBy: (dataSet?: any[], sortClauses?: any[]) => any[];
|
|
2
8
|
//# sourceMappingURL=sortBy.d.ts.map
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.sortBy = void 0;
|
|
7
|
+
var _compareAs = require("../utilities/compareAs");
|
|
7
8
|
// Where a value sorts before any other, ascending: missing first, then null, then the values (MySQL's null placement,
|
|
8
9
|
// with missing below null). Descending reverses it.
|
|
9
10
|
const presence = (data, property) => {
|
|
@@ -12,6 +13,12 @@ const presence = (data, property) => {
|
|
|
12
13
|
}
|
|
13
14
|
return data[property] === null ? 1 : 2;
|
|
14
15
|
};
|
|
16
|
+
/**
|
|
17
|
+
* Sort by each clause in turn: missing, then null, then the values, compared by the field's declared type when the
|
|
18
|
+
* clause has one (see compareAs), so a string field sorts as text ('10' before '9') and an int field as numbers.
|
|
19
|
+
* @param dataSet
|
|
20
|
+
* @param sortClauses
|
|
21
|
+
*/
|
|
15
22
|
const sortBy = (dataSet = [], sortClauses = []) => {
|
|
16
23
|
if (!sortClauses.length) {
|
|
17
24
|
return dataSet;
|
|
@@ -25,13 +32,15 @@ const sortBy = (dataSet = [], sortClauses = []) => {
|
|
|
25
32
|
if (rankA !== rankB) {
|
|
26
33
|
return direction === 'asc' ? rankA - rankB : rankB - rankA;
|
|
27
34
|
}
|
|
28
|
-
//
|
|
29
|
-
//
|
|
35
|
+
// Values compare by the declared type, so numeric ids in a string field sort as text ('10' before '9'). Loose so
|
|
36
|
+
// '3' and 3 still tie in an untyped field, as do two nulls or two missing.
|
|
37
|
+
const valueA = (0, _compareAs.compareAs)(sortClause.type, a[property]);
|
|
38
|
+
const valueB = (0, _compareAs.compareAs)(sortClause.type, b[property]);
|
|
30
39
|
// eslint-disable-next-line eqeqeq
|
|
31
|
-
if (
|
|
40
|
+
if (valueA == valueB) {
|
|
32
41
|
continue;
|
|
33
42
|
}
|
|
34
|
-
const result =
|
|
43
|
+
const result = valueA < valueB ? -1 : 1;
|
|
35
44
|
return direction === 'asc' ? result : result * -1;
|
|
36
45
|
}
|
|
37
46
|
return 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.sortBy=void 0;const presence=(e,r)=>Object.prototype.hasOwnProperty.call(e,r)?null===e[r]?1:2:0,sortBy=(e=[],r=[])=>r.length?(e.sort(((e,t)=>{for(const o of r){const r=o.property,s=o.direction,
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.sortBy=void 0;var _compareAs=require("../utilities/compareAs");const presence=(e,r)=>Object.prototype.hasOwnProperty.call(e,r)?null===e[r]?1:2:0,sortBy=(e=[],r=[])=>r.length?(e.sort(((e,t)=>{for(const o of r){const r=o.property,s=o.direction,c=presence(e,r),p=presence(t,r);if(c!==p)return"asc"===s?c-p:p-c;const n=(0,_compareAs.compareAs)(o.type,e[r]),a=(0,_compareAs.compareAs)(o.type,t[r]);if(n==a)continue;const i=n<a?-1:1;return"asc"===s?i:-1*i}return 0})),e):e;exports.sortBy=sortBy;
|
|
@@ -18,7 +18,8 @@ const likeMatch = (dataValue, pattern) => {
|
|
|
18
18
|
};
|
|
19
19
|
/**
|
|
20
20
|
* Equality (=, !=, <>, in) compares by the field's declared type when given one (see sameValue), so
|
|
21
|
-
* '3' and 3 match in a string or int field. Ordering (>, <, between
|
|
21
|
+
* '3' and 3 match in a string or int field. Ordering (>, >=, <, <=, between) compares by it too (see compareAs): a
|
|
22
|
+
* string field orders as text ('10' < '9'), an int field as numbers. like compares the raw values.
|
|
22
23
|
*
|
|
23
24
|
* Null and missing are their own cases, as in SQL: a field that is null or missing matches no comparison (not even
|
|
24
25
|
* `!=`), and a null never equals anything, not even another null. Only these test for them:
|
|
@@ -47,6 +48,7 @@ const makeCondition = (data, property, comparator, value, type = undefined) => {
|
|
|
47
48
|
return false;
|
|
48
49
|
}
|
|
49
50
|
const dataValue = data[property];
|
|
51
|
+
const typedValue = (0, _compareAs.compareAs)(type, dataValue);
|
|
50
52
|
switch (comparator) {
|
|
51
53
|
case '=':
|
|
52
54
|
return (0, _compareAs.sameValue)(type, dataValue, value);
|
|
@@ -54,18 +56,18 @@ const makeCondition = (data, property, comparator, value, type = undefined) => {
|
|
|
54
56
|
case '<>':
|
|
55
57
|
return !(0, _compareAs.sameValue)(type, dataValue, value);
|
|
56
58
|
case '>':
|
|
57
|
-
return
|
|
59
|
+
return typedValue > (0, _compareAs.compareAs)(type, value);
|
|
58
60
|
case '>=':
|
|
59
|
-
return
|
|
61
|
+
return typedValue >= (0, _compareAs.compareAs)(type, value);
|
|
60
62
|
case '<':
|
|
61
|
-
return
|
|
63
|
+
return typedValue < (0, _compareAs.compareAs)(type, value);
|
|
62
64
|
case '<=':
|
|
63
|
-
return
|
|
65
|
+
return typedValue <= (0, _compareAs.compareAs)(type, value);
|
|
64
66
|
case 'in':
|
|
65
67
|
return Array.isArray(value) && (type ? value.some(item => (0, _compareAs.sameValue)(type, dataValue, item)) : value.includes(dataValue));
|
|
66
68
|
case 'between':
|
|
67
69
|
// A null bound would act as 0 in >= / <=: it bounds nothing, so nothing matches (the parser refuses it)
|
|
68
|
-
return Array.isArray(value) && value.length === 2 && !value.includes(null) &&
|
|
70
|
+
return Array.isArray(value) && value.length === 2 && !value.includes(null) && typedValue >= (0, _compareAs.compareAs)(type, value[0]) && typedValue <= (0, _compareAs.compareAs)(type, value[1]);
|
|
69
71
|
case 'like':
|
|
70
72
|
return likeMatch(dataValue, value);
|
|
71
73
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.where=void 0,require("core-js/modules/es.array.includes.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.some.js");var _compareAs=require("../utilities/compareAs");const likeMatch=(e,r)=>{if("string"!=typeof e||"string"!=typeof r)return!1;const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.where=void 0,require("core-js/modules/es.array.includes.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.filter.js"),require("core-js/modules/esnext.iterator.some.js");var _compareAs=require("../utilities/compareAs");const likeMatch=(e,r)=>{if("string"!=typeof e||"string"!=typeof r)return!1;const s=r.replace(/[.*+?^${}()|[\]\\]/g,"\\$&").replace(/%/g,".*").replace(/_/g,".");return new RegExp(`^${s}$`,"i").test(e)},makeCondition=(e,r,s,t,a=void 0)=>{const o=Object.prototype.hasOwnProperty.call(e,r);switch(s){case"exists":return o;case"does not exist":return!o;case"is null":return o&&null===e[r];case"is not null":return o&&null!==e[r]}if(!o||null===e[r]||null===t)return!1;const c=e[r],n=(0,_compareAs.compareAs)(a,c);switch(s){case"=":return(0,_compareAs.sameValue)(a,c,t);case"!=":case"<>":return!(0,_compareAs.sameValue)(a,c,t);case">":return n>(0,_compareAs.compareAs)(a,t);case">=":return n>=(0,_compareAs.compareAs)(a,t);case"<":return n<(0,_compareAs.compareAs)(a,t);case"<=":return n<=(0,_compareAs.compareAs)(a,t);case"in":return Array.isArray(t)&&(a?t.some((e=>(0,_compareAs.sameValue)(a,c,e))):t.includes(c));case"between":return Array.isArray(t)&&2===t.length&&!t.includes(null)&&n>=(0,_compareAs.compareAs)(a,t[0])&&n<=(0,_compareAs.compareAs)(a,t[1]);case"like":return likeMatch(c,t)}return!1},where=(e=[],{property:r="",joinEntity:s,comparator:t="=",value:a=null,type:o}={})=>e.filter((e=>makeCondition(e,s?`${s}.${r}`:r,t,a,o)));exports.where=where;
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.runQuery = void 0;
|
|
7
7
|
require("core-js/modules/esnext.iterator.constructor.js");
|
|
8
|
+
require("core-js/modules/esnext.iterator.find.js");
|
|
8
9
|
require("core-js/modules/esnext.iterator.reduce.js");
|
|
9
10
|
require("core-js/modules/esnext.set.add-all.js");
|
|
10
11
|
require("core-js/modules/esnext.set.delete-all.js");
|
|
@@ -44,15 +45,15 @@ var _isEntityProperty = require("./parsers/isEntityProperty");
|
|
|
44
45
|
var _splitEntityProperty = require("./parsers/splitEntityProperty");
|
|
45
46
|
var _fieldType = require("./fieldType");
|
|
46
47
|
/**
|
|
47
|
-
* Give each condition its field's declared type, so where
|
|
48
|
-
* is looked up on that entity's record).
|
|
48
|
+
* Give each condition and sort clause its field's declared type, so where and sortBy compare by it
|
|
49
|
+
* (a joined entity's field is looked up on that entity's record).
|
|
49
50
|
* @param parsed
|
|
50
51
|
* @param recordData
|
|
51
52
|
*/
|
|
52
|
-
const
|
|
53
|
-
for (const
|
|
53
|
+
const typeClauses = async (parsed, recordData) => {
|
|
54
|
+
for (const clause of [...parsed.conditions, ...parsed.sortClauses]) {
|
|
54
55
|
let entity = parsed.entity;
|
|
55
|
-
let property =
|
|
56
|
+
let property = clause.property;
|
|
56
57
|
if ((0, _isEntityProperty.isEntityProperty)(property)) {
|
|
57
58
|
({
|
|
58
59
|
entity,
|
|
@@ -62,7 +63,7 @@ const typeConditions = async (parsed, recordData) => {
|
|
|
62
63
|
if (!Object.prototype.hasOwnProperty.call(recordData, entity)) {
|
|
63
64
|
recordData[entity] = await (0, _retrieveRecord.retrieveRecord)(entity);
|
|
64
65
|
}
|
|
65
|
-
|
|
66
|
+
clause.type = (0, _fieldType.fieldType)(recordData[entity], property);
|
|
66
67
|
}
|
|
67
68
|
};
|
|
68
69
|
const runQuery = async parsed => {
|
|
@@ -85,13 +86,23 @@ const runQuery = async parsed => {
|
|
|
85
86
|
[parsed.entity]: await (0, _showRecords.showRecords)()
|
|
86
87
|
};
|
|
87
88
|
}
|
|
89
|
+
// update/delete apply their conditions before any join or merge runs, so a condition on another entity's field
|
|
90
|
+
// can't be checked there. An indexed one used to be dropped once its index had narrowed the joined rows, and the
|
|
91
|
+
// command then hit every row the other conditions allowed (`delete workouts.exercises on ... where
|
|
92
|
+
// exercises._id = 1` deleted every workout)
|
|
93
|
+
if (parsed.command === 'update' || parsed.command === 'delete') {
|
|
94
|
+
const other = parsed.conditions.find(condition => (0, _isEntityProperty.isEntityProperty)(condition.property) && (0, _splitEntityProperty.splitEntityProperty)(condition.property).entity !== parsed.entity);
|
|
95
|
+
if (other) {
|
|
96
|
+
throw new Error(`${parsed.command} can only use conditions on ${parsed.entity}'s own fields, not ${other.property}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
88
99
|
const recordData = {
|
|
89
100
|
[parsed.entity]: await (0, _retrieveRecord.retrieveRecord)(parsed.entity)
|
|
90
101
|
};
|
|
91
102
|
if (typeof parsed.joinEntity !== 'undefined') {
|
|
92
103
|
recordData[parsed.joinEntity] = await (0, _retrieveRecord.retrieveRecord)(parsed.joinEntity);
|
|
93
104
|
}
|
|
94
|
-
await
|
|
105
|
+
await typeClauses(parsed, recordData);
|
|
95
106
|
let dataSet = {
|
|
96
107
|
[parsed.entity]: []
|
|
97
108
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.runQuery=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.reduce.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _deleteEntity=require("../queries/deleteEntity"),_insertEntity=require("../queries/insertEntity"),_readEntity=require("../queries/readEntity"),_updateEntity=require("../queries/updateEntity"),_createRecord=require("../queries/createRecord"),_dropRecord=require("../queries/dropRecord"),_describeRecord=require("../queries/describeRecord"),_showRecords=require("../queries/showRecords"),_joinEntity=require("../queries/joinEntity"),_mergeJoins=require("../queries/mergeJoins"),_where=require("../queries/where"),_sortBy=require("../queries/sortBy"),_groupBy=require("../queries/groupBy"),_limitOffset=require("../queries/limitOffset"),_selectFields=require("../queries/selectFields"),_retrieveRecord=require("./retrieveRecord"),_getConditionIndexedList=require("./getConditionIndexedList"),_getJoinIndexedList=require("./getJoinIndexedList"),_isEntityProperty=require("./parsers/isEntityProperty"),_splitEntityProperty=require("./parsers/splitEntityProperty"),_fieldType=require("./fieldType");const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.runQuery=void 0,require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.find.js"),require("core-js/modules/esnext.iterator.reduce.js"),require("core-js/modules/esnext.set.add-all.js"),require("core-js/modules/esnext.set.delete-all.js"),require("core-js/modules/esnext.set.difference.js"),require("core-js/modules/esnext.set.every.js"),require("core-js/modules/esnext.set.filter.js"),require("core-js/modules/esnext.set.find.js"),require("core-js/modules/esnext.set.intersection.js"),require("core-js/modules/esnext.set.is-disjoint-from.js"),require("core-js/modules/esnext.set.is-subset-of.js"),require("core-js/modules/esnext.set.is-superset-of.js"),require("core-js/modules/esnext.set.join.js"),require("core-js/modules/esnext.set.map.js"),require("core-js/modules/esnext.set.reduce.js"),require("core-js/modules/esnext.set.some.js"),require("core-js/modules/esnext.set.symmetric-difference.js"),require("core-js/modules/esnext.set.union.js");var _deleteEntity=require("../queries/deleteEntity"),_insertEntity=require("../queries/insertEntity"),_readEntity=require("../queries/readEntity"),_updateEntity=require("../queries/updateEntity"),_createRecord=require("../queries/createRecord"),_dropRecord=require("../queries/dropRecord"),_describeRecord=require("../queries/describeRecord"),_showRecords=require("../queries/showRecords"),_joinEntity=require("../queries/joinEntity"),_mergeJoins=require("../queries/mergeJoins"),_where=require("../queries/where"),_sortBy=require("../queries/sortBy"),_groupBy=require("../queries/groupBy"),_limitOffset=require("../queries/limitOffset"),_selectFields=require("../queries/selectFields"),_retrieveRecord=require("./retrieveRecord"),_getConditionIndexedList=require("./getConditionIndexedList"),_getJoinIndexedList=require("./getJoinIndexedList"),_isEntityProperty=require("./parsers/isEntityProperty"),_splitEntityProperty=require("./parsers/splitEntityProperty"),_fieldType=require("./fieldType");const typeClauses=async(e,t)=>{for(const r of[...e.conditions,...e.sortClauses]){let i=e.entity,s=r.property;(0,_isEntityProperty.isEntityProperty)(s)&&({entity:i,property:s}=(0,_splitEntityProperty.splitEntityProperty)(s)),Object.prototype.hasOwnProperty.call(t,i)||(t[i]=await(0,_retrieveRecord.retrieveRecord)(i)),r.type=(0,_fieldType.fieldType)(t[i],s)}},runQuery=async e=>{switch(e.command){case"create":return{[e.entity]:await(0,_createRecord.createRecord)(e.entity,e.create)};case"drop":return{[e.entity]:await(0,_dropRecord.dropRecord)(e.entity,e.ifExists)};case"describe":return{[e.entity]:await(0,_describeRecord.describeRecord)(e.entity)};case"show":return{[e.entity]:await(0,_showRecords.showRecords)()}}if("update"===e.command||"delete"===e.command){const t=e.conditions.find((t=>(0,_isEntityProperty.isEntityProperty)(t.property)&&(0,_splitEntityProperty.splitEntityProperty)(t.property).entity!==e.entity));if(t)throw new Error(`${e.command} can only use conditions on ${e.entity}'s own fields, not ${t.property}`)}const t={[e.entity]:await(0,_retrieveRecord.retrieveRecord)(e.entity)};void 0!==e.joinEntity&&(t[e.joinEntity]=await(0,_retrieveRecord.retrieveRecord)(e.joinEntity)),await typeClauses(e,t);let r={[e.entity]:[]};const i=new Set;e=await(0,_getConditionIndexedList.getConditionIndexedList)(e,t,r,i);const s=i.has(e.entity);switch("delete"!==(e=await(0,_getJoinIndexedList.getJoinIndexedList)(e,t,r)).command&&"update"!==e.command||(s||(r=await(0,_readEntity.readEntity)(e.entity,r)),r[e.entity]=e.conditions.reduce(((e,t)=>(0,_where.where)(e,t)),r[e.entity])),e.command){case"delete":r=await(0,_deleteEntity.deleteEntity)(e.entity,r);break;case"insert":r=await(0,_insertEntity.insertEntity)(e.entity,e.insertValues,r);break;case"read":s||(r=await(0,_readEntity.readEntity)(e.entity,r));break;case"update":r=await(0,_updateEntity.updateEntity)(e.entity,e.updateValues,r);break;default:throw new Error(`Unknown command: ${e.command}`)}return r=await(0,_joinEntity.joinEntity)(e.entity,e.joinEntity,r,e.joinClauses,s),r=await(0,_mergeJoins.mergeJoins)(r,e.mergeJoins),"delete"!==e.command&&"update"!==e.command&&(r[e.entity]=e.conditions.reduce(((e,t)=>(0,_where.where)(e,t)),r[e.entity])),r[e.entity]=(0,_sortBy.sortBy)(r[e.entity],e.sortClauses),r[e.entity]=(0,_limitOffset.limitOffset)(r[e.entity],e.offset,e.limit),r[e.entity]=(0,_groupBy.groupBy)(r[e.entity],e.groupBy),r[e.entity]=(0,_selectFields.selectFields)(r[e.entity],e.selectClauses),r};exports.runQuery=runQuery;
|