json-fs-query 1.1.0 → 2.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 (113) hide show
  1. package/LICENSE +674 -674
  2. package/README.md +295 -98
  3. package/browser/jsonFsQuery.js +12733 -10934
  4. package/browser/jsonFsQuery.min.js +1 -1
  5. package/dist/data/introspect/create.d.ts +1 -1
  6. package/dist/data/introspect/create.js +35 -4
  7. package/dist/data/introspect/create.min.js +1 -1
  8. package/dist/data/introspect/definitions/field.d.ts +6 -2
  9. package/dist/data/introspect/definitions/field.js +7 -1
  10. package/dist/data/introspect/definitions/field.min.js +1 -1
  11. package/dist/data/introspect/index.d.ts +6 -3
  12. package/dist/data/introspect/index.js +10 -19
  13. package/dist/data/introspect/index.min.js +1 -1
  14. package/dist/data/introspect/policies/foreignKeyExists.js +28 -28
  15. package/dist/data/introspect/policies/hasDependents.js +53 -53
  16. package/dist/data/introspect/policies/keyUnique.js +34 -34
  17. package/dist/data/introspect/policies/typeCheck.d.ts +9 -1
  18. package/dist/data/introspect/policies/typeCheck.js +16 -2
  19. package/dist/data/introspect/policies/typeCheck.min.js +1 -1
  20. package/dist/data/queries/createRecord.d.ts +11 -0
  21. package/dist/data/queries/createRecord.js +58 -0
  22. package/dist/data/queries/createRecord.min.js +1 -0
  23. package/dist/data/queries/deleteEntity.js +100 -100
  24. package/dist/data/queries/describeRecord.d.ts +9 -0
  25. package/dist/data/queries/describeRecord.js +29 -0
  26. package/dist/data/queries/describeRecord.min.js +1 -0
  27. package/dist/data/queries/dropRecord.d.ts +9 -0
  28. package/dist/data/queries/dropRecord.js +61 -0
  29. package/dist/data/queries/dropRecord.min.js +1 -0
  30. package/dist/data/queries/insertEntity.js +122 -117
  31. package/dist/data/queries/insertEntity.min.js +1 -1
  32. package/dist/data/queries/parser.d.ts +1 -1
  33. package/dist/data/queries/parser.js +7 -15
  34. package/dist/data/queries/parser.min.js +1 -1
  35. package/dist/data/queries/query.d.ts +6 -0
  36. package/dist/data/queries/query.js +15 -6
  37. package/dist/data/queries/query.min.js +1 -1
  38. package/dist/data/queries/queryStatus.d.ts +15 -0
  39. package/dist/data/queries/queryStatus.js +52 -0
  40. package/dist/data/queries/queryStatus.min.js +1 -0
  41. package/dist/data/queries/quote.d.ts +11 -0
  42. package/dist/data/queries/quote.js +17 -0
  43. package/dist/data/queries/quote.min.js +1 -0
  44. package/dist/data/queries/showRecords.d.ts +6 -0
  45. package/dist/data/queries/showRecords.js +21 -0
  46. package/dist/data/queries/showRecords.min.js +1 -0
  47. package/dist/data/queries/sortBy.js +27 -27
  48. package/dist/data/queries/updateEntity.js +245 -193
  49. package/dist/data/queries/updateEntity.min.js +1 -1
  50. package/dist/data/queries/where.d.ts +7 -7
  51. package/dist/data/queries/where.js +67 -67
  52. package/dist/data/utilities/compareAs.d.ts +19 -19
  53. package/dist/data/utilities/compareAs.js +57 -57
  54. package/dist/data/utilities/config.d.ts +15 -0
  55. package/dist/data/utilities/config.js +31 -1
  56. package/dist/data/utilities/config.min.js +1 -1
  57. package/dist/data/utilities/databaseLock.d.ts +16 -0
  58. package/dist/data/utilities/databaseLock.js +63 -0
  59. package/dist/data/utilities/databaseLock.min.js +1 -0
  60. package/dist/data/utilities/fieldType.d.ts +15 -15
  61. package/dist/data/utilities/fieldType.js +22 -22
  62. package/dist/data/utilities/getConditionIndexedList.js +47 -47
  63. package/dist/data/utilities/matchIndexedJoins.js +62 -62
  64. package/dist/data/utilities/mergeJoin.js +47 -47
  65. package/dist/data/utilities/parsers/findConditions.d.ts +18 -15
  66. package/dist/data/utilities/parsers/findConditions.js +15 -6
  67. package/dist/data/utilities/parsers/findConditions.min.js +1 -1
  68. package/dist/data/utilities/parsers/findInsertValues.js +3 -2
  69. package/dist/data/utilities/parsers/findInsertValues.min.js +1 -1
  70. package/dist/data/utilities/parsers/findSelects.js +6 -3
  71. package/dist/data/utilities/parsers/findSelects.min.js +1 -1
  72. package/dist/data/utilities/parsers/findSortClauses.js +5 -2
  73. package/dist/data/utilities/parsers/findSortClauses.min.js +1 -1
  74. package/dist/data/utilities/parsers/findUpdateValues.js +3 -2
  75. package/dist/data/utilities/parsers/findUpdateValues.min.js +1 -1
  76. package/dist/data/utilities/parsers/maskStrings.d.ts +39 -0
  77. package/dist/data/utilities/parsers/maskStrings.js +123 -0
  78. package/dist/data/utilities/parsers/maskStrings.min.js +1 -0
  79. package/dist/data/utilities/parsers/parseCreate.d.ts +20 -0
  80. package/dist/data/utilities/parsers/parseCreate.js +330 -0
  81. package/dist/data/utilities/parsers/parseCreate.min.js +1 -0
  82. package/dist/data/utilities/parsers/parseLiteralValue.d.ts +2 -1
  83. package/dist/data/utilities/parsers/parseLiteralValue.js +6 -3
  84. package/dist/data/utilities/parsers/parseLiteralValue.min.js +1 -1
  85. package/dist/data/utilities/parsers/parseQuery.d.ts +3 -0
  86. package/dist/data/utilities/parsers/parseQuery.js +28 -2
  87. package/dist/data/utilities/parsers/parseQuery.min.js +1 -1
  88. package/dist/data/utilities/parsers/parseSchemaStatement.d.ts +13 -0
  89. package/dist/data/utilities/parsers/parseSchemaStatement.js +82 -0
  90. package/dist/data/utilities/parsers/parseSchemaStatement.min.js +1 -0
  91. package/dist/data/utilities/parsers/scanQuery.d.ts +52 -0
  92. package/dist/data/utilities/parsers/scanQuery.js +158 -0
  93. package/dist/data/utilities/parsers/scanQuery.min.js +1 -0
  94. package/dist/data/utilities/parsers/splitQueries.d.ts +6 -0
  95. package/dist/data/utilities/parsers/splitQueries.js +20 -2
  96. package/dist/data/utilities/parsers/splitQueries.min.js +1 -1
  97. package/dist/data/utilities/parsers/startsQuery.d.ts +5 -0
  98. package/dist/data/utilities/parsers/startsQuery.js +10 -0
  99. package/dist/data/utilities/parsers/startsQuery.min.js +1 -0
  100. package/dist/data/utilities/recordExists.d.ts +6 -0
  101. package/dist/data/utilities/recordExists.js +18 -0
  102. package/dist/data/utilities/recordExists.min.js +1 -0
  103. package/dist/data/utilities/removeFromIndex.d.ts +14 -14
  104. package/dist/data/utilities/removeFromIndex.js +45 -45
  105. package/dist/data/utilities/runQuery.js +135 -112
  106. package/dist/data/utilities/runQuery.min.js +1 -1
  107. package/dist/data/utilities/updateIndex.d.ts +17 -17
  108. package/dist/data/utilities/updateIndex.js +57 -57
  109. package/dist/data/utilities/useJoinClause.js +56 -56
  110. package/dist/index.d.ts +2 -0
  111. package/dist/index.js +14 -0
  112. package/dist/index.min.js +1 -1
  113. package/package.json +68 -60
