json-fs-query 2.3.1 → 3.0.0

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.
Files changed (58) hide show
  1. package/README.md +77 -6
  2. package/browser/jsonFsQuery.js +485 -208
  3. package/browser/jsonFsQuery.min.js +1 -1
  4. package/dist/data/queries/groupBy.d.ts +20 -1
  5. package/dist/data/queries/groupBy.js +71 -9
  6. package/dist/data/queries/groupBy.min.js +1 -1
  7. package/dist/data/queries/limitOffset.d.ts +1 -1
  8. package/dist/data/queries/limitOffset.js +1 -1
  9. package/dist/data/queries/selectFields.d.ts +6 -4
  10. package/dist/data/queries/selectFields.js +15 -10
  11. package/dist/data/queries/selectFields.min.js +1 -1
  12. package/dist/data/utilities/parsers/findCommand.d.ts +2 -1
  13. package/dist/data/utilities/parsers/findCommand.js +4 -4
  14. package/dist/data/utilities/parsers/findCommand.min.js +1 -1
  15. package/dist/data/utilities/parsers/findConditions.d.ts +8 -9
  16. package/dist/data/utilities/parsers/findConditions.js +29 -41
  17. package/dist/data/utilities/parsers/findConditions.min.js +1 -1
  18. package/dist/data/utilities/parsers/findGroupBy.d.ts +6 -4
  19. package/dist/data/utilities/parsers/findGroupBy.js +17 -9
  20. package/dist/data/utilities/parsers/findGroupBy.min.js +1 -1
  21. package/dist/data/utilities/parsers/findInsertValues.d.ts +4 -3
  22. package/dist/data/utilities/parsers/findInsertValues.js +9 -9
  23. package/dist/data/utilities/parsers/findInsertValues.min.js +1 -1
  24. package/dist/data/utilities/parsers/findJoinClauses.d.ts +4 -3
  25. package/dist/data/utilities/parsers/findJoinClauses.js +20 -13
  26. package/dist/data/utilities/parsers/findJoinClauses.min.js +1 -1
  27. package/dist/data/utilities/parsers/findJoinEntity.d.ts +1 -1
  28. package/dist/data/utilities/parsers/findJoinEntity.js +3 -5
  29. package/dist/data/utilities/parsers/findJoinEntity.min.js +1 -1
  30. package/dist/data/utilities/parsers/findLimit.d.ts +4 -3
  31. package/dist/data/utilities/parsers/findLimit.js +8 -8
  32. package/dist/data/utilities/parsers/findLimit.min.js +1 -1
  33. package/dist/data/utilities/parsers/findMergeJoins.d.ts +4 -3
  34. package/dist/data/utilities/parsers/findMergeJoins.js +19 -12
  35. package/dist/data/utilities/parsers/findMergeJoins.min.js +1 -1
  36. package/dist/data/utilities/parsers/findOffset.d.ts +4 -3
  37. package/dist/data/utilities/parsers/findOffset.js +8 -8
  38. package/dist/data/utilities/parsers/findOffset.min.js +1 -1
  39. package/dist/data/utilities/parsers/findSelects.d.ts +4 -3
  40. package/dist/data/utilities/parsers/findSelects.js +13 -14
  41. package/dist/data/utilities/parsers/findSelects.min.js +1 -1
  42. package/dist/data/utilities/parsers/findSortClauses.d.ts +4 -3
  43. package/dist/data/utilities/parsers/findSortClauses.js +12 -12
  44. package/dist/data/utilities/parsers/findSortClauses.min.js +1 -1
  45. package/dist/data/utilities/parsers/findUpdateValues.d.ts +5 -7
  46. package/dist/data/utilities/parsers/findUpdateValues.js +10 -13
  47. package/dist/data/utilities/parsers/findUpdateValues.min.js +1 -1
  48. package/dist/data/utilities/parsers/parseQuery.js +83 -9
  49. package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
  50. package/dist/data/utilities/parsers/splitClauses.d.ts +29 -0
  51. package/dist/data/utilities/parsers/splitClauses.js +139 -0
  52. package/dist/data/utilities/parsers/splitClauses.min.js +1 -0
  53. package/dist/data/utilities/runQuery.js +5 -4
  54. package/dist/data/utilities/runQuery.min.js +1 -1
  55. package/package.json +1 -1
  56. package/dist/data/utilities/parsers/removeFromQuery.d.ts +0 -2
  57. package/dist/data/utilities/parsers/removeFromQuery.js +0 -8
  58. package/dist/data/utilities/parsers/removeFromQuery.min.js +0 -1
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findJoinClauses=void 0;var _removeFromQuery=require("./removeFromQuery");const joinClauseMatch=/(and)?\s*on\s+([a-z0-9_-]+\.[a-z0-9_-]+)\s+(=|!=|>|<|>=|<=|in|between|like)\s+([a-z0-9_-]+\.[a-z0-9_-]+)/gi,findJoinClauses=(e,o)=>{const r=o.matchAll(joinClauseMatch);for(const s of r)e.joinClauses.push({propertyA:s[2],comparator:s[3],propertyB:s[4]}),o=(0,_removeFromQuery.removeFromQuery)(s[0],o);return o};exports.findJoinClauses=findJoinClauses;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findJoinClauses=void 0;const joinClauseMatch=/^([a-z0-9_-]+\.[a-z0-9_-]+)\s+(=|!=|>|<|>=|<=|in|between|like)\s+([a-z0-9_-]+\.[a-z0-9_-]+)(?![a-z0-9._-])/i,nextMatch=/^and\s+on\s+/i,findJoinClauses=(e,t)=>{let s=t;for(let t=s.match(joinClauseMatch);t;t=s.match(joinClauseMatch)){e.joinClauses.push({propertyA:t[1],comparator:t[2],propertyB:t[3]}),s=s.slice(t[0].length).trim();const a=s.match(nextMatch);if(!a||!joinClauseMatch.test(s.slice(a[0].length)))break;s=s.slice(a[0].length)}return s};exports.findJoinClauses=findJoinClauses;
@@ -1,7 +1,7 @@
1
1
  import { ParsedQuery } from './parseQuery';