@@ -1,48 +1,48 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.mergeJoin = void 0;
7
- require("core-js/modules/esnext.iterator.constructor.js");
8
- require("core-js/modules/esnext.iterator.map.js");
9
- var _readEntity = require("../queries/readEntity");
10
- var _splitEntityProperty = require("./parsers/splitEntityProperty");
11
- var _where = require("../queries/where");
12
- var _retrieveRecord = require("./retrieveRecord");
13
- var _fieldType = require("./fieldType");
14
- const mergeJoin = async (propertyA = '', propertyB = '', dataSets = {}) => {
15
- const {
16
- entity: entityA,
17
- property: propA
18
- } = (0, _splitEntityProperty.splitEntityProperty)(propertyA);
19
- const {
20
- entity: entityB,
21
- property: propB
22
- } = (0, _splitEntityProperty.splitEntityProperty)(propertyB);
23
- dataSets = await (0, _readEntity.readEntity)(entityA, dataSets);
24
- dataSets = await (0, _readEntity.readEntity)(entityB, dataSets);
25
- const typeB = (0, _fieldType.fieldType)(await (0, _retrieveRecord.retrieveRecord)(entityB), propB);
26
- dataSets[entityA] = dataSets[entityA].map(dataA => {
27
- const matches = (0, _where.where)(dataSets[entityB], {
28
- property: propB,
29
- comparator: '=',
30
- value: dataA[propA],
31
- type: typeB
32
- });
33
- if (!matches.length) {
34
- return dataA;
35
- }
36
- const mergeMatch = matches[0];
37
- for (const prop in mergeMatch) {
38
- if (prop === propB) {
39
- // Skip the condition property since it is irrelevant
40
- continue;
41
- }
42
- dataA[`${entityB}.${prop}`] = mergeMatch[prop];
43
- }
44
- return dataA;
45
- });
46
- return dataSets;
47
- };
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.mergeJoin = void 0;
7
+ require("core-js/modules/esnext.iterator.constructor.js");
8
+ require("core-js/modules/esnext.iterator.map.js");
9
+ var _readEntity = require("../queries/readEntity");
10
+ var _splitEntityProperty = require("./parsers/splitEntityProperty");
11
+ var _where = require("../queries/where");
12
+ var _retrieveRecord = require("./retrieveRecord");
13
+ var _fieldType = require("./fieldType");
14
+ const mergeJoin = async (propertyA = '', propertyB = '', dataSets = {}) => {
15
+ const {
16
+ entity: entityA,
17
+ property: propA
18
+ } = (0, _splitEntityProperty.splitEntityProperty)(propertyA);
19
+ const {
20
+ entity: entityB,
21
+ property: propB
22
+ } = (0, _splitEntityProperty.splitEntityProperty)(propertyB);
23
+ dataSets = await (0, _readEntity.readEntity)(entityA, dataSets);
24
+ dataSets = await (0, _readEntity.readEntity)(entityB, dataSets);
25
+ const typeB = (0, _fieldType.fieldType)(await (0, _retrieveRecord.retrieveRecord)(entityB), propB);
26
+ dataSets[entityA] = dataSets[entityA].map(dataA => {
27
+ const matches = (0, _where.where)(dataSets[entityB], {
28
+ property: propB,
29
+ comparator: '=',
30
+ value: dataA[propA],
31
+ type: typeB
32
+ });
33
+ if (!matches.length) {
34
+ return dataA;
35
+ }
36
+ const mergeMatch = matches[0];
37
+ for (const prop in mergeMatch) {
38
+ if (prop === propB) {
39
+ // Skip the condition property since it is irrelevant
40
+ continue;
41
+ }
42
+ dataA[`${entityB}.${prop}`] = mergeMatch[prop];
43
+ }
44
+ return dataA;
45
+ });
46
+ return dataSets;
47
+ };
48
48
  exports.mergeJoin = mergeJoin;
@@ -1,16 +1,19 @@
1
- import { LiteralValue } from './parseLiteralValue';
2
- import { ParsedQuery } from './parseQuery';
3
- export type ConditionValue = LiteralValue;
4
- export type ParsedCondition = {
5
- property: string;
6
- comparator: string;
7
- value: ConditionValue;
8
- type?: string;
9
- };
10
- /**
11
- * Extract condition clauses from the query.
12
- * @param parsed
13
- * @param query
14
- */
15
- export declare const findConditions: (parsed: ParsedQuery, query: string) => string;
1
+ import { LiteralValue } from './parseLiteralValue';
2
+ import { ParsedQuery } from './parseQuery';
3
+ export type ConditionValue = LiteralValue;
4
+ export type ParsedCondition = {
5
+ property: string;
6
+ comparator: string;
7
+ value: ConditionValue;
8
+ type?: string;
9
+ };
10
+ /**
11
+ * Extract condition clauses from the query: `where <field> <comparator> <value>`, each further one joined with
12
+ * `and where`. `or where` is refused until or is built (TASKS: the where-clauses epic): it used to be read the same as
13
+ * `and where`, which silently returned the wrong rows.
14
+ * @param parsed
15
+ * @param query
16
+ * @throws {Error} For `or where`.
17
+ */
18
+ export declare const findConditions: (parsed: ParsedQuery, query: string) => string;
16
19
  //# sourceMappingURL=findConditions.d.ts.map
@@ -6,22 +6,31 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.findConditions = void 0;
7
7
  var _removeFromQuery = require("./removeFromQuery");
8
8
  var _parseLiteralValue = require("./parseLiteralValue");