2
2
  export type ParsedJoinEntity = string;
3
3
  /**
4
- * Extract the main join entity from the query.
4
+ * Read the joined record from what findCommand left of the head.
5
5
  * @param parsed
6
6
  * @param query
7
7
  */
@@ -4,12 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.findJoinEntity = void 0;
7
- var _removeFromQuery = require("./removeFromQuery");
8
- // Only straight after the entity (findCommand leaves `.joined ...`): a `.` later on is a number's (`1.5`) or a
9
- // condition's `entity.field`, not the join
7
+ // What findCommand leaves of the head: `.joined`
10
8
  const joinEntityMatch = /^\.([a-z0-9_-]+)/i;
11
9
  /**
12
- * Extract the main join entity from the query.
10
+ * Read the joined record from what findCommand left of the head.
13
11
  * @param parsed
14
12
  * @param query
15
13
  */
@@ -17,7 +15,7 @@ const findJoinEntity = (parsed, query) => {
17
15
  const joinEntityFound = query.match(joinEntityMatch);
18
16
  if (joinEntityFound) {
19
17
  parsed['joinEntity'] = joinEntityFound ? joinEntityFound[1] : undefined;
20
- return (0, _removeFromQuery.removeFromQuery)(joinEntityFound[0], query);
18
+ return query.slice(joinEntityFound[0].length).trim();
21
19
  }
22
20
  return query;
23
21
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findJoinEntity=void 0;var _removeFromQuery=require("./removeFromQuery");const joinEntityMatch=/^\.([a-z0-9_-]+)/i,findJoinEntity=(t,e)=>{const i=e.match(joinEntityMatch);return i?(t.joinEntity=i?i[1]:void 0,(0,_removeFromQuery.removeFromQuery)(i[0],e)):e};exports.findJoinEntity=findJoinEntity;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findJoinEntity=void 0;const joinEntityMatch=/^\.([a-z0-9_-]+)/i,findJoinEntity=(t,i)=>{const n=i.match(joinEntityMatch);return n?(t.joinEntity=n?n[1]:void 0,i.slice(n[0].length).trim()):i};exports.findJoinEntity=findJoinEntity;
@@ -1,9 +1,10 @@
1
1
  import { ParsedQuery } from './parseQuery';
2
2
  export type ParsedLimit = number;
3
3
  /**
4
- * Extract the limit clauses from the query.
4
+ * Read a limit clause body (a whole number, see splitClauses).
5
5
  * @param parsed
6
- * @param query
6
+ * @param body
7
+ * @returns The rest of the body, after the number.
7
8
  */
8
- export declare const findLimit: (parsed: ParsedQuery, query: string) => string;
9
+ export declare const findLimit: (parsed: ParsedQuery, body: string) => string;
9
10
  //# sourceMappingURL=findLimit.d.ts.map
@@ -4,19 +4,19 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.findLimit = void 0;
7
- var _removeFromQuery = require("./removeFromQuery");
8
- const limitMatch = /limit\s*(\d+)/i;
7
+ const limitMatch = /^(\d+)/;
9
8
  /**
10
- * Extract the limit clauses from the query.
9
+ * Read a limit clause body (a whole number, see splitClauses).
11
10
  * @param parsed
12
- * @param query
11
+ * @param body
12
+ * @returns The rest of the body, after the number.
13
13
  */
14
- const findLimit = (parsed, query) => {
15
- const limitFound = query.match(limitMatch);
14
+ const findLimit = (parsed, body) => {
15
+ const limitFound = body.match(limitMatch);
16
16
  if (limitFound) {
17
17
  parsed['limit'] = limitFound ? parseInt(limitFound[1]) : undefined;
18
- return (0, _removeFromQuery.removeFromQuery)(limitFound[0], query);
18
+ return body.slice(limitFound[0].length).trim();
19
19
  }
20
- return query;
20
+ return body;
21
21
  };
22
22
  exports.findLimit = findLimit;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findLimit=void 0;var _removeFromQuery=require("./removeFromQuery");const limitMatch=/limit\s*(\d+)/i,findLimit=(e,i)=>{const r=i.match(limitMatch);return r?(e.limit=r?parseInt(r[1]):void 0,(0,_removeFromQuery.removeFromQuery)(r[0],i)):i};exports.findLimit=findLimit;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findLimit=void 0;const limitMatch=/^(\d+)/,findLimit=(i,t)=>{const e=t.match(limitMatch);return e?(i.limit=e?parseInt(e[1]):void 0,t.slice(e[0].length).trim()):t};exports.findLimit=findLimit;
@@ -4,9 +4,10 @@ export type ParsedMergeJoin = {
4
4
  propertyB: string;
5
5
  };
6
6
  /**
7
- * Extract merge-join clauses from the query.
7
+ * Read a merge clause body (`a.x with b.y merge c.z with d.w`, see splitClauses).
8
8
  * @param parsed
9
- * @param query
9
+ * @param body
10
+ * @returns The rest of the body, after the last merge.
10
11
  */
11
- export declare const findMergeJoins: (parsed: ParsedQuery, query: string) => string;
12
+ export declare const findMergeJoins: (parsed: ParsedQuery, body: string) => string;
12
13
  //# sourceMappingURL=findMergeJoins.d.ts.map
@@ -4,23 +4,30 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.findMergeJoins = void 0;
7
- var _removeFromQuery = require("./removeFromQuery");
8
- const mergeJoinMatch = /(and)?\s*merge\s+([a-z0-9_-]+\.[a-z0-9_-]+)\s+with\s+([a-z0-9_-]+\.[a-z0-9_-]+)/ig;
7
+ // One merge, at the start of the text; every one after the first starts with `merge` or `and merge` (see splitClauses)
8
+ const mergeJoinMatch = /^([a-z0-9_-]+\.[a-z0-9_-]+)\s+with\s+([a-z0-9_-]+\.[a-z0-9_-]+)(?![a-z0-9._-])/i;
9
+ const nextMatch = /^(?:and\s+)?merge\s+/i;
9
10
  /**
10
- * Extract merge-join clauses from the query.
11
+ * Read a merge clause body (`a.x with b.y merge c.z with d.w`, see splitClauses).
11
12
  * @param parsed
12
- * @param query
13
+ * @param body
14
+ * @returns The rest of the body, after the last merge.
13
15
  */
14
- const findMergeJoins = (parsed, query) => {
15
- const mergeJoinsFound = query.matchAll(mergeJoinMatch);
16
- // @ts-ignore
17
- for (const mergeJoin of mergeJoinsFound) {
16
+ const findMergeJoins = (parsed, body) => {
17
+ let rest = body;
18
+ for (let mergeJoin = rest.match(mergeJoinMatch); mergeJoin; mergeJoin = rest.match(mergeJoinMatch)) {
18
19
  parsed['mergeJoins'].push({
19
- propertyA: mergeJoin[2],
20
- propertyB: mergeJoin[3]
20
+ propertyA: mergeJoin[1],
21
+ propertyB: mergeJoin[2]
21
22
  });
22
- query = (0, _removeFromQuery.removeFromQuery)(mergeJoin[0].trim(), query);
23
+ rest = rest.slice(mergeJoin[0].length).trim();
24
+ // The connector only with another one after it, so a bad one is shown with its connector
25
+ const next = rest.match(nextMatch);
26
+ if (!next || !mergeJoinMatch.test(rest.slice(next[0].length))) {
27
+ break;
28
+ }
29
+ rest = rest.slice(next[0].length);
23
30
  }
24
- return query;
31
+ return rest;
25
32
  };
26
33
  exports.findMergeJoins = findMergeJoins;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findMergeJoins=void 0;var _removeFromQuery=require("./removeFromQuery");const mergeJoinMatch=/(and)?\s*merge\s+([a-z0-9_-]+\.[a-z0-9_-]+)\s+with\s+([a-z0-9_-]+\.[a-z0-9_-]+)/gi,findMergeJoins=(e,r)=>{const o=r.matchAll(mergeJoinMatch);for(const s of o)e.mergeJoins.push({propertyA:s[2],propertyB:s[3]}),r=(0,_removeFromQuery.removeFromQuery)(s[0].trim(),r);return r};exports.findMergeJoins=findMergeJoins;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findMergeJoins=void 0;const mergeJoinMatch=/^([a-z0-9_-]+\.[a-z0-9_-]+)\s+with\s+([a-z0-9_-]+\.[a-z0-9_-]+)(?![a-z0-9._-])/i,nextMatch=/^(?:and\s+)?merge\s+/i,findMergeJoins=(e,t)=>{let r=t;for(let t=r.match(mergeJoinMatch);t;t=r.match(mergeJoinMatch)){e.mergeJoins.push({propertyA:t[1],propertyB:t[2]}),r=r.slice(t[0].length).trim();const i=r.match(nextMatch);if(!i||!mergeJoinMatch.test(r.slice(i[0].length)))break;r=r.slice(i[0].length)}return r};exports.findMergeJoins=findMergeJoins;
@@ -1,9 +1,10 @@
1
1
  import { ParsedQuery } from './parseQuery';
2
2
  export type ParsedOffset = number;
3
3
  /**
4
- * Extract the offset clauses from the query.
4
+ * Read a offset clause body (a whole number, see splitClauses).
5
5
  * @param parsed
6
- * @param query
6
+ * @param body
7
+ * @returns The rest of the body, after the number.
7
8
  */
8
- export declare const findOffset: (parsed: ParsedQuery, query: string) => string;
9
+ export declare const findOffset: (parsed: ParsedQuery, body: string) => string;
9
10
  //# sourceMappingURL=findOffset.d.ts.map
@@ -4,19 +4,19 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.findOffset = void 0;
7
- var _removeFromQuery = require("./removeFromQuery");
8
- const offsetMatch = /offset\s*(\d+)/i;
7
+ const offsetMatch = /^(\d+)/;
9
8
  /**
10
- * Extract the offset clauses from the query.
9
+ * Read a offset clause body (a whole number, see splitClauses).
11
10
  * @param parsed
12
- * @param query
11
+ * @param body
12
+ * @returns The rest of the body, after the number.
13
13
  */
14
- const findOffset = (parsed, query) => {
15
- const offsetFound = query.match(offsetMatch);
14
+ const findOffset = (parsed, body) => {
15
+ const offsetFound = body.match(offsetMatch);
16
16
  if (offsetFound) {
17
17
  parsed['offset'] = offsetFound ? parseInt(offsetFound[1]) : undefined;
18
- return (0, _removeFromQuery.removeFromQuery)(offsetFound[0], query);
18
+ return body.slice(offsetFound[0].length).trim();
19
19
  }
20
- return query;
20
+ return body;
21
21
  };
22
22
  exports.findOffset = findOffset;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findOffset=void 0;var _removeFromQuery=require("./removeFromQuery");const offsetMatch=/offset\s*(\d+)/i,findOffset=(e,r)=>{const t=r.match(offsetMatch);return t?(e.offset=t?parseInt(t[1]):void 0,(0,_removeFromQuery.removeFromQuery)(t[0],r)):r};exports.findOffset=findOffset;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findOffset=void 0;const offsetMatch=/^(\d+)/,findOffset=(t,e)=>{const f=e.match(offsetMatch);return f?(t.offset=f?parseInt(f[1]):void 0,e.slice(f[0].length).trim()):e};exports.findOffset=findOffset;
@@ -4,9 +4,10 @@ export type ParsedSelect = {
4
4
  alias: string | undefined;
5
5
  };
6
6
  /**
7
- * Extract select clauses from the query.
7
+ * Read a select clause body (`a, b as c`, see splitClauses).
8
8
  * @param parsed
9
- * @param query
9
+ * @param body
10
+ * @returns The rest of the body, after the last field.
10
11
  */
11
- export declare const findSelects: (parsed: ParsedQuery, query: string) => string;
12
+ export declare const findSelects: (parsed: ParsedQuery, body: string) => string;
12
13
  //# sourceMappingURL=findSelects.d.ts.map
@@ -4,30 +4,29 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.findSelects = void 0;
7
- var _removeFromQuery = require("./removeFromQuery");
8
- // One field is a name, then optionally `as <alias>` (`as` as a whole word); fields are separated by commas. The first
9
- // field used to accept an alias without `as`, so in `select name where a = 1` the word `where` became the alias.
7
+ // One field is a name, then optionally `as <alias>` (`as` as a whole word); fields are separated by commas
10
8
  const selectField = '[a-z0-9=._-]+(?:\\s+as\\s+[a-z0-9_-]+)?';
11
- const selectClausesMatch = new RegExp(`select\\s+${selectField}(?:\\s*,\\s*${selectField})*`, 'i');
12
- const selectClauseMatch = /(select)?\s*,?\s*([a-z0-9=._-]+)(?:\s+as\s+([a-z0-9_-]+))?/ig;
9
+ const selectsMatch = new RegExp(`^${selectField}(?:\\s*,\\s*${selectField})*`, 'i');
10
+ const selectFieldMatch = /,?\s*([a-z0-9=._-]+)(?:\s+as\s+([a-z0-9_-]+))?/ig;
13
11
  /**
14
- * Extract select clauses from the query.
12
+ * Read a select clause body (`a, b as c`, see splitClauses).
15
13
  * @param parsed
16
- * @param query
14
+ * @param body
15
+ * @returns The rest of the body, after the last field.
17
16
  */
18
- const findSelects = (parsed, query) => {
19
- const selectsFound = query.match(selectClausesMatch);
17
+ const findSelects = (parsed, body) => {
18
+ const selectsFound = body.match(selectsMatch);
20
19
  if (selectsFound) {
21
- const selectClausesFound = selectsFound[0].matchAll(selectClauseMatch);
20
+ const selectClausesFound = selectsFound[0].matchAll(selectFieldMatch);
22
21
  // @ts-ignore
23
22
  for (const selectClause of selectClausesFound) {
24
23
  parsed['selectClauses'].push({
25
- property: selectClause[2],
26
- alias: selectClause[3]
24
+ property: selectClause[1],
25
+ alias: selectClause[2]
27
26
  });
28
27
  }
29
- return (0, _removeFromQuery.removeFromQuery)(selectsFound[0], query);
28
+ return body.slice(selectsFound[0].length).trim();
30
29
  }
31
- return query;
30
+ return body;
32
31
  };
33
32
  exports.findSelects = findSelects;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findSelects=void 0;var _removeFromQuery=require("./removeFromQuery");const selectField="[a-z0-9=._-]+(?:\\s+as\\s+[a-z0-9_-]+)?",selectClausesMatch=new RegExp(`select\\s+${selectField}(?:\\s*,\\s*${selectField})*`,"i"),selectClauseMatch=/(select)?\s*,?\s*([a-z0-9=._-]+)(?:\s+as\s+([a-z0-9_-]+))?/gi,findSelects=(e,s)=>{const t=s.match(selectClausesMatch);if(t){const r=t[0].matchAll(selectClauseMatch);for(const s of r)e.selectClauses.push({property:s[2],alias:s[3]});return(0,_removeFromQuery.removeFromQuery)(t[0],s)}return s};exports.findSelects=findSelects;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findSelects=void 0;const selectField="[a-z0-9=._-]+(?:\\s+as\\s+[a-z0-9_-]+)?",selectsMatch=new RegExp(`^${selectField}(?:\\s*,\\s*${selectField})*`,"i"),selectFieldMatch=/,?\s*([a-z0-9=._-]+)(?:\s+as\s+([a-z0-9_-]+))?/gi,findSelects=(e,s)=>{const t=s.match(selectsMatch);if(t){const c=t[0].matchAll(selectFieldMatch);for(const s of c)e.selectClauses.push({property:s[1],alias:s[2]});return s.slice(t[0].length).trim()}return s};exports.findSelects=findSelects;
@@ -5,9 +5,10 @@ export type ParsedSortClause = {
5
5
  type?: string;
6
6
  };
7
7
  /**
8
- * Extract sort clauses from the query.
8
+ * Read a sort clause body (`a, b desc`, see splitClauses).
9
9
  * @param parsed
10
- * @param query
10
+ * @param body
11
+ * @returns The rest of the body, after the last rule.
11
12
  */
12
- export declare const findSortClauses: (parsed: ParsedQuery, query: string) => string;
13
+ export declare const findSortClauses: (parsed: ParsedQuery, body: string) => string;
13
14
  //# sourceMappingURL=findSortClauses.d.ts.map
@@ -4,30 +4,30 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.findSortClauses = void 0;
7
- var _removeFromQuery = require("./removeFromQuery");
8
7
  // One rule is a field, then optionally asc or desc as a whole word. Rules are separated by commas, so the list ends
9
- // at the first word that doesn't follow a comma: in `sort a limit 1`, `limit` starts the next clause.
8
+ // at the first word that doesn't follow a comma: in `sort a b`, `b` is left over.
10
9
  const sortRule = '[a-z0-9._-]+(?:\\s+(?:asc|desc)(?![a-z0-9._-]))?';
11
- const sortMatch = new RegExp(`sort\\s+${sortRule}(?:\\s*,\\s*${sortRule})*`, 'i');
12
- const sortRuleMatch = /(sort)?\s*,?\s*([a-z0-9._-]+)(?:\s+(asc|desc)(?![a-z0-9._-]))?/ig;
10
+ const sortMatch = new RegExp(`^${sortRule}(?:\\s*,\\s*${sortRule})*`, 'i');
11
+ const sortRuleMatch = /,?\s*([a-z0-9._-]+)(?:\s+(asc|desc)(?![a-z0-9._-]))?/ig;
13
12
  /**
14
- * Extract sort clauses from the query.
13
+ * Read a sort clause body (`a, b desc`, see splitClauses).
15
14
  * @param parsed
16
- * @param query
15
+ * @param body
16
+ * @returns The rest of the body, after the last rule.
17
17
  */
18
- const findSortClauses = (parsed, query) => {
19
- const sortFound = query.match(sortMatch);
18
+ const findSortClauses = (parsed, body) => {
19
+ const sortFound = body.match(sortMatch);
20
20
  if (sortFound) {
21
21
  const sortRulesFound = sortFound[0].matchAll(sortRuleMatch);
22
22
  // @ts-ignore
23
23
  for (const sortClause of sortRulesFound) {
24
24
  parsed['sortClauses'].push({
25
- property: sortClause[2],
26
- direction: (sortClause[3] || 'asc').toLowerCase()
25
+ property: sortClause[1],
26
+ direction: (sortClause[2] || 'asc').toLowerCase()
27
27
  });
28
28
  }
29
- return (0, _removeFromQuery.removeFromQuery)(sortFound[0], query);
29
+ return body.slice(sortFound[0].length).trim();
30
30
  }
31
- return query;
31
+ return body;
32
32
  };
33
33
  exports.findSortClauses = findSortClauses;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findSortClauses=void 0;var _removeFromQuery=require("./removeFromQuery");const sortRule="[a-z0-9._-]+(?:\\s+(?:asc|desc)(?![a-z0-9._-]))?",sortMatch=new RegExp(`sort\\s+${sortRule}(?:\\s*,\\s*${sortRule})*`,"i"),sortRuleMatch=/(sort)?\s*,?\s*([a-z0-9._-]+)(?:\s+(asc|desc)(?![a-z0-9._-]))?/gi,findSortClauses=(e,r)=>{const s=r.match(sortMatch);if(s){const o=s[0].matchAll(sortRuleMatch);for(const r of o)e.sortClauses.push({property:r[2],direction:(r[3]||"asc").toLowerCase()});return(0,_removeFromQuery.removeFromQuery)(s[0],r)}return r};exports.findSortClauses=findSortClauses;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findSortClauses=void 0;const sortRule="[a-z0-9._-]+(?:\\s+(?:asc|desc)(?![a-z0-9._-]))?",sortMatch=new RegExp(`^${sortRule}(?:\\s*,\\s*${sortRule})*`,"i"),sortRuleMatch=/,?\s*([a-z0-9._-]+)(?:\s+(asc|desc)(?![a-z0-9._-]))?/gi,findSortClauses=(s,t)=>{const e=t.match(sortMatch);if(e){const o=e[0].matchAll(sortRuleMatch);for(const t of o)s.sortClauses.push({property:t[1],direction:(t[2]||"asc").toLowerCase()});return t.slice(e[0].length).trim()}return t};exports.findSortClauses=findSortClauses;
@@ -3,13 +3,11 @@ export type ParsedUpdateValues = {
3
3
  [field: string]: any;
4
4
  };
5
5
  /**
6
- * Extract an update's "set field = value, field2 = value2" clause from the query. Uses a two-pass
7
- * match, unlike the other parsers here: the set clause's own boundary is found first (so it can
8
- * be removed from the query as a whole, and so the comma-separated list doesn't get confused with
9
- * anything that follows, like a where clause), then each individual assignment is parsed out of
10
- * that captured substring.
6
+ * Read an update's set clause body (`field = value, field2 = value2`, see splitClauses). Uses a two-pass match: the
7
+ * whole comma-separated list first, so anything after it is left over, then each assignment out of that list.
11
8
  * @param parsed
12
- * @param query
9
+ * @param body
10
+ * @returns The rest of the body, after the last assignment.
13
11
  */
14
- export declare const findUpdateValues: (parsed: ParsedQuery, query: string) => string;
12
+ export declare const findUpdateValues: (parsed: ParsedQuery, body: string) => string;
15
13
  //# sourceMappingURL=findUpdateValues.d.ts.map
@@ -4,32 +4,29 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.findUpdateValues = void 0;
7
- var _removeFromQuery = require("./removeFromQuery");
8
7
  var _parseLiteralValue = require("./parseLiteralValue");
9
8
  var _maskStrings = require("./maskStrings");
10
9
  const literal = `(?:${_maskStrings.placeholderSource.replace('(', '(?:')}|${_parseLiteralValue.numberSource}|${_maskStrings.arraySource.replace('(', '(?:')}|null|true|false)`;
11
- const setClauseMatch = new RegExp(`(set)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i');
10
+ const setMatch = new RegExp(`^([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i');
12
11
  const assignmentMatch = new RegExp(`([a-z0-9_-]+)\\s*=\\s*(${_maskStrings.placeholderSource}|(${_parseLiteralValue.numberSource})|${_maskStrings.arraySource}|(null)|(true)|(false))`, 'ig');
13
12
  /**
14
- * Extract an update's "set field = value, field2 = value2" clause from the query. Uses a two-pass
15
- * match, unlike the other parsers here: the set clause's own boundary is found first (so it can
16
- * be removed from the query as a whole, and so the comma-separated list doesn't get confused with
17
- * anything that follows, like a where clause), then each individual assignment is parsed out of
18
- * that captured substring.
13
+ * Read an update's set clause body (`field = value, field2 = value2`, see splitClauses). Uses a two-pass match: the
14
+ * whole comma-separated list first, so anything after it is left over, then each assignment out of that list.
19
15
  * @param parsed
20
- * @param query
16
+ * @param body
17
+ * @returns The rest of the body, after the last assignment.
21
18
  */
22
- const findUpdateValues = (parsed, query) => {
23
- const clauseFound = query.match(setClauseMatch);
19
+ const findUpdateValues = (parsed, body) => {
20
+ const clauseFound = body.match(setMatch);
24
21
  parsed['updateValues'] = {};
25
22
  if (!clauseFound) {
26
- return query;
23
+ return body;
27
24
  }
28
- const assignmentsFound = clauseFound[2].matchAll(assignmentMatch);
25
+ const assignmentsFound = clauseFound[1].matchAll(assignmentMatch);
29
26
  // @ts-ignore
30
27
  for (const assignment of assignmentsFound) {
31
28
  parsed['updateValues'][assignment[1]] = (0, _parseLiteralValue.parseLiteralValue)(assignment, 3);
32
29
  }
33
- return (0, _removeFromQuery.removeFromQuery)(clauseFound[0], query);
30
+ return body.slice(clauseFound[0].length).trim();
34
31
  };
35
32
  exports.findUpdateValues = findUpdateValues;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findUpdateValues=void 0;var _removeFromQuery=require("./removeFromQuery"),_parseLiteralValue=require("./parseLiteralValue"),_maskStrings=require("./maskStrings");const literal=`(?:${_maskStrings.placeholderSource.replace("(","(?:")}|${_parseLiteralValue.numberSource}|${_maskStrings.arraySource.replace("(","(?:")}|null|true|false)`,setClauseMatch=new RegExp(`(set)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`,"i"),assignmentMatch=new RegExp(`([a-z0-9_-]+)\\s*=\\s*(${_maskStrings.placeholderSource}|(${_parseLiteralValue.numberSource})|${_maskStrings.arraySource}|(null)|(true)|(false))`,"ig"),findUpdateValues=(e,r)=>{const a=r.match(setClauseMatch);if(e.updateValues={},!a)return r;const s=a[2].matchAll(assignmentMatch);for(const r of s)e.updateValues[r[1]]=(0,_parseLiteralValue.parseLiteralValue)(r,3);return(0,_removeFromQuery.removeFromQuery)(a[0],r)};exports.findUpdateValues=findUpdateValues;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findUpdateValues=void 0;var _parseLiteralValue=require("./parseLiteralValue"),_maskStrings=require("./maskStrings");const literal=`(?:${_maskStrings.placeholderSource.replace("(","(?:")}|${_parseLiteralValue.numberSource}|${_maskStrings.arraySource.replace("(","(?:")}|null|true|false)`,setMatch=new RegExp(`^([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`,"i"),assignmentMatch=new RegExp(`([a-z0-9_-]+)\\s*=\\s*(${_maskStrings.placeholderSource}|(${_parseLiteralValue.numberSource})|${_maskStrings.arraySource}|(null)|(true)|(false))`,"ig"),findUpdateValues=(e,a)=>{const r=a.match(setMatch);if(e.updateValues={},!r)return a;const s=r[1].matchAll(assignmentMatch);for(const a of s)e.updateValues[a[1]]=(0,_parseLiteralValue.parseLiteralValue)(a,3);return a.slice(r[0].length).trim()};exports.findUpdateValues=findUpdateValues;
@@ -4,13 +4,13 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.parseQuery = void 0;
7
- var _siFunciona = _interopRequireDefault(require("si-funciona"));
8
7
  var _findCommand = require("./findCommand");
9
8
  var _findInsertValues = require("./findInsertValues");
10
9
  var _findUpdateValues = require("./findUpdateValues");
11
10
  var _findJoinEntity = require("./findJoinEntity");
12
11
  var _findSelects = require("./findSelects");
13
12
  var _findConditions = require("./findConditions");
13
+ var _conditionTree = require("../conditionTree");
14
14
  var _findJoinClauses = require("./findJoinClauses");
15
15
  var _findMergeJoins = require("./findMergeJoins");
16
16
  var _findSortClauses = require("./findSortClauses");
@@ -20,8 +20,63 @@ var _findOffset = require("./findOffset");
20
20
  var _maskStrings = require("./maskStrings");
21
21
  var _parseCreate = require("./parseCreate");
22
22
  var _parseSchemaStatement = require("./parseSchemaStatement");
23
+ var _splitClauses = require("./splitClauses");
23
24
  var _startsQuery = require("./startsQuery");
24
- function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
25
+ // Each clause's own step, and what its body must start with (for the error when it doesn't)
26
+ const clauseSteps = {
27
+ values: {
28
+ step: _findInsertValues.findInsertValues,
29
+ expected: 'an assignment (field = value)'
30
+ },
31
+ set: {
32
+ step: _findUpdateValues.findUpdateValues,
33
+ expected: 'an assignment (field = value)'
34
+ },
35
+ select: {
36
+ step: _findSelects.findSelects,
37
+ expected: 'a field'
38
+ },
39
+ on: {
40
+ step: _findJoinClauses.findJoinClauses,
41
+ expected: 'a join condition (a.x = b.y)'
42
+ },
43
+ merge: {
44
+ step: _findMergeJoins.findMergeJoins,
45
+ expected: 'a merge (a.x with b.y)'
46
+ },
47
+ where: {
48
+ step: _findConditions.findConditions,
49
+ expected: 'a condition'
50
+ },
51
+ 'group by': {
52
+ step: _findGroupBy.findGroupBy,
53
+ expected: 'a field'
54
+ },
55
+ sort: {
56
+ step: _findSortClauses.findSortClauses,
57
+ expected: 'a field'
58
+ },
59
+ limit: {
60
+ step: _findLimit.findLimit,
61
+ expected: 'a whole number'
62
+ },
63
+ offset: {
64
+ step: _findOffset.findOffset,
65
+ expected: 'a whole number'
66
+ }
67
+ };
68
+ /**
69
+ * The error for text a step couldn't read: another query run on without a `;`, or text that doesn't belong.
70
+ * @param rest The text left over, masked
71
+ * @param after What was read before it, masked
72
+ */
73
+ const leftoverError = (rest, after) => {
74
+ const shown = text => (0, _maskStrings.unmaskStrings)(text, '\'');
75
+ if (_startsQuery.startsQueryMatch.test(rest)) {
76
+ return new Error(`Missing ; before: ${shown(rest)}`);
77
+ }
78
+ return new Error(`Unexpected "${shown(rest)}" after "${shown(after)}"`);
79
+ };
25
80
  /**
26
81
  * Break a query down into its components.
27
82
  * @param query
@@ -44,10 +99,6 @@ const parseQuery = query => {
44
99
  create: undefined,
45
100
  ifExists: undefined
46
101
  };
47
- const {
48
- curry,
49
- pipe
50
- } = _siFunciona.default;
51
102
  // No find* step may see inside a string or an array: each one becomes a placeholder holding its value
52
103
  query = (0, _maskStrings.maskArrays)((0, _maskStrings.maskStrings)(query));
53
104
  // A create statement has its own shape (a bracketed list of fields and keys), so it gets its own parser
@@ -65,13 +116,36 @@ const parseQuery = query => {
65
116
  if (_parseSchemaStatement.schemaStatementMatch.test(query)) {
66
117
  return Object.assign(parsedQuery, (0, _parseSchemaStatement.parseSchemaStatement)(query));
67
118
  }
68
- query = pipe(curry(_findCommand.findCommand)(parsedQuery), curry(_findInsertValues.findInsertValues)(parsedQuery), curry(_findUpdateValues.findUpdateValues)(parsedQuery), curry(_findJoinEntity.findJoinEntity)(parsedQuery), curry(_findSelects.findSelects)(parsedQuery), curry(_findConditions.findConditions)(parsedQuery), curry(_findJoinClauses.findJoinClauses)(parsedQuery), curry(_findMergeJoins.findMergeJoins)(parsedQuery), curry(_findSortClauses.findSortClauses)(parsedQuery), curry(_findGroupBy.findGroupBy)(parsedQuery), curry(_findLimit.findLimit)(parsedQuery), curry(_findOffset.findOffset)(parsedQuery))(query);
69
- if (query) {
119
+ // Clauses come at most once each, in a fixed order (see clauseOrder); each step reads only its own clause's body
120
+ const split = (0, _splitClauses.splitClauses)(query);
121
+ if (!split) {
122
+ query = query.trim();
70
123
  if (_startsQuery.startsQueryMatch.test(query)) {
71
- throw new Error(`Missing ; before: ${(0, _maskStrings.unmaskStrings)(query.trim(), '\'')}`);
124
+ throw new Error(`Missing ; before: ${(0, _maskStrings.unmaskStrings)(query, '\'')}`);
72
125
  }
73
126
  throw new Error(`Unrecognized query value: ${(0, _maskStrings.unmaskStrings)(query, '\'')}`);
74
127
  }
128
+ (0, _findJoinEntity.findJoinEntity)(parsedQuery, (0, _findCommand.findCommand)(parsedQuery, split.head));
129
+ parsedQuery.where = (0, _conditionTree.allOf)([]);
130
+ if (split.leading) {
131
+ throw leftoverError(split.leading, split.head);
132
+ }
133
+ for (const {
134
+ keyword,
135
+ body
136
+ } of split.clauses) {
137
+ const {
138
+ step,
139
+ expected
140
+ } = clauseSteps[keyword];
141
+ const rest = step(parsedQuery, body);
142
+ if (rest === body) {
143
+ throw new Error(`Missing ${expected} after ${keyword}${body ? `: ${(0, _maskStrings.unmaskStrings)(body, '\'')}` : ''}`);
144
+ }
145
+ if (rest) {
146
+ throw leftoverError(rest, `${keyword} ${body.slice(0, body.length - rest.length).trim()}`);
147
+ }
148
+ }
75
149
  return parsedQuery;
76
150
  };
77
151
  exports.parseQuery = parseQuery;
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseQuery=void 0;var _siFunciona=_interopRequireDefault(require("si-funciona")),_findCommand=require("./findCommand"),_findInsertValues=require("./findInsertValues"),_findUpdateValues=require("./findUpdateValues"),_findJoinEntity=require("./findJoinEntity"),_findSelects=require("./findSelects"),_findConditions=require("./findConditions"),_findJoinClauses=require("./findJoinClauses"),_findMergeJoins=require("./findMergeJoins"),_findSortClauses=require("./findSortClauses"),_findGroupBy=require("./findGroupBy"),_findLimit=require("./findLimit"),_findOffset=require("./findOffset"),_maskStrings=require("./maskStrings"),_parseCreate=require("./parseCreate"),_parseSchemaStatement=require("./parseSchemaStatement"),_startsQuery=require("./startsQuery");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const parseQuery=e=>{const i={command:void 0,entity:void 0,joinEntity:void 0,selectClauses:[],insertValues:[],updateValues:{},where:void 0,joinClauses:[],mergeJoins:[],sortClauses:[],groupBy:void 0,limit:void 0,offset:void 0,create:void 0,ifExists:void 0},{curry:r,pipe:n}=_siFunciona.default;if(e=(0,_maskStrings.maskArrays)((0,_maskStrings.maskStrings)(e)),_parseCreate.createMatch.test(e)){const{entity:r,create:n}=(0,_parseCreate.parseCreate)(e);return Object.assign(i,{command:"create",entity:r,create:n})}if(_parseSchemaStatement.schemaStatementMatch.test(e))return Object.assign(i,(0,_parseSchemaStatement.parseSchemaStatement)(e));if(e=n(r(_findCommand.findCommand)(i),r(_findInsertValues.findInsertValues)(i),r(_findUpdateValues.findUpdateValues)(i),r(_findJoinEntity.findJoinEntity)(i),r(_findSelects.findSelects)(i),r(_findConditions.findConditions)(i),r(_findJoinClauses.findJoinClauses)(i),r(_findMergeJoins.findMergeJoins)(i),r(_findSortClauses.findSortClauses)(i),r(_findGroupBy.findGroupBy)(i),r(_findLimit.findLimit)(i),r(_findOffset.findOffset)(i))(e)){if(_startsQuery.startsQueryMatch.test(e))throw new Error(`Missing ; before: ${(0,_maskStrings.unmaskStrings)(e.trim(),"'")}`);throw new Error(`Unrecognized query value: ${(0,_maskStrings.unmaskStrings)(e,"'")}`)}return i};exports.parseQuery=parseQuery;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.parseQuery=void 0;var _findCommand=require("./findCommand"),_findInsertValues=require("./findInsertValues"),_findUpdateValues=require("./findUpdateValues"),_findJoinEntity=require("./findJoinEntity"),_findSelects=require("./findSelects"),_findConditions=require("./findConditions"),_conditionTree=require("../conditionTree"),_findJoinClauses=require("./findJoinClauses"),_findMergeJoins=require("./findMergeJoins"),_findSortClauses=require("./findSortClauses"),_findGroupBy=require("./findGroupBy"),_findLimit=require("./findLimit"),_findOffset=require("./findOffset"),_maskStrings=require("./maskStrings"),_parseCreate=require("./parseCreate"),_parseSchemaStatement=require("./parseSchemaStatement"),_splitClauses=require("./splitClauses"),_startsQuery=require("./startsQuery");const clauseSteps={values:{step:_findInsertValues.findInsertValues,expected:"an assignment (field = value)"},set:{step:_findUpdateValues.findUpdateValues,expected:"an assignment (field = value)"},select:{step:_findSelects.findSelects,expected:"a field"},on:{step:_findJoinClauses.findJoinClauses,expected:"a join condition (a.x = b.y)"},merge:{step:_findMergeJoins.findMergeJoins,expected:"a merge (a.x with b.y)"},where:{step:_findConditions.findConditions,expected:"a condition"},"group by":{step:_findGroupBy.findGroupBy,expected:"a field"},sort:{step:_findSortClauses.findSortClauses,expected:"a field"},limit:{step:_findLimit.findLimit,expected:"a whole number"},offset:{step:_findOffset.findOffset,expected:"a whole number"}},leftoverError=(e,t)=>{const i=e=>(0,_maskStrings.unmaskStrings)(e,"'");return _startsQuery.startsQueryMatch.test(e)?new Error(`Missing ; before: ${i(e)}`):new Error(`Unexpected "${i(e)}" after "${i(t)}"`)},parseQuery=e=>{const t={command:void 0,entity:void 0,joinEntity:void 0,selectClauses:[],insertValues:[],updateValues:{},where:void 0,joinClauses:[],mergeJoins:[],sortClauses:[],groupBy:void 0,limit:void 0,offset:void 0,create:void 0,ifExists:void 0};if(e=(0,_maskStrings.maskArrays)((0,_maskStrings.maskStrings)(e)),_parseCreate.createMatch.test(e)){const{entity:i,create:r}=(0,_parseCreate.parseCreate)(e);return Object.assign(t,{command:"create",entity:i,create:r})}if(_parseSchemaStatement.schemaStatementMatch.test(e))return Object.assign(t,(0,_parseSchemaStatement.parseSchemaStatement)(e));const i=(0,_splitClauses.splitClauses)(e);if(!i){if(e=e.trim(),_startsQuery.startsQueryMatch.test(e))throw new Error(`Missing ; before: ${(0,_maskStrings.unmaskStrings)(e,"'")}`);throw new Error(`Unrecognized query value: ${(0,_maskStrings.unmaskStrings)(e,"'")}`)}if((0,_findJoinEntity.findJoinEntity)(t,(0,_findCommand.findCommand)(t,i.head)),t.where=(0,_conditionTree.allOf)([]),i.leading)throw leftoverError(i.leading,i.head);for(const{keyword:e,body:r}of i.clauses){const{step:i,expected:s}=clauseSteps[e],n=i(t,r);if(n===r)throw new Error(`Missing ${s} after ${e}${r?`: ${(0,_maskStrings.unmaskStrings)(r,"'")}`:""}`);if(n)throw leftoverError(n,`${e} ${r.slice(0,r.length-n.length).trim()}`)}return t};exports.parseQuery=parseQuery;
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The clauses each command allows, in the order they must come. create, drop, describe and show have their own
3
+ * parsers and never get here.
4
+ */
5
+ export declare const clauseOrder: {
6
+ [command: string]: string[];
7
+ };
8
+ export declare const whereHint = "use and / or inside one where clause (where a = 1 and b = 2)";
9
+ export type SplitClause = {
10
+ keyword: string;
11
+ body: string;
12
+ };
13
+ export type SplitQuery = {
14
+ command: string;
15
+ head: string;
16
+ leading: string;
17
+ clauses: SplitClause[];
18
+ };
19
+ /**
20
+ * Split a masked query (see maskStrings) into its clauses, reading its top-level words once, left to right. A clause
21
+ * word counts only as a whole word outside brackets, and not where it must be a name: as a clause's first word
22
+ * (`sort limit`), after a comma or `as`, or before a comparator (`where limit = 1`).
23
+ * @param query
24
+ * @returns undefined when the query doesn't start with read, insert, update or delete (left to the find* steps).
25
+ * @throws {Error} For a joined record outside read, a clause the command doesn't allow, a repeated clause, a clause out
26
+ * of order, or the 2.x forms of a second where (`and where`, `or where`, or a plain repeat).
27
+ */
28
+ export declare const splitClauses: (query: string) => SplitQuery | undefined;
29
+ //# sourceMappingURL=splitClauses.d.ts.map