9
- const conditionMatch = /(and|or)?\s*(where)\s+([a-z0-9_-]+\.?[a-z0-9_-]*)\s+(=|!=|>|<|>=|<=|in|between|like)\s+(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/ig;
9
+ var _maskStrings = require("./maskStrings");
10
+ // `and`/`or`/`where` count only as whole words: in `on t.x = u.color where ...` the `or` is part of the name `color`
11
+ const conditionMatch = new RegExp(`(^|[^a-z0-9._-])(?:(and|or)\\s+)?(where)\\s+([a-z0-9_-]+\\.?[a-z0-9_-]*)\\s+(=|!=|>|<|>=|<=|in|between|like)\\s+(${_maskStrings.placeholderSource}|([0-9]+)|${_maskStrings.arraySource}|(null)|(true)|(false))`, 'ig');
10
12
  /**
11
- * Extract condition clauses from the query.
13
+ * Extract condition clauses from the query: `where <field> <comparator> <value>`, each further one joined with
14
+ * `and where`. `or where` is refused until or is built (TASKS: the where-clauses epic): it used to be read the same as
15
+ * `and where`, which silently returned the wrong rows.
12
16
  * @param parsed
13
17
  * @param query
18
+ * @throws {Error} For `or where`.
14
19
  */
15
20
  const findConditions = (parsed, query) => {
16
21
  const conditionsFound = query.matchAll(conditionMatch);
17
22
  // @ts-ignore
18
23
  for (const condition of conditionsFound) {
24
+ if (typeof condition[2] !== 'undefined' && condition[2].toLowerCase() === 'or') {
25
+ throw new Error('`or where` is not supported yet: use `and where`, or run one query per alternative');
26
+ }
19
27
  parsed['conditions'].push({
20
- property: condition[3],
21
- comparator: condition[4],
22
- value: (0, _parseLiteralValue.parseLiteralValue)(condition, 6)
28
+ property: condition[4],
29
+ comparator: condition[5],
30
+ value: (0, _parseLiteralValue.parseLiteralValue)(condition, 7)
23
31
  });
24
- query = (0, _removeFromQuery.removeFromQuery)(condition[0], query);
32
+ // Leave out the character before the condition (group 1): it isn't part of it, and an earlier removal may have trimmed it
33
+ query = (0, _removeFromQuery.removeFromQuery)(condition[0].slice(condition[1].length), query);
25
34
  }
26
35
  return query;
27
36
  };
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findConditions=void 0;var _removeFromQuery=require("./removeFromQuery"),_parseLiteralValue=require("./parseLiteralValue");const conditionMatch=/(and|or)?\s*(where)\s+([a-z0-9_-]+\.?[a-z0-9_-]*)\s+(=|!=|>|<|>=|<=|in|between|like)\s+(["'](.*)['"]|([0-9]+)|(\[.*])|(null)|(true)|(false))/gi,findConditions=(e,r)=>{const o=r.matchAll(conditionMatch);for(const i of o)e.conditions.push({property:i[3],comparator:i[4],value:(0,_parseLiteralValue.parseLiteralValue)(i,6)}),r=(0,_removeFromQuery.removeFromQuery)(i[0],r);return r};exports.findConditions=findConditions;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findConditions=void 0;var _removeFromQuery=require("./removeFromQuery"),_parseLiteralValue=require("./parseLiteralValue"),_maskStrings=require("./maskStrings");const conditionMatch=new RegExp(`(^|[^a-z0-9._-])(?:(and|or)\\s+)?(where)\\s+([a-z0-9_-]+\\.?[a-z0-9_-]*)\\s+(=|!=|>|<|>=|<=|in|between|like)\\s+(${_maskStrings.placeholderSource}|([0-9]+)|${_maskStrings.arraySource}|(null)|(true)|(false))`,"ig"),findConditions=(e,r)=>{const o=r.matchAll(conditionMatch);for(const t of o){if(void 0!==t[2]&&"or"===t[2].toLowerCase())throw new Error("`or where` is not supported yet: use `and where`, or run one query per alternative");e.conditions.push({property:t[4],comparator:t[5],value:(0,_parseLiteralValue.parseLiteralValue)(t,7)}),r=(0,_removeFromQuery.removeFromQuery)(t[0].slice(t[1].length),r)}return r};exports.findConditions=findConditions;
@@ -6,9 +6,10 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.findInsertValues = void 0;
7
7
  var _removeFromQuery = require("./removeFromQuery");
8
8
  var _parseLiteralValue = require("./parseLiteralValue");
9
- const literal = '(?:["\'][^"\']*[\'"]|[0-9]+|\\[.*?]|null|true|false)';
9
+ var _maskStrings = require("./maskStrings");
10
+ const literal = `(?:${_maskStrings.placeholderSource.replace('(', '(?:')}|[0-9]+|${_maskStrings.arraySource.replace('(', '(?:')}|null|true|false)`;
10
11
  const valuesClauseMatch = new RegExp(`(values)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i');
11
- const assignmentMatch = /([a-z0-9_-]+)\s*=\s*(["'](.*?)['"]|([0-9]+)|(\[.*?])|(null)|(true)|(false))/ig;
12
+ const assignmentMatch = new RegExp(`([a-z0-9_-]+)\\s*=\\s*(${_maskStrings.placeholderSource}|([0-9]+)|${_maskStrings.arraySource}|(null)|(true)|(false))`, 'ig');
12
13
  /**
13
14
  * Extract an insert's "values field = value, field2 = value2" clause from the query, the same way
14
15
  * findUpdateValues() does for "set". insertEntity() accepts an array of rows for bulk inserts, but
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findInsertValues=void 0;var _removeFromQuery=require("./removeFromQuery"),_parseLiteralValue=require("./parseLiteralValue");const literal="(?:[\"'][^\"']*['\"]|[0-9]+|\\[.*?]|null|true|false)",valuesClauseMatch=new RegExp(`(values)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`,"i"),assignmentMatch=/([a-z0-9_-]+)\s*=\s*(["'](.*?)['"]|([0-9]+)|(\[.*?])|(null)|(true)|(false))/gi,findInsertValues=(e,r)=>{const s=r.match(valuesClauseMatch);if(e.insertValues=[],!s)return r;const a={},t=s[2].matchAll(assignmentMatch);for(const e of t)a[e[1]]=(0,_parseLiteralValue.parseLiteralValue)(e,3);return e.insertValues=[a],(0,_removeFromQuery.removeFromQuery)(s[0],r)};exports.findInsertValues=findInsertValues;
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findInsertValues=void 0;var _removeFromQuery=require("./removeFromQuery"),_parseLiteralValue=require("./parseLiteralValue"),_maskStrings=require("./maskStrings");const literal=`(?:${_maskStrings.placeholderSource.replace("(","(?:")}|[0-9]+|${_maskStrings.arraySource.replace("(","(?:")}|null|true|false)`,valuesClauseMatch=new RegExp(`(values)\\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}|([0-9]+)|${_maskStrings.arraySource}|(null)|(true)|(false))`,"ig"),findInsertValues=(e,r)=>{const s=r.match(valuesClauseMatch);if(e.insertValues=[],!s)return r;const a={},t=s[2].matchAll(assignmentMatch);for(const e of t)a[e[1]]=(0,_parseLiteralValue.parseLiteralValue)(e,3);return e.insertValues=[a],(0,_removeFromQuery.removeFromQuery)(s[0],r)};exports.findInsertValues=findInsertValues;
@@ -5,8 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.findSelects = void 0;
7
7
  var _removeFromQuery = require("./removeFromQuery");
8
- const selectClausesMatch = /select\s+([a-z0-9=._-]+\s*(as\s+)?([a-z0-9_-]+)?)+\s*(,\s*[a-z0-9=._-]+\s*(as\s*[a-z0-9_-]+)?)*/i;
9
- const selectClauseMatch = /(select)?\s*,?\s*([a-z0-9=._-]+)\s*(as\s+)?([a-z0-9_-]+)?/ig;
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.
10
+ 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;
10
13
  /**
11
14
  * Extract select clauses from the query.
12
15
  * @param parsed
@@ -20,7 +23,7 @@ const findSelects = (parsed, query) => {
20
23
  for (const selectClause of selectClausesFound) {
21
24
  parsed['selectClauses'].push({
22
25
  property: selectClause[2],
23
- alias: selectClause[4]
26
+ alias: selectClause[3]
24
27
  });
25
28
  }
26
29
  return (0, _removeFromQuery.removeFromQuery)(selectsFound[0], query);
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findSelects=void 0;var _removeFromQuery=require("./removeFromQuery");const selectClausesMatch=/select\s+([a-z0-9=._-]+\s*(as\s+)?([a-z0-9_-]+)?)+\s*(,\s*[a-z0-9=._-]+\s*(as\s*[a-z0-9_-]+)?)*/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[4]});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;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;
@@ -5,8 +5,11 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.findSortClauses = void 0;
7
7
  var _removeFromQuery = require("./removeFromQuery");
8
- const sortMatch = /sort\s+([a-z0-9._-]+\s*(asc|desc)?)+\s*(,\s*[a-z0-9._-]+\s*(asc|desc)?)*/i;
9
- const sortRuleMatch = /(sort)?\s*,?\s*([a-z0-9._-]+)\s*(asc|desc)?/ig;
8
+ // 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.
10
+ 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
13
  /**
11
14
  * Extract sort clauses from the query.
12
15
  * @param parsed
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findSortClauses=void 0;var _removeFromQuery=require("./removeFromQuery");const sortMatch=/sort\s+([a-z0-9._-]+\s*(asc|desc)?)+\s*(,\s*[a-z0-9._-]+\s*(asc|desc)?)*/i,sortRuleMatch=/(sort)?\s*,?\s*([a-z0-9._-]+)\s*(asc|desc)?/gi,findSortClauses=(s,r)=>{const e=r.match(sortMatch);if(e){const o=e[0].matchAll(sortRuleMatch);for(const r of o)s.sortClauses.push({property:r[2],direction:r[3]||"asc"});return(0,_removeFromQuery.removeFromQuery)(e[0],r)}return r};exports.findSortClauses=findSortClauses;
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"});return(0,_removeFromQuery.removeFromQuery)(s[0],r)}return r};exports.findSortClauses=findSortClauses;
@@ -6,9 +6,10 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.findUpdateValues = void 0;
7
7
  var _removeFromQuery = require("./removeFromQuery");
8
8
  var _parseLiteralValue = require("./parseLiteralValue");
9
- const literal = '(?:["\'][^"\']*[\'"]|[0-9]+|\\[.*?]|null|true|false)';
9
+ var _maskStrings = require("./maskStrings");
10
+ const literal = `(?:${_maskStrings.placeholderSource.replace('(', '(?:')}|[0-9]+|${_maskStrings.arraySource.replace('(', '(?:')}|null|true|false)`;
10
11
  const setClauseMatch = new RegExp(`(set)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`, 'i');
11
- const assignmentMatch = /([a-z0-9_-]+)\s*=\s*(["'](.*?)['"]|([0-9]+)|(\[.*?])|(null)|(true)|(false))/ig;
12
+ const assignmentMatch = new RegExp(`([a-z0-9_-]+)\\s*=\\s*(${_maskStrings.placeholderSource}|([0-9]+)|${_maskStrings.arraySource}|(null)|(true)|(false))`, 'ig');
12
13
  /**
13
14
  * Extract an update's "set field = value, field2 = value2" clause from the query. Uses a two-pass
14
15
  * match, unlike the other parsers here: the set clause's own boundary is found first (so it can
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.findUpdateValues=void 0;var _removeFromQuery=require("./removeFromQuery"),_parseLiteralValue=require("./parseLiteralValue");const literal="(?:[\"'][^\"']*['\"]|[0-9]+|\\[.*?]|null|true|false)",setClauseMatch=new RegExp(`(set)\\s+([a-z0-9_-]+\\s*=\\s*${literal}(?:\\s*,\\s*[a-z0-9_-]+\\s*=\\s*${literal})*)`,"i"),assignmentMatch=/([a-z0-9_-]+)\s*=\s*(["'](.*?)['"]|([0-9]+)|(\[.*?])|(null)|(true)|(false))/gi,findUpdateValues=(e,a)=>{const r=a.match(setClauseMatch);if(e.updateValues={},!r)return a;const s=r[2].matchAll(assignmentMatch);for(const a of s)e.updateValues[a[1]]=(0,_parseLiteralValue.parseLiteralValue)(a,3);return(0,_removeFromQuery.removeFromQuery)(r[0],a)};exports.findUpdateValues=findUpdateValues;
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("(","(?:")}|[0-9]+|${_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}|([0-9]+)|${_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;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Regex source matching one placeholder from maskStrings, with the hex-encoded value as its only group. The
3
+ * find* parsers use it where they would otherwise match a quoted string.
4
+ */
5
+ export declare const placeholderSource = "\\u0000([0-9a-f]*)\\u0000";
6
+ /**
7
+ * Regex source matching one placeholder from maskArrays, with the hex-encoded JSON of the array as its only group.
8
+ * The find* parsers use it where they would otherwise match `[...]`.
9
+ */
10
+ export declare const arraySource = "\\u0001([0-9a-f]*)\\u0001";
11
+ /**
12
+ * Turn the hex of a placeholder back into the string's value.
13
+ * @param hex
14
+ */
15
+ export declare const fromPlaceholder: (hex: string) => string;
16
+ /**
17
+ * Replace every quoted string in a query with a placeholder holding its value (with the escapes applied), so that
18
+ * nothing inside a string (a keyword, a quote, `and`, a `]`) can be matched by the find* parsers.
19
+ * @param query
20
+ * @throws {Error} For an unclosed string, comment or bracket, or a NUL or SOH character outside a string (which
21
+ * could otherwise pass for a placeholder).
22
+ */
23
+ export declare const maskStrings: (query: string) => string;
24
+ /**
25
+ * Put every placeholder back the way it would be written in a query: strings quoted, arrays as JSON. For error
26
+ * messages, and for reading an array's text as JSON.
27
+ * @param text
28
+ * @param quote - wrap strings with JSON's double quotes (the default) or with single quotes
29
+ */
30
+ export declare const unmaskStrings: (text: string, quote?: "json" | "'") => string;
31
+ /**
32
+ * Replace every array (outermost brackets only, so a nested array stays inside its parent) with a placeholder holding
33
+ * its JSON, so that the find* parsers never have to find where an array ends, and nothing inside one (a `.`, a `]`,
34
+ * a keyword) can be matched by them. Run it on the output of maskStrings, where no `[` or `]` is inside a string.
35
+ * @param masked
36
+ * @throws {Error} For an array which is not valid JSON once its strings are put back.
37
+ */
38
+ export declare const maskArrays: (masked: string) => string;
39
+ //# sourceMappingURL=maskStrings.d.ts.map
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.unmaskStrings = exports.placeholderSource = exports.maskStrings = exports.maskArrays = exports.fromPlaceholder = exports.arraySource = void 0;
7
+ require("core-js/modules/es.json.stringify.js");
8
+ require("core-js/modules/esnext.iterator.constructor.js");
9
+ require("core-js/modules/esnext.iterator.map.js");
10
+ require("core-js/modules/esnext.iterator.some.js");
11
+ var _scanQuery = require("./scanQuery");
12
+ /**
13
+ * Regex source matching one placeholder from maskStrings, with the hex-encoded value as its only group. The
14
+ * find* parsers use it where they would otherwise match a quoted string.
15
+ */
16
+ const placeholderSource = exports.placeholderSource = '\\u0000([0-9a-f]*)\\u0000';
17
+ const placeholderMatch = new RegExp(placeholderSource, 'g');
18
+ /**
19
+ * Regex source matching one placeholder from maskArrays, with the hex-encoded JSON of the array as its only group.
20
+ * The find* parsers use it where they would otherwise match `[...]`.
21
+ */
22
+ const arraySource = exports.arraySource = '\\u0001([0-9a-f]*)\\u0001';
23
+ const arrayMatch = new RegExp(arraySource, 'g');
24
+ /**
25
+ * Encode a value as hex, four digits per UTF-16 code unit: only 0-9 and a-f, so no keyword, quote, space or
26
+ * bracket a parser looks for can appear in it.
27
+ * @param value
28
+ */
29
+ const toHex = value => value.split('').map(char => char.charCodeAt(0).toString(16).padStart(4, '0')).join('');
30
+ /**
31
+ * Turn the hex of a placeholder back into the string's value.
32
+ * @param hex
33
+ */
34
+ const fromPlaceholder = hex => (hex.match(/.{4}/g) || []).map(code => String.fromCharCode(parseInt(code, 16))).join('');
35
+ /**
36
+ * Replace every quoted string in a query with a placeholder holding its value (with the escapes applied), so that
37
+ * nothing inside a string (a keyword, a quote, `and`, a `]`) can be matched by the find* parsers.
38
+ * @param query
39
+ * @throws {Error} For an unclosed string, comment or bracket, or a NUL or SOH character outside a string (which
40
+ * could otherwise pass for a placeholder).
41
+ */
42
+ exports.fromPlaceholder = fromPlaceholder;
43
+ const maskStrings = query => {
44
+ const {
45
+ strings
46
+ } = (0, _scanQuery.assertClosed)((0, _scanQuery.scanQuery)(query));
47
+ for (const [character, name] of [['\u0000', 'NUL'], ['\u0001', 'SOH']]) {
48
+ for (let index = query.indexOf(character); index !== -1; index = query.indexOf(character, index + 1)) {
49
+ if (!strings.some(({
50
+ start,
51
+ end
52
+ }) => start < index && index < end)) {
53
+ throw new Error(`Unexpected ${name} character at position ${index}`);
54
+ }
55
+ }
56
+ }
57
+ return strings.reduceRight((masked, {
58
+ start,
59
+ end,
60
+ value
61
+ }) => `${masked.slice(0, start)}\u0000${toHex(value)}\u0000${masked.slice(end)}`, query);
62
+ };
63
+ /**
64
+ * Put every placeholder back the way it would be written in a query: strings quoted, arrays as JSON. For error
65
+ * messages, and for reading an array's text as JSON.
66
+ * @param text
67
+ * @param quote - wrap strings with JSON's double quotes (the default) or with single quotes
68
+ */
69
+ exports.maskStrings = maskStrings;
70
+ const unmaskStrings = (text, quote = 'json') => text.replace(placeholderMatch, (placeholder, hex) => {
71
+ const value = fromPlaceholder(hex);
72
+ return quote === 'json' ? JSON.stringify(value) : `'${value.replace(/\\/g, '\\\\').replace(/'/g, '\\\'')}'`;
73
+ }).replace(arrayMatch, (placeholder, hex) => fromPlaceholder(hex));
74
+ /**
75
+ * Read one array's text (its strings already placeholders) as JSON, so it is checked once, here, with a clear error.
76
+ * @param text
77
+ */
78
+ exports.unmaskStrings = unmaskStrings;
79
+ const arrayJson = text => {
80
+ try {
81
+ // A number too big for a double reads as Infinity, which JSON would write back as null: refuse it instead
82
+ return JSON.stringify(JSON.parse(unmaskStrings(text), (key, value) => {
83
+ if (typeof value === 'number' && !Number.isFinite(value)) {
84
+ throw new Error(`${value} is too large`);
85
+ }
86
+ return value;
87
+ }));
88
+ } catch (e) {
89
+ throw new Error(`Invalid array ${unmaskStrings(text, '\'')}: ${e.message}`);
90
+ }
91
+ };
92
+ /**
93
+ * Replace every array (outermost brackets only, so a nested array stays inside its parent) with a placeholder holding
94
+ * its JSON, so that the find* parsers never have to find where an array ends, and nothing inside one (a `.`, a `]`,
95
+ * a keyword) can be matched by them. Run it on the output of maskStrings, where no `[` or `]` is inside a string.
96
+ * @param masked
97
+ * @throws {Error} For an array which is not valid JSON once its strings are put back.
98
+ */
99
+ const maskArrays = masked => {
100
+ let result = '';
101
+ let depth = 0;
102
+ let start = 0;
103
+ for (let index = 0; index < masked.length; index++) {
104
+ const char = masked[index];
105
+ if (char === '[') {
106
+ if (depth === 0) {
107
+ start = index;
108
+ }
109
+ depth++;
110
+ } else if (char === ']' && depth > 0) {
111
+ depth--;
112
+ if (depth === 0) {
113
+ result += `\u0001${toHex(arrayJson(masked.slice(start, index + 1)))}\u0001`;
114
+ continue;
115
+ }
116
+ }
117
+ if (depth === 0) {
118
+ result += char;
119
+ }
120
+ }
121
+ return depth > 0 ? result + masked.slice(start) : result;
122
+ };
123
+ exports.maskArrays = maskArrays;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:!0}),exports.unmaskStrings=exports.placeholderSource=exports.maskStrings=exports.maskArrays=exports.fromPlaceholder=exports.arraySource=void 0,require("core-js/modules/es.json.stringify.js"),require("core-js/modules/esnext.iterator.constructor.js"),require("core-js/modules/esnext.iterator.map.js"),require("core-js/modules/esnext.iterator.some.js");var _scanQuery=require("./scanQuery");const placeholderSource=exports.placeholderSource="\\u0000([0-9a-f]*)\\u0000",placeholderMatch=new RegExp(placeholderSource,"g"),arraySource=exports.arraySource="\\u0001([0-9a-f]*)\\u0001",arrayMatch=new RegExp(arraySource,"g"),toHex=r=>r.split("").map((r=>r.charCodeAt(0).toString(16).padStart(4,"0"))).join(""),fromPlaceholder=r=>(r.match(/.{4}/g)||[]).map((r=>String.fromCharCode(parseInt(r,16)))).join("");exports.fromPlaceholder=fromPlaceholder;const maskStrings=r=>{const{strings:e}=(0,_scanQuery.assertClosed)((0,_scanQuery.scanQuery)(r));for(const[s,o]of[["\0","NUL"],["","SOH"]])for(let t=r.indexOf(s);-1!==t;t=r.indexOf(s,t+1))if(!e.some((({start:r,end:e})=>r<t&&t<e)))throw new Error(`Unexpected ${o} character at position ${t}`);return e.reduceRight(((r,{start:e,end:s,value:o})=>`${r.slice(0,e)}\0${toHex(o)}\0${r.slice(s)}`),r)};exports.maskStrings=maskStrings;const unmaskStrings=(r,e="json")=>r.replace(placeholderMatch,((r,s)=>{const o=fromPlaceholder(s);return"json"===e?JSON.stringify(o):`'${o.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}'`})).replace(arrayMatch,((r,e)=>fromPlaceholder(e)));exports.unmaskStrings=unmaskStrings;const arrayJson=r=>{try{return JSON.stringify(JSON.parse(unmaskStrings(r),((r,e)=>{if("number"==typeof e&&!Number.isFinite(e))throw new Error(`${e} is too large`);return e})))}catch(e){throw new Error(`Invalid array ${unmaskStrings(r,"'")}: ${e.message}`)}},maskArrays=r=>{let e="",s=0,o=0;for(let t=0;t<r.length;t++){const a=r[t];if("["===a)0===s&&(o=t),s++;else if("]"===a&&s>0&&(s--,0===s)){e+=`${toHex(arrayJson(r.slice(o,t+1)))}`;continue}0===s&&(e+=a)}return s>0?e+r.slice(o):e};exports.maskArrays=maskArrays;
@@ -0,0 +1,20 @@
1
+ import { fieldProperties } from '../../introspect/definitions/field';
2
+ import { keyProperties } from '../../introspect/definitions/key';
3
+ export type ParsedCreate = {
4
+ ifNotExists: boolean;
5
+ definition: fieldProperties[];
6
+ keys: keyProperties[];
7
+ };
8
+ export type ParsedCreateQuery = {
9
+ entity: string;
10
+ create: ParsedCreate;
11
+ };
12
+ export declare const createMatch: RegExp;
13
+ /**
14
+ * Parse a create statement (strings and arrays already masked):
15
+ * `create [if not exists] <name> (<field>, ..., <key>, ...)`. See the README's "Creating a record". Only checks
16
+ * what the text alone can tell; the referenced records of foreign keys are checked when it runs.
17
+ * @param query
18
+ */
19
+ export declare const parseCreate: (query: string) => ParsedCreateQuery;
20
+ //# sourceMappingURL=parseCreate.d.ts.map