@react-querybuilder/core 8.20.2 → 8.21.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.
Files changed (109) hide show
  1. package/README.md +4 -0
  2. package/dist/cjs/react-querybuilder_core.cjs.development.d.ts +2261 -2113
  3. package/dist/cjs/react-querybuilder_core.cjs.development.js +319 -22
  4. package/dist/cjs/react-querybuilder_core.cjs.development.js.map +1 -1
  5. package/dist/cjs/react-querybuilder_core.cjs.production.d.ts +2261 -2113
  6. package/dist/cjs/react-querybuilder_core.cjs.production.js +1 -1
  7. package/dist/cjs/react-querybuilder_core.cjs.production.js.map +1 -1
  8. package/dist/{convertQuery-BJKNgecE.js → convertQuery-Cw76XFIn.js} +8 -8
  9. package/dist/{convertQuery-BJKNgecE.js.map → convertQuery-Cw76XFIn.js.map} +1 -1
  10. package/dist/{convertQuery-J1CaoDxe.mjs → convertQuery-D_4J7E-Z.mjs} +2 -2
  11. package/dist/{convertQuery-J1CaoDxe.mjs.map → convertQuery-D_4J7E-Z.mjs.map} +1 -1
  12. package/dist/formatQuery.d.mts +499 -459
  13. package/dist/formatQuery.d.ts +499 -459
  14. package/dist/formatQuery.js +170 -88
  15. package/dist/formatQuery.js.map +1 -1
  16. package/dist/formatQuery.mjs +97 -20
  17. package/dist/formatQuery.mjs.map +1 -1
  18. package/dist/import-BVdxeIBO.d.mts +26 -0
  19. package/dist/import-Ddc3d_8q.d.ts +26 -0
  20. package/dist/{index-DlVg-QXo.d.mts → index-BSwFvkeI.d.mts} +679 -648
  21. package/dist/{index-DlVg-QXo.d.ts → index-BSwFvkeI.d.ts} +679 -648
  22. package/dist/{objectUtils-DBJI82bl.js → isRuleGroup-0JNiQgLg.js} +1 -26
  23. package/dist/isRuleGroup-0JNiQgLg.js.map +1 -0
  24. package/dist/{objectUtils-ZvPkF6u6.mjs → isRuleGroup-CqLThsbu.mjs} +2 -15
  25. package/dist/isRuleGroup-CqLThsbu.mjs.map +1 -0
  26. package/dist/objectUtils-Cr02aGxb.js +27 -0
  27. package/dist/objectUtils-Cr02aGxb.js.map +1 -0
  28. package/dist/objectUtils-DBlmJgBf.mjs +16 -0
  29. package/dist/objectUtils-DBlmJgBf.mjs.map +1 -0
  30. package/dist/parseCEL.d.mts +64 -30
  31. package/dist/parseCEL.d.ts +64 -30
  32. package/dist/parseCEL.js +91 -12
  33. package/dist/parseCEL.js.map +1 -1
  34. package/dist/parseCEL.mjs +85 -8
  35. package/dist/parseCEL.mjs.map +1 -1
  36. package/dist/parseCypher.d.mts +24 -25
  37. package/dist/parseCypher.d.ts +24 -25
  38. package/dist/parseGremlin.d.mts +18 -19
  39. package/dist/parseGremlin.d.ts +18 -19
  40. package/dist/parseJSONata.d.mts +207 -20
  41. package/dist/parseJSONata.d.ts +207 -20
  42. package/dist/parseJSONata.js +92 -7
  43. package/dist/parseJSONata.js.map +1 -1
  44. package/dist/parseJSONata.mjs +80 -4
  45. package/dist/parseJSONata.mjs.map +1 -1
  46. package/dist/parseJsonLogic.d.mts +51 -18
  47. package/dist/parseJsonLogic.d.ts +51 -18
  48. package/dist/parseJsonLogic.js +95 -34
  49. package/dist/parseJsonLogic.js.map +1 -1
  50. package/dist/parseJsonLogic.mjs +65 -6
  51. package/dist/parseJsonLogic.mjs.map +1 -1
  52. package/dist/parseMongoDB.d.mts +89 -58
  53. package/dist/parseMongoDB.d.ts +89 -58
  54. package/dist/parseMongoDB.js +140 -15
  55. package/dist/parseMongoDB.js.map +1 -1
  56. package/dist/parseMongoDB.mjs +128 -5
  57. package/dist/parseMongoDB.mjs.map +1 -1
  58. package/dist/parseSPARQL.d.mts +17 -18
  59. package/dist/parseSPARQL.d.ts +17 -18
  60. package/dist/parseSPARQL.js.map +1 -1
  61. package/dist/parseSPARQL.mjs.map +1 -1
  62. package/dist/parseSQL.d.mts +266 -18
  63. package/dist/parseSQL.d.ts +266 -18
  64. package/dist/parseSQL.js +163 -10
  65. package/dist/parseSQL.js.map +1 -1
  66. package/dist/parseSQL.mjs +149 -7
  67. package/dist/parseSQL.mjs.map +1 -1
  68. package/dist/parseSpEL.d.mts +193 -19
  69. package/dist/parseSpEL.d.ts +193 -19
  70. package/dist/parseSpEL.js +166 -7
  71. package/dist/parseSpEL.js.map +1 -1
  72. package/dist/parseSpEL.mjs +142 -6
  73. package/dist/parseSpEL.mjs.map +1 -1
  74. package/dist/{prepareQueryObjects-Bni5VgYM.js → prepareQueryObjects-C2-kTZvR.js} +5 -5
  75. package/dist/prepareQueryObjects-C2-kTZvR.js.map +1 -0
  76. package/dist/{prepareQueryObjects-BCLU20Cg.mjs → prepareQueryObjects-Q18lHCKl.mjs} +3 -3
  77. package/dist/prepareQueryObjects-Q18lHCKl.mjs.map +1 -0
  78. package/dist/query-builder-layout.css.map +1 -1
  79. package/dist/query-builder.css.map +1 -1
  80. package/dist/react-querybuilder_core.d.mts +2261 -2113
  81. package/dist/react-querybuilder_core.legacy-esm.d.ts +2261 -2113
  82. package/dist/react-querybuilder_core.legacy-esm.js +335 -40
  83. package/dist/react-querybuilder_core.legacy-esm.js.map +1 -1
  84. package/dist/react-querybuilder_core.mjs +309 -23
  85. package/dist/react-querybuilder_core.mjs.map +1 -1
  86. package/dist/react-querybuilder_core.production.d.mts +2261 -2113
  87. package/dist/react-querybuilder_core.production.mjs +1 -1
  88. package/dist/react-querybuilder_core.production.mjs.map +1 -1
  89. package/dist/styles/_layout.scss +18 -14
  90. package/dist/styles/_main.scss +7 -2
  91. package/dist/transformQuery.d.mts +91 -92
  92. package/dist/transformQuery.d.ts +91 -92
  93. package/dist/transformQuery.js +4 -3
  94. package/dist/transformQuery.js.map +1 -1
  95. package/dist/transformQuery.mjs +2 -1
  96. package/dist/transformQuery.mjs.map +1 -1
  97. package/dist/{utils-BpaOtylk.js → utils-DEwV7F6B.js} +108 -12
  98. package/dist/utils-DEwV7F6B.js.map +1 -0
  99. package/dist/{utils-CJRGiPb-.mjs → utils-Dt0D_DMV.mjs} +69 -3
  100. package/dist/utils-Dt0D_DMV.mjs.map +1 -0
  101. package/package.json +16 -16
  102. package/dist/import-Qs1-kgv5.d.ts +0 -27
  103. package/dist/import-ShTj5IdB.d.mts +0 -27
  104. package/dist/objectUtils-DBJI82bl.js.map +0 -1
  105. package/dist/objectUtils-ZvPkF6u6.mjs.map +0 -1
  106. package/dist/prepareQueryObjects-BCLU20Cg.mjs.map +0 -1
  107. package/dist/prepareQueryObjects-Bni5VgYM.js.map +0 -1
  108. package/dist/utils-BpaOtylk.js.map +0 -1
  109. package/dist/utils-CJRGiPb-.mjs.map +0 -1
@@ -1,7 +1,8 @@
1
- import { E as joinWith, k as defaultOperatorNegationMap } from "./utils-CJRGiPb-.mjs";
2
- import { i as isRuleGroupType, n as objectKeys, o as isPojo } from "./objectUtils-ZvPkF6u6.mjs";
3
- import { n as convertToIC } from "./convertQuery-J1CaoDxe.mjs";
4
- import { n as fieldIsValidUtil, r as getFieldsArray, t as prepareRuleGroup } from "./prepareQueryObjects-BCLU20Cg.mjs";
1
+ import { P as defaultOperatorNegationMap, j as joinWith } from "./utils-Dt0D_DMV.mjs";
2
+ import { i as isPojo, n as isRuleGroupType } from "./isRuleGroup-CqLThsbu.mjs";
3
+ import { n as objectKeys } from "./objectUtils-DBlmJgBf.mjs";
4
+ import { n as convertToIC } from "./convertQuery-D_4J7E-Z.mjs";
5
+ import { n as fieldIsValidUtil, r as getFieldsArray, t as prepareRuleGroup } from "./prepareQueryObjects-Q18lHCKl.mjs";
5
6
  //#region src/utils/parseMongoDB/utils.ts
6
7
  const getRegExStr = (re) => typeof re === "string" ? re : re.source;
7
8
  const isPrimitive = (v) => typeof v === "string" || typeof v === "number" || typeof v === "boolean";
@@ -13,6 +14,26 @@ const mongoDbToRqbOperatorMap = {
13
14
  $lt: "<",
14
15
  $lte: "<="
15
16
  };
17
+ /** Comparison aggregation operators that can carry expression operands, mapped to RQB operators. */
18
+ const mongoDbExprComparisonMap = {
19
+ $eq: "=",
20
+ $ne: "!=",
21
+ $gt: ">",
22
+ $gte: ">=",
23
+ $lt: "<",
24
+ $lte: "<="
25
+ };
26
+ /** Flips a comparison operator (for operand order reversal); non-comparisons pass through. */
27
+ const flipMongoDbOperator = (op) => op === "<" ? ">" : op === "<=" ? ">=" : op === ">" ? "<" : op === ">=" ? "<=" : op;
28
+ /**
29
+ * A MongoDB `$expr` comparison operand that is a candidate expression subtree: an
30
+ * aggregation-operator object (e.g. `{ $multiply: [...] }`). Bare `"$field"` strings and
31
+ * literals are not expression operands. The expr-supplied `getExpression` handler decides
32
+ * whether it maps to a known function.
33
+ */
34
+ const isMongoDBExpressionOperand = (operand) => isPojo(operand);
35
+ /** Reads a MongoDB field-path operand (`"$field"`), returning the field name or `null`. */
36
+ const mongoDbFieldRef = (operand) => typeof operand === "string" && operand.startsWith("$") ? operand.slice(1) : null;
16
37
  //#endregion
17
38
  //#region src/utils/parseMongoDB/parseMongoDB.ts
18
39
  const emptyRuleGroup = {
@@ -25,6 +46,7 @@ function parseMongoDB(mongoDbRules, options = {}) {
25
46
  const getValueSources = options.getValueSources;
26
47
  const additionalOperators = options.additionalOperators ?? {};
27
48
  const preventOperatorNegation = !!options.preventOperatorNegation;
49
+ const getExpression = options.getExpression;
28
50
  const { additionalOperators: _ao, ...otherOptions } = options;
29
51
  const fieldIsValid = (fieldName, operator, subordinateFieldName) => fieldIsValidUtil({
30
52
  fieldName,
@@ -33,6 +55,102 @@ function parseMongoDB(mongoDbRules, options = {}) {
33
55
  subordinateFieldName,
34
56
  getValueSources
35
57
  });
58
+ const exprCtx = { fieldExists: (fieldName) => fieldsFlat.length === 0 || fieldsFlat.some((f) => f.name === fieldName) };
59
+ /**
60
+ * Parses a `$expr` payload that carries arithmetic/function expression operands. Returns a
61
+ * rule, `false` to drop, or `undefined` when the payload is not an expression form (so the
62
+ * caller falls through to the stock `$expr` handling).
63
+ */
64
+ function processMongoDbExprExpression(op, payload) {
65
+ // v8 ignore next -- guarded at call site
66
+ if (!getExpression) return void 0;
67
+ if (op in mongoDbExprComparisonMap && Array.isArray(payload) && payload.length === 2) {
68
+ const [l, r] = payload;
69
+ const lIsExpr = isMongoDBExpressionOperand(l);
70
+ const rIsExpr = isMongoDBExpressionOperand(r);
71
+ if (!lIsExpr && !rIsExpr) return void 0;
72
+ const rqbOp = mongoDbExprComparisonMap[op];
73
+ if (lIsExpr && rIsExpr) {
74
+ const lhs = getExpression(l, exprCtx);
75
+ const rhs = getExpression(r, exprCtx);
76
+ if (lhs && rhs) return {
77
+ field: "",
78
+ operator: rqbOp,
79
+ lhs,
80
+ value: rhs,
81
+ valueSource: "expression"
82
+ };
83
+ return false;
84
+ }
85
+ if (rIsExpr) {
86
+ const field = mongoDbFieldRef(l);
87
+ if (field !== null) {
88
+ const node = getExpression(r, exprCtx);
89
+ if (node && fieldIsValid(field, rqbOp)) return {
90
+ field,
91
+ operator: rqbOp,
92
+ value: node,
93
+ valueSource: "expression"
94
+ };
95
+ return false;
96
+ }
97
+ const node = getExpression(r, exprCtx);
98
+ if (node) return {
99
+ field: "",
100
+ operator: flipMongoDbOperator(rqbOp),
101
+ lhs: node,
102
+ value: l
103
+ };
104
+ return false;
105
+ }
106
+ const field = mongoDbFieldRef(r);
107
+ if (field !== null) {
108
+ const flipped = flipMongoDbOperator(rqbOp);
109
+ const node = getExpression(l, exprCtx);
110
+ if (node && fieldIsValid(field, flipped)) return {
111
+ field,
112
+ operator: flipped,
113
+ value: node,
114
+ valueSource: "expression"
115
+ };
116
+ return false;
117
+ }
118
+ const node = getExpression(l, exprCtx);
119
+ if (node) return {
120
+ field: "",
121
+ operator: rqbOp,
122
+ lhs: node,
123
+ value: r
124
+ };
125
+ return false;
126
+ }
127
+ if ((op === "$and" || op === "$or") && Array.isArray(payload) && payload.length === 2) {
128
+ const between = op === "$and";
129
+ const [c1, c2] = payload;
130
+ if (!isPojo(c1) || !isPojo(c2)) return void 0;
131
+ const k1 = objectKeys(c1)[0];
132
+ const k2 = objectKeys(c2)[0];
133
+ const [expK1, expK2] = between ? ["$gte", "$lte"] : ["$lt", "$gt"];
134
+ if (k1 !== expK1 || k2 !== expK2) return void 0;
135
+ const a1 = c1[k1];
136
+ const a2 = c2[k2];
137
+ if (!Array.isArray(a1) || a1.length !== 2 || !Array.isArray(a2) || a2.length !== 2) return;
138
+ const field = mongoDbFieldRef(a1[0]);
139
+ if (field === null || field !== mongoDbFieldRef(a2[0])) return void 0;
140
+ const [from, to] = [a1[1], a2[1]];
141
+ if (!isMongoDBExpressionOperand(from) && !isMongoDBExpressionOperand(to)) return void 0;
142
+ const fromNode = getExpression(from, exprCtx);
143
+ const toNode = getExpression(to, exprCtx);
144
+ const operator = between ? "between" : "notBetween";
145
+ if (fromNode && toNode && fieldIsValid(field, operator)) return {
146
+ field,
147
+ operator,
148
+ value: [fromNode, toNode],
149
+ valueSource: "expression"
150
+ };
151
+ return false;
152
+ }
153
+ }
36
154
  function processMongoDbQueryBooleanOperator(field, mdbOperator, keyValue) {
37
155
  let operator = "=";
38
156
  let value = "";
@@ -156,6 +274,10 @@ function parseMongoDB(mongoDbRules, options = {}) {
156
274
  return false;
157
275
  } else if (key === "$expr") {
158
276
  const op = objectKeys(keyValue)[0];
277
+ if (getExpression) {
278
+ const exprRule = processMongoDbExprExpression(op, keyValue[op]);
279
+ if (exprRule !== void 0) return exprRule;
280
+ }
159
281
  if (/^\$(eq|gte?|lte?|n?in)$/.test(op) && Array.isArray(keyValue[op]) && keyValue[op].length === 2 && typeof keyValue[op][0] === "string" && keyValue[op][0].startsWith("$")) {
160
282
  field = keyValue[op][0].replace(/^\$/, "");
161
283
  const val = keyValue[op][1];
@@ -170,6 +292,7 @@ function parseMongoDB(mongoDbRules, options = {}) {
170
292
  };
171
293
  }
172
294
  }
295
+ if (isPojo(keyValue[op][1])) return false;
173
296
  return processMongoDbQueryBooleanOperator(field, op, keyValue[op][1]);
174
297
  }
175
298
  } else if (/^[^$]/.test(key)) {
@@ -258,6 +381,6 @@ function parseMongoDB(mongoDbRules, options = {}) {
258
381
  return prepare(options.independentCombinators ? convertToIC(finalQuery) : finalQuery);
259
382
  }
260
383
  //#endregion
261
- export { parseMongoDB };
384
+ export { isMongoDBExpressionOperand, mongoDbFieldRef, parseMongoDB };
262
385
 
263
386
  //# sourceMappingURL=parseMongoDB.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"parseMongoDB.mjs","names":[],"sources":["../src/utils/parseMongoDB/utils.ts","../src/utils/parseMongoDB/parseMongoDB.ts"],"sourcesContent":["import type { DefaultOperatorName } from '../../types';\nimport type { MongoDbSupportedOperators } from './types';\n\nexport const getRegExStr = (re: string | RegExp): string =>\n typeof re === 'string' ? re : re.source;\n\nexport const isPrimitive = (v: unknown): v is string | number | boolean =>\n typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';\n\nexport const mongoDbToRqbOperatorMap: Partial<\n Record<MongoDbSupportedOperators, DefaultOperatorName>\n> = {\n $eq: '=',\n $ne: '!=',\n $gt: '>',\n $gte: '>=',\n $lt: '<',\n $lte: '<=',\n} satisfies Partial<Record<MongoDbSupportedOperators, DefaultOperatorName>>;\n","import type { Except } from 'type-fest';\nimport { defaultOperatorNegationMap } from '../../defaults';\nimport type {\n DefaultOperatorName,\n DefaultRuleGroupType,\n DefaultRuleGroupTypeAny,\n DefaultRuleGroupTypeIC,\n DefaultRuleType,\n RuleGroupType,\n RuleType,\n} from '../../types';\nimport type { ParserCommonOptions } from '../../types/import';\nimport { joinWith } from '../arrayUtils';\nimport { convertToIC } from '../convertQuery';\nimport { isRuleGroupType } from '../isRuleGroup';\nimport { isPojo } from '../misc';\nimport { objectKeys } from '../objectUtils';\nimport { fieldIsValidUtil, getFieldsArray } from '../parserUtils';\nimport { prepareRuleGroup } from '../prepareQueryObjects';\nimport type { MongoDbSupportedOperators } from './types';\nimport { getRegExStr, isPrimitive, mongoDbToRqbOperatorMap } from './utils';\n\n/**\n * Options object for {@link parseMongoDB}.\n */\nexport interface ParseMongoDbOptions extends ParserCommonOptions {\n /**\n * When `true`, MongoDB rules in the form of `{ fieldName: { $not: { <...rule> } } }`\n * will be parsed into a rule group with the `not` attribute set to `true`. By default\n * (i.e., when this attribute is `false`), such \"`$not`\" rules will be parsed into a\n * rule with a negated operator.\n *\n * For example, with `preventOperatorNegation` set to `true`, a MongoDB rule like this...\n *\n * ```ts\n * { fieldName: { $not: { $eq: 1 } } }\n * ```\n *\n * ...would yield a rule group like this:\n *\n * ```ts\n * {\n * combinator: 'and',\n * not: true,\n * rules: [{ field: 'fieldName', operator: '=', value: 1 }]\n * }\n * ```\n *\n * By default, the same MongoDB rule would yield a rule like this:\n *\n * ```ts\n * { field: 'fieldName', operator: '!=', value: 1 }\n * // negated operator ^\n * ```\n *\n * @default false\n */\n preventOperatorNegation?: boolean;\n /**\n * Map of additional operators to their respective processing functions. Operators\n * must begin with `\"$\"`. Processing functions should return either a {@link index!RuleType RuleType}\n * or {@link index!RuleGroupType RuleGroupType}.\n *\n * (The functions should _not_ return {@link index!RuleGroupTypeIC RuleGroupTypeIC}, even if using independent\n * combinators. If the `independentCombinators` option is `true`, `parseMongoDB`\n * will convert the final query to {@link index!RuleGroupTypeIC RuleGroupTypeIC} before returning it.)\n *\n * @default {}\n */\n additionalOperators?: Record<\n `$${string}`,\n (\n field: string,\n operator: string,\n // oxlint-disable-next-line typescript/no-explicit-any\n value: any,\n options: ParserCommonOptions\n ) => RuleType | RuleGroupType\n >;\n}\n\nconst emptyRuleGroup: DefaultRuleGroupType = { combinator: 'and', rules: [] };\n\n/**\n * Converts a MongoDB query object or parseable string into a query suitable\n * for the {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupType DefaultRuleGroupType}).\n */\n// oxlint-disable-next-line typescript/no-explicit-any\nfunction parseMongoDB(mongoDbRules: string | Record<string, any>): DefaultRuleGroupType;\n/**\n * Converts a MongoDB query object or parseable string into a query suitable\n * for the {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupType DefaultRuleGroupType}).\n */\nfunction parseMongoDB(\n // oxlint-disable-next-line typescript/no-explicit-any\n mongoDbRules: string | Record<string, any>,\n options: Except<ParseMongoDbOptions, 'independentCombinators'> & {\n independentCombinators?: false;\n }\n): DefaultRuleGroupType;\n/**\n * Converts a MongoDB query object or parseable string into a query suitable\n * for the {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupTypeIC DefaultRuleGroupTypeIC}).\n */\nfunction parseMongoDB(\n // oxlint-disable-next-line typescript/no-explicit-any\n mongoDbRules: string | Record<string, any>,\n options: Except<ParseMongoDbOptions, 'independentCombinators'> & {\n independentCombinators: true;\n }\n): DefaultRuleGroupTypeIC;\nfunction parseMongoDB(\n // oxlint-disable-next-line typescript/no-explicit-any\n mongoDbRules: string | Record<string, any>,\n options: ParseMongoDbOptions = {}\n): DefaultRuleGroupTypeAny {\n const listsAsArrays = !!options.listsAsArrays;\n const fieldsFlat = getFieldsArray(options.fields);\n const getValueSources = options.getValueSources;\n const additionalOperators = options.additionalOperators ?? {};\n const preventOperatorNegation = !!options.preventOperatorNegation;\n const { additionalOperators: _ao, ...otherOptions } = options;\n\n const fieldIsValid = (\n fieldName: string,\n operator: DefaultOperatorName,\n subordinateFieldName?: string\n ) =>\n fieldIsValidUtil({\n fieldName,\n fieldsFlat,\n operator,\n subordinateFieldName,\n getValueSources,\n });\n\n function processMongoDbQueryBooleanOperator(\n field: string,\n mdbOperator: MongoDbSupportedOperators,\n // oxlint-disable-next-line typescript/no-explicit-any\n keyValue: any\n ): DefaultRuleType | false {\n let operator: DefaultOperatorName = '=';\n // oxlint-disable-next-line typescript/no-explicit-any\n let value: any = '';\n\n // v8 ignore else\n if (\n mdbOperator === '$eq' ||\n mdbOperator === '$ne' ||\n mdbOperator === '$gt' ||\n mdbOperator === '$gte' ||\n mdbOperator === '$lt' ||\n mdbOperator === '$lte'\n ) {\n if (mdbOperator === '$ne' && keyValue === null) {\n if (fieldIsValid(field, 'notNull')) {\n return { field, operator: 'notNull', value: null };\n }\n } else {\n operator = mongoDbToRqbOperatorMap[mdbOperator]!;\n if (fieldIsValid(field, operator)) {\n return { field, operator, value: keyValue };\n }\n }\n } else if (mdbOperator === '$regex' && /^[^$^]$|^[^^].*[^$]$/.test(getRegExStr(keyValue))) {\n if (fieldIsValid(field, 'contains')) {\n return {\n field,\n operator: 'contains',\n value: getRegExStr(keyValue),\n };\n }\n } else if (mdbOperator === '$regex' && /^\\^.*[^$]/.test(getRegExStr(keyValue))) {\n if (fieldIsValid(field, 'beginsWith')) {\n return {\n field,\n operator: 'beginsWith',\n value: getRegExStr(keyValue).replace(/^\\^/, ''),\n };\n }\n } else if (mdbOperator === '$regex' && /[^^].*\\$/.test(getRegExStr(keyValue))) {\n if (fieldIsValid(field, 'endsWith')) {\n return {\n field,\n operator: 'endsWith',\n value: getRegExStr(keyValue).replace(/\\$$/, ''),\n };\n }\n } else if (mdbOperator === '$in' && Array.isArray(keyValue)) {\n if (fieldIsValid(field, 'in')) {\n value = listsAsArrays\n ? keyValue\n : joinWith(\n keyValue.map(v => `${v}`),\n ','\n );\n return { field, operator: 'in', value };\n }\n } else if (mdbOperator === '$nin' && Array.isArray(keyValue) && fieldIsValid(field, 'notIn')) {\n value = listsAsArrays\n ? keyValue\n : joinWith(\n keyValue.map(v => `${v}`),\n ','\n );\n return { field, operator: 'notIn', value };\n }\n\n return false;\n }\n\n function processMongoDbQueryObjectKey(\n key: string,\n // oxlint-disable-next-line typescript/no-explicit-any\n keyValue: any\n ): DefaultRuleType | DefaultRuleGroupType | false {\n let field = '';\n\n // v8 ignore else\n if (key === '$and') {\n if (!Array.isArray(keyValue) || keyValue.length === 0 || !keyValue.every(v => isPojo(v))) {\n return false;\n }\n\n // Check if this should result in a \"between\" clause\n if (keyValue.length === 2 && keyValue.every(kv => objectKeys(kv).length === 1)) {\n const [rule1, rule2] = keyValue;\n const [ruleKey1, ruleKey2] = keyValue.map(kv => objectKeys(kv)[0]);\n if (\n ruleKey1 === ruleKey2 &&\n isPojo(rule1[ruleKey1]) &&\n objectKeys(rule1[ruleKey1]).length === 1 &&\n isPojo(rule2[ruleKey2]) &&\n objectKeys(rule2[ruleKey2]).length === 1 &&\n (('$gte' in rule1[ruleKey1] &&\n '$lte' in rule2[ruleKey2] &&\n rule2[ruleKey2].$lte >= rule1[ruleKey1].$gte) ||\n ('$lte' in rule1[ruleKey1] &&\n '$gte' in rule2[ruleKey2] &&\n rule1[ruleKey1].$lte >= rule2[ruleKey2].$gte))\n ) {\n const [val1, val2] = [\n rule1[ruleKey1].$gte ?? rule1[ruleKey1].$lte,\n rule2[ruleKey2].$lte ?? rule2[ruleKey2].$gte,\n ];\n let value = listsAsArrays ? [val1, val2] : joinWith([val1, val2], ',');\n if (val1 > val2) {\n value = listsAsArrays ? [val2, val1] : joinWith([val2, val1], ',');\n }\n return { field: ruleKey1, operator: 'between', value };\n }\n }\n\n const rules = keyValue.map(l => processMongoDbQueryObject(l)).filter(Boolean) as (\n | DefaultRuleType\n | DefaultRuleGroupType\n )[];\n\n return rules.length > 0 ? { combinator: 'and', rules } : false;\n } else if (key === '$or') {\n if (!Array.isArray(keyValue) || keyValue.length === 0 || !keyValue.every(v => isPojo(v))) {\n return false;\n }\n\n // Check if this should result in \"notBetween\"\n if (keyValue.length === 2 && keyValue.every(kv => objectKeys(kv).length === 1)) {\n const [rule1, rule2] = keyValue;\n const [ruleKey1, ruleKey2] = keyValue.map(kv => objectKeys(kv)[0]);\n if (\n ruleKey1 === ruleKey2 &&\n isPojo(rule1[ruleKey1]) &&\n objectKeys(rule1[ruleKey1]).length === 1 &&\n isPojo(rule2[ruleKey2]) &&\n objectKeys(rule2[ruleKey2]).length === 1 &&\n (('$gt' in rule1[ruleKey1] &&\n '$lt' in rule2[ruleKey2] &&\n rule1[ruleKey1].$gt >= rule2[ruleKey2].$lt) ||\n ('$lt' in rule1[ruleKey1] &&\n '$gt' in rule2[ruleKey2] &&\n rule2[ruleKey2].$gt >= rule1[ruleKey1].$lt))\n ) {\n const [val1, val2] = [\n rule1[ruleKey1].$gt ?? rule1[ruleKey1].$lt,\n rule2[ruleKey2].$lt ?? rule2[ruleKey2].$gt,\n ];\n let value = listsAsArrays ? [val1, val2] : `${val1},${val2}`;\n if (val1 > val2) {\n value = listsAsArrays ? [val2, val1] : `${val2},${val1}`;\n }\n return { field: ruleKey1, operator: 'notBetween', value };\n }\n }\n\n const rules = keyValue.map(l => processMongoDbQueryObject(l)).filter(Boolean) as (\n | DefaultRuleType\n | DefaultRuleGroupType\n )[];\n\n return rules.length > 0 ? { combinator: 'or', rules } : false;\n } else if (key === '$not' && isPojo(keyValue)) {\n const ruleOrGroup = processMongoDbQueryObject(keyValue);\n if (ruleOrGroup) {\n if (isRuleGroupType(ruleOrGroup)) {\n return ruleOrGroup.not\n ? { combinator: 'and', rules: [ruleOrGroup], not: true }\n : { ...ruleOrGroup, not: true };\n }\n return preventOperatorNegation\n ? { combinator: 'and', rules: [ruleOrGroup], not: true }\n : { ...ruleOrGroup, operator: defaultOperatorNegationMap[ruleOrGroup.operator] };\n }\n return false;\n } else if (key === '$expr') {\n const op = objectKeys(keyValue)[0] as MongoDbSupportedOperators;\n if (\n /^\\$(eq|gte?|lte?|n?in)$/.test(op) &&\n Array.isArray(keyValue[op]) &&\n keyValue[op].length === 2 &&\n typeof keyValue[op][0] === 'string' &&\n keyValue[op][0].startsWith('$')\n ) {\n field = keyValue[op][0].replace(/^\\$/, '');\n const val = keyValue[op][1];\n if (\n (typeof val === 'string' && val.startsWith('$')) ||\n (Array.isArray(val) &&\n val.every(v => typeof v === 'string') &&\n val.every(v => v.startsWith('$')))\n ) {\n const valForProcessing = Array.isArray(val)\n ? val.map(v => v.replace(/^\\$/, ''))\n : val.replace(/^\\$/, '');\n const tempRule = processMongoDbQueryBooleanOperator(field, op, valForProcessing);\n if (tempRule) {\n if (\n typeof tempRule.value === 'string' &&\n !fieldIsValid(field, tempRule.operator, tempRule.value)\n ) {\n return false;\n }\n return { ...tempRule, valueSource: 'field' };\n }\n }\n return processMongoDbQueryBooleanOperator(field, op, keyValue[op][1]);\n }\n } else if (/^[^$]/.test(key)) {\n field = key;\n\n if (isPrimitive(keyValue)) {\n if (fieldIsValid(field, '=')) {\n return { field, operator: '=', value: keyValue };\n }\n } else if (keyValue === null) {\n if (fieldIsValid(field, 'null')) {\n return { field, operator: 'null', value: keyValue };\n }\n } else if (isPojo(keyValue)) {\n let betweenRule: DefaultRuleType | false = false;\n let notRule: DefaultRuleType | DefaultRuleGroupType | false = false;\n const additionalOpKeys = objectKeys(additionalOperators).map(o => o.replace(/^\\$/, ''));\n const allOps = ['eq', 'ne', 'gte?', 'lte?', 'n?in', 'regex', 'not', ...additionalOpKeys];\n const acceptedOpsRegExp = new RegExp(`^\\\\$(${allOps.join('|')})$`);\n\n const operators = objectKeys(keyValue)\n .filter(o => acceptedOpsRegExp.test(o))\n // oxlint-disable-next-line no-array-sort\n .sort() as MongoDbSupportedOperators[];\n\n if (operators.length === 0) {\n return false;\n }\n\n if ('$not' in keyValue && isPojo(keyValue.$not)) {\n const invertedNotRule = processMongoDbQueryObject({ [field]: keyValue.$not });\n if (invertedNotRule) {\n if (isRuleGroupType(invertedNotRule)) {\n notRule = { ...invertedNotRule, not: true };\n } else {\n notRule = preventOperatorNegation\n ? { combinator: 'and', rules: [invertedNotRule], not: true }\n : {\n ...invertedNotRule,\n operator: defaultOperatorNegationMap[invertedNotRule.operator],\n };\n }\n }\n }\n\n if ('$gte' in keyValue && '$lte' in keyValue) {\n // This is (at least) a compact \"between\" clause\n betweenRule = {\n field,\n operator: 'between',\n value: listsAsArrays\n ? [keyValue.$gte, keyValue.$lte]\n : `${keyValue.$gte},${keyValue.$lte}`,\n };\n }\n\n const rules = operators\n // filter out $not\n .filter(op => !(notRule && op === '$not'))\n // filter out $gte and $lte if they were both present\n .filter(op => !(betweenRule && (op === '$gte' || op === '$lte')))\n .map(op =>\n op in additionalOperators && typeof additionalOperators[op] === 'function'\n ? additionalOperators[op](field, op, keyValue[op], otherOptions)\n : processMongoDbQueryBooleanOperator(field, op, keyValue[op])\n )\n .filter(Boolean) as (DefaultRuleGroupType | DefaultRuleType)[];\n\n if (notRule) {\n rules.unshift(notRule);\n }\n\n if (betweenRule) {\n rules.unshift(betweenRule);\n }\n\n if (rules.length === 0) {\n return false;\n }\n if (rules.length === 1) {\n return rules[0];\n }\n return { combinator: 'and', rules };\n }\n }\n\n return false;\n }\n\n function processMongoDbQueryObject(\n // oxlint-disable-next-line typescript/no-explicit-any\n mongoDbQueryObject: Record<string, any>\n ): DefaultRuleGroupType | DefaultRuleType | false {\n const rules = objectKeys(mongoDbQueryObject)\n .map(k => processMongoDbQueryObjectKey(k, mongoDbQueryObject[k]))\n .filter(Boolean) as DefaultRuleGroupType[];\n return rules.length === 1 ? rules[0] : rules.length > 1 ? { combinator: 'and', rules } : false;\n }\n\n const prepare = options.generateIDs ? prepareRuleGroup : <T>(g: T) => g;\n\n let mongoDbPOJO = mongoDbRules;\n if (typeof mongoDbRules === 'string') {\n try {\n mongoDbPOJO = JSON.parse(mongoDbRules);\n } catch {\n return prepare(emptyRuleGroup);\n }\n }\n\n // Bail if the mongoDbPOJO is not actually a POJO\n if (!isPojo(mongoDbPOJO)) {\n return prepare(emptyRuleGroup);\n }\n\n const result = processMongoDbQueryObject(mongoDbPOJO);\n const finalQuery: DefaultRuleGroupType = result\n ? isRuleGroupType(result)\n ? result\n : { combinator: 'and', rules: [result] }\n : emptyRuleGroup;\n return prepare(options.independentCombinators ? convertToIC(finalQuery) : finalQuery);\n}\n\nexport { parseMongoDB };\n"],"mappings":"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"}
1
+ {"version":3,"file":"parseMongoDB.mjs","names":[],"sources":["../src/utils/parseMongoDB/utils.ts","../src/utils/parseMongoDB/parseMongoDB.ts"],"sourcesContent":["import type { DefaultOperatorName } from '../../types';\nimport { isPojo } from '../misc';\nimport type { MongoDbSupportedOperators } from './types';\n\nexport const getRegExStr = (re: string | RegExp): string =>\n typeof re === 'string' ? re : re.source;\n\nexport const isPrimitive = (v: unknown): v is string | number | boolean =>\n typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean';\n\nexport const mongoDbToRqbOperatorMap: Partial<\n Record<MongoDbSupportedOperators, DefaultOperatorName>\n> = {\n $eq: '=',\n $ne: '!=',\n $gt: '>',\n $gte: '>=',\n $lt: '<',\n $lte: '<=',\n} satisfies Partial<Record<MongoDbSupportedOperators, DefaultOperatorName>>;\n\n/** Comparison aggregation operators that can carry expression operands, mapped to RQB operators. */\nexport const mongoDbExprComparisonMap: Record<string, DefaultOperatorName> = {\n $eq: '=',\n $ne: '!=',\n $gt: '>',\n $gte: '>=',\n $lt: '<',\n $lte: '<=',\n};\n\n/** Flips a comparison operator (for operand order reversal); non-comparisons pass through. */\nexport const flipMongoDbOperator = (op: DefaultOperatorName): DefaultOperatorName =>\n op === '<' ? '>' : op === '<=' ? '>=' : op === '>' ? '<' : op === '>=' ? '<=' : op;\n\n/**\n * A MongoDB `$expr` comparison operand that is a candidate expression subtree: an\n * aggregation-operator object (e.g. `{ $multiply: [...] }`). Bare `\"$field\"` strings and\n * literals are not expression operands. The expr-supplied `getExpression` handler decides\n * whether it maps to a known function.\n */\nexport const isMongoDBExpressionOperand = (operand: unknown): boolean => isPojo(operand);\n\n/** Reads a MongoDB field-path operand (`\"$field\"`), returning the field name or `null`. */\nexport const mongoDbFieldRef = (operand: unknown): string | null =>\n typeof operand === 'string' && operand.startsWith('$') ? operand.slice(1) : null;\n","import type { Except } from 'type-fest';\nimport { defaultOperatorNegationMap } from '../../defaults';\nimport type {\n DefaultOperatorName,\n DefaultRuleGroupType,\n DefaultRuleGroupTypeAny,\n DefaultRuleGroupTypeIC,\n DefaultRuleType,\n ExpressionNode,\n RuleGroupType,\n RuleType,\n} from '../../types';\nimport type { ParserCommonOptions } from '../../types/import';\nimport { joinWith } from '../arrayUtils';\nimport { convertToIC } from '../convertQuery';\nimport { isRuleGroupType } from '../isRuleGroup';\nimport { isPojo } from '../misc';\nimport { objectKeys } from '../objectUtils';\nimport { fieldIsValidUtil, getFieldsArray } from '../parserUtils';\nimport { prepareRuleGroup } from '../prepareQueryObjects';\nimport type {\n MongoDBExpressionOperand,\n MongoDbSupportedOperators,\n ParseMongoDBExpressionContext,\n} from './types';\nimport {\n flipMongoDbOperator,\n getRegExStr,\n isMongoDBExpressionOperand,\n isPrimitive,\n mongoDbExprComparisonMap,\n mongoDbFieldRef,\n mongoDbToRqbOperatorMap,\n} from './utils';\n\n/**\n * Options object for {@link parseMongoDB}.\n */\nexport interface ParseMongoDbOptions extends ParserCommonOptions {\n /**\n * When `true`, MongoDB rules in the form of `{ fieldName: { $not: { <...rule> } } }`\n * will be parsed into a rule group with the `not` attribute set to `true`. By default\n * (i.e., when this attribute is `false`), such \"`$not`\" rules will be parsed into a\n * rule with a negated operator.\n *\n * For example, with `preventOperatorNegation` set to `true`, a MongoDB rule like this...\n *\n * ```ts\n * { fieldName: { $not: { $eq: 1 } } }\n * ```\n *\n * ...would yield a rule group like this:\n *\n * ```ts\n * {\n * combinator: 'and',\n * not: true,\n * rules: [{ field: 'fieldName', operator: '=', value: 1 }]\n * }\n * ```\n *\n * By default, the same MongoDB rule would yield a rule like this:\n *\n * ```ts\n * { field: 'fieldName', operator: '!=', value: 1 }\n * // negated operator ^\n * ```\n *\n * @default false\n */\n preventOperatorNegation?: boolean;\n /**\n * Map of additional operators to their respective processing functions. Operators\n * must begin with `\"$\"`. Processing functions should return either a {@link index!RuleType RuleType}\n * or {@link index!RuleGroupType RuleGroupType}.\n *\n * (The functions should _not_ return {@link index!RuleGroupTypeIC RuleGroupTypeIC}, even if using independent\n * combinators. If the `independentCombinators` option is `true`, `parseMongoDB`\n * will convert the final query to {@link index!RuleGroupTypeIC RuleGroupTypeIC} before returning it.)\n *\n * @default {}\n */\n additionalOperators?: Record<\n `$${string}`,\n (\n field: string,\n operator: string,\n // oxlint-disable-next-line typescript/no-explicit-any\n value: any,\n options: ParserCommonOptions\n ) => RuleType | RuleGroupType\n >;\n /**\n * Handler that converts a MongoDB aggregation-expression operand (within `$expr`) into an\n * {@link ExpressionNode}. Return `null` to reject (the rule is dropped). Supplied by\n * `@react-querybuilder/expr` (`expressionParserMongoDB`). When omitted, expression\n * operands are ignored (rule dropped).\n */\n getExpression?: (\n node: MongoDBExpressionOperand,\n ctx: ParseMongoDBExpressionContext\n ) => ExpressionNode | null;\n}\n\nconst emptyRuleGroup: DefaultRuleGroupType = { combinator: 'and', rules: [] };\n\n/**\n * Converts a MongoDB query object or parseable string into a query suitable\n * for the {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupType DefaultRuleGroupType}).\n */\n// oxlint-disable-next-line typescript/no-explicit-any\nfunction parseMongoDB(mongoDbRules: string | Record<string, any>): DefaultRuleGroupType;\n/**\n * Converts a MongoDB query object or parseable string into a query suitable\n * for the {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupType DefaultRuleGroupType}).\n */\nfunction parseMongoDB(\n // oxlint-disable-next-line typescript/no-explicit-any\n mongoDbRules: string | Record<string, any>,\n options: Except<ParseMongoDbOptions, 'independentCombinators'> & {\n independentCombinators?: false;\n }\n): DefaultRuleGroupType;\n/**\n * Converts a MongoDB query object or parseable string into a query suitable\n * for the {@link index!QueryBuilder QueryBuilder} component's `query` or `defaultQuery` props\n * ({@link index!DefaultRuleGroupTypeIC DefaultRuleGroupTypeIC}).\n */\nfunction parseMongoDB(\n // oxlint-disable-next-line typescript/no-explicit-any\n mongoDbRules: string | Record<string, any>,\n options: Except<ParseMongoDbOptions, 'independentCombinators'> & {\n independentCombinators: true;\n }\n): DefaultRuleGroupTypeIC;\nfunction parseMongoDB(\n // oxlint-disable-next-line typescript/no-explicit-any\n mongoDbRules: string | Record<string, any>,\n options: ParseMongoDbOptions = {}\n): DefaultRuleGroupTypeAny {\n const listsAsArrays = !!options.listsAsArrays;\n const fieldsFlat = getFieldsArray(options.fields);\n const getValueSources = options.getValueSources;\n const additionalOperators = options.additionalOperators ?? {};\n const preventOperatorNegation = !!options.preventOperatorNegation;\n const getExpression = options.getExpression;\n const { additionalOperators: _ao, ...otherOptions } = options;\n\n const fieldIsValid = (\n fieldName: string,\n operator: DefaultOperatorName,\n subordinateFieldName?: string\n ) =>\n fieldIsValidUtil({\n fieldName,\n fieldsFlat,\n operator,\n subordinateFieldName,\n getValueSources,\n });\n\n const exprCtx: ParseMongoDBExpressionContext = {\n fieldExists: fieldName => fieldsFlat.length === 0 || fieldsFlat.some(f => f.name === fieldName),\n };\n\n /**\n * Parses a `$expr` payload that carries arithmetic/function expression operands. Returns a\n * rule, `false` to drop, or `undefined` when the payload is not an expression form (so the\n * caller falls through to the stock `$expr` handling).\n */\n function processMongoDbExprExpression(\n op: string,\n // oxlint-disable-next-line typescript/no-explicit-any\n payload: any\n ): DefaultRuleType | false | undefined {\n // v8 ignore next -- guarded at call site\n if (!getExpression) return undefined;\n\n // Comparison: { $gt: [lhs, rhs] } with an expression operand\n if (op in mongoDbExprComparisonMap && Array.isArray(payload) && payload.length === 2) {\n const [l, r] = payload;\n const lIsExpr = isMongoDBExpressionOperand(l);\n const rIsExpr = isMongoDBExpressionOperand(r);\n if (!lIsExpr && !rIsExpr) return undefined;\n const rqbOp = mongoDbExprComparisonMap[op];\n\n if (lIsExpr && rIsExpr) {\n // expression <op> expression → both sides on lhs/value\n const lhs = getExpression(l, exprCtx);\n const rhs = getExpression(r, exprCtx);\n if (lhs && rhs) {\n return { field: '', operator: rqbOp, lhs, value: rhs, valueSource: 'expression' };\n }\n return false;\n }\n\n if (rIsExpr) {\n const field = mongoDbFieldRef(l);\n if (field !== null) {\n // field <op> expression → rhs expression\n const node = getExpression(r, exprCtx);\n if (node && fieldIsValid(field, rqbOp)) {\n return { field, operator: rqbOp, value: node, valueSource: 'expression' };\n }\n return false;\n }\n // literal <op> expression → lhs = expression, flip operator\n const node = getExpression(r, exprCtx);\n if (node) {\n return { field: '', operator: flipMongoDbOperator(rqbOp), lhs: node, value: l };\n }\n return false;\n }\n\n // lIsExpr && !rIsExpr\n const field = mongoDbFieldRef(r);\n if (field !== null) {\n // expression <op> field → flip to field <op> expression\n const flipped = flipMongoDbOperator(rqbOp);\n const node = getExpression(l, exprCtx);\n if (node && fieldIsValid(field, flipped)) {\n return { field, operator: flipped, value: node, valueSource: 'expression' };\n }\n return false;\n }\n // expression <op> literal → lhs = expression, plain value\n const node = getExpression(l, exprCtx);\n if (node) {\n return { field: '', operator: rqbOp, lhs: node, value: r };\n }\n return false;\n }\n\n // Between: { $and: [{ $gte: [lhs, from] }, { $lte: [lhs, to] }] }\n // notBetween: { $or: [{ $lt: [lhs, from] }, { $gt: [lhs, to] }] }\n if ((op === '$and' || op === '$or') && Array.isArray(payload) && payload.length === 2) {\n const between = op === '$and';\n const [c1, c2] = payload;\n if (!isPojo(c1) || !isPojo(c2)) return undefined;\n const k1 = objectKeys(c1)[0];\n const k2 = objectKeys(c2)[0];\n const [expK1, expK2] = between ? ['$gte', '$lte'] : ['$lt', '$gt'];\n if (k1 !== expK1 || k2 !== expK2) return undefined;\n const a1 = c1[k1];\n const a2 = c2[k2];\n if (!Array.isArray(a1) || a1.length !== 2 || !Array.isArray(a2) || a2.length !== 2) {\n return undefined;\n }\n const field = mongoDbFieldRef(a1[0]);\n if (field === null || field !== mongoDbFieldRef(a2[0])) return undefined;\n const [from, to] = [a1[1], a2[1]];\n if (!isMongoDBExpressionOperand(from) && !isMongoDBExpressionOperand(to)) return undefined;\n const fromNode = getExpression(from, exprCtx);\n const toNode = getExpression(to, exprCtx);\n const operator: DefaultOperatorName = between ? 'between' : 'notBetween';\n if (fromNode && toNode && fieldIsValid(field, operator)) {\n return { field, operator, value: [fromNode, toNode], valueSource: 'expression' };\n }\n return false;\n }\n\n return undefined;\n }\n\n function processMongoDbQueryBooleanOperator(\n field: string,\n mdbOperator: MongoDbSupportedOperators,\n // oxlint-disable-next-line typescript/no-explicit-any\n keyValue: any\n ): DefaultRuleType | false {\n let operator: DefaultOperatorName = '=';\n // oxlint-disable-next-line typescript/no-explicit-any\n let value: any = '';\n\n // v8 ignore else\n if (\n mdbOperator === '$eq' ||\n mdbOperator === '$ne' ||\n mdbOperator === '$gt' ||\n mdbOperator === '$gte' ||\n mdbOperator === '$lt' ||\n mdbOperator === '$lte'\n ) {\n if (mdbOperator === '$ne' && keyValue === null) {\n if (fieldIsValid(field, 'notNull')) {\n return { field, operator: 'notNull', value: null };\n }\n } else {\n operator = mongoDbToRqbOperatorMap[mdbOperator]!;\n if (fieldIsValid(field, operator)) {\n return { field, operator, value: keyValue };\n }\n }\n } else if (mdbOperator === '$regex' && /^[^$^]$|^[^^].*[^$]$/.test(getRegExStr(keyValue))) {\n if (fieldIsValid(field, 'contains')) {\n return {\n field,\n operator: 'contains',\n value: getRegExStr(keyValue),\n };\n }\n } else if (mdbOperator === '$regex' && /^\\^.*[^$]/.test(getRegExStr(keyValue))) {\n if (fieldIsValid(field, 'beginsWith')) {\n return {\n field,\n operator: 'beginsWith',\n value: getRegExStr(keyValue).replace(/^\\^/, ''),\n };\n }\n } else if (mdbOperator === '$regex' && /[^^].*\\$/.test(getRegExStr(keyValue))) {\n if (fieldIsValid(field, 'endsWith')) {\n return {\n field,\n operator: 'endsWith',\n value: getRegExStr(keyValue).replace(/\\$$/, ''),\n };\n }\n } else if (mdbOperator === '$in' && Array.isArray(keyValue)) {\n if (fieldIsValid(field, 'in')) {\n value = listsAsArrays\n ? keyValue\n : joinWith(\n keyValue.map(v => `${v}`),\n ','\n );\n return { field, operator: 'in', value };\n }\n } else if (mdbOperator === '$nin' && Array.isArray(keyValue) && fieldIsValid(field, 'notIn')) {\n value = listsAsArrays\n ? keyValue\n : joinWith(\n keyValue.map(v => `${v}`),\n ','\n );\n return { field, operator: 'notIn', value };\n }\n\n return false;\n }\n\n function processMongoDbQueryObjectKey(\n key: string,\n // oxlint-disable-next-line typescript/no-explicit-any\n keyValue: any\n ): DefaultRuleType | DefaultRuleGroupType | false {\n let field = '';\n\n // v8 ignore else\n if (key === '$and') {\n if (!Array.isArray(keyValue) || keyValue.length === 0 || !keyValue.every(v => isPojo(v))) {\n return false;\n }\n\n // Check if this should result in a \"between\" clause\n if (keyValue.length === 2 && keyValue.every(kv => objectKeys(kv).length === 1)) {\n const [rule1, rule2] = keyValue;\n const [ruleKey1, ruleKey2] = keyValue.map(kv => objectKeys(kv)[0]);\n if (\n ruleKey1 === ruleKey2 &&\n isPojo(rule1[ruleKey1]) &&\n objectKeys(rule1[ruleKey1]).length === 1 &&\n isPojo(rule2[ruleKey2]) &&\n objectKeys(rule2[ruleKey2]).length === 1 &&\n (('$gte' in rule1[ruleKey1] &&\n '$lte' in rule2[ruleKey2] &&\n rule2[ruleKey2].$lte >= rule1[ruleKey1].$gte) ||\n ('$lte' in rule1[ruleKey1] &&\n '$gte' in rule2[ruleKey2] &&\n rule1[ruleKey1].$lte >= rule2[ruleKey2].$gte))\n ) {\n const [val1, val2] = [\n rule1[ruleKey1].$gte ?? rule1[ruleKey1].$lte,\n rule2[ruleKey2].$lte ?? rule2[ruleKey2].$gte,\n ];\n let value = listsAsArrays ? [val1, val2] : joinWith([val1, val2], ',');\n if (val1 > val2) {\n value = listsAsArrays ? [val2, val1] : joinWith([val2, val1], ',');\n }\n return { field: ruleKey1, operator: 'between', value };\n }\n }\n\n const rules = keyValue.map(l => processMongoDbQueryObject(l)).filter(Boolean) as (\n | DefaultRuleType\n | DefaultRuleGroupType\n )[];\n\n return rules.length > 0 ? { combinator: 'and', rules } : false;\n } else if (key === '$or') {\n if (!Array.isArray(keyValue) || keyValue.length === 0 || !keyValue.every(v => isPojo(v))) {\n return false;\n }\n\n // Check if this should result in \"notBetween\"\n if (keyValue.length === 2 && keyValue.every(kv => objectKeys(kv).length === 1)) {\n const [rule1, rule2] = keyValue;\n const [ruleKey1, ruleKey2] = keyValue.map(kv => objectKeys(kv)[0]);\n if (\n ruleKey1 === ruleKey2 &&\n isPojo(rule1[ruleKey1]) &&\n objectKeys(rule1[ruleKey1]).length === 1 &&\n isPojo(rule2[ruleKey2]) &&\n objectKeys(rule2[ruleKey2]).length === 1 &&\n (('$gt' in rule1[ruleKey1] &&\n '$lt' in rule2[ruleKey2] &&\n rule1[ruleKey1].$gt >= rule2[ruleKey2].$lt) ||\n ('$lt' in rule1[ruleKey1] &&\n '$gt' in rule2[ruleKey2] &&\n rule2[ruleKey2].$gt >= rule1[ruleKey1].$lt))\n ) {\n const [val1, val2] = [\n rule1[ruleKey1].$gt ?? rule1[ruleKey1].$lt,\n rule2[ruleKey2].$lt ?? rule2[ruleKey2].$gt,\n ];\n let value = listsAsArrays ? [val1, val2] : `${val1},${val2}`;\n if (val1 > val2) {\n value = listsAsArrays ? [val2, val1] : `${val2},${val1}`;\n }\n return { field: ruleKey1, operator: 'notBetween', value };\n }\n }\n\n const rules = keyValue.map(l => processMongoDbQueryObject(l)).filter(Boolean) as (\n | DefaultRuleType\n | DefaultRuleGroupType\n )[];\n\n return rules.length > 0 ? { combinator: 'or', rules } : false;\n } else if (key === '$not' && isPojo(keyValue)) {\n const ruleOrGroup = processMongoDbQueryObject(keyValue);\n if (ruleOrGroup) {\n if (isRuleGroupType(ruleOrGroup)) {\n return ruleOrGroup.not\n ? { combinator: 'and', rules: [ruleOrGroup], not: true }\n : { ...ruleOrGroup, not: true };\n }\n return preventOperatorNegation\n ? { combinator: 'and', rules: [ruleOrGroup], not: true }\n : { ...ruleOrGroup, operator: defaultOperatorNegationMap[ruleOrGroup.operator] };\n }\n return false;\n } else if (key === '$expr') {\n const op = objectKeys(keyValue)[0] as MongoDbSupportedOperators;\n if (getExpression) {\n const exprRule = processMongoDbExprExpression(op, keyValue[op]);\n if (exprRule !== undefined) return exprRule;\n }\n if (\n /^\\$(eq|gte?|lte?|n?in)$/.test(op) &&\n Array.isArray(keyValue[op]) &&\n keyValue[op].length === 2 &&\n typeof keyValue[op][0] === 'string' &&\n keyValue[op][0].startsWith('$')\n ) {\n field = keyValue[op][0].replace(/^\\$/, '');\n const val = keyValue[op][1];\n if (\n (typeof val === 'string' && val.startsWith('$')) ||\n (Array.isArray(val) &&\n val.every(v => typeof v === 'string') &&\n val.every(v => v.startsWith('$')))\n ) {\n const valForProcessing = Array.isArray(val)\n ? val.map(v => v.replace(/^\\$/, ''))\n : val.replace(/^\\$/, '');\n const tempRule = processMongoDbQueryBooleanOperator(field, op, valForProcessing);\n if (tempRule) {\n if (\n typeof tempRule.value === 'string' &&\n !fieldIsValid(field, tempRule.operator, tempRule.value)\n ) {\n return false;\n }\n return { ...tempRule, valueSource: 'field' };\n }\n }\n // An aggregation-object operand requires a `getExpression` handler; without one it\n // cannot be represented, so drop the rule rather than emit an object-valued rule.\n if (isPojo(keyValue[op][1])) {\n return false;\n }\n return processMongoDbQueryBooleanOperator(field, op, keyValue[op][1]);\n }\n } else if (/^[^$]/.test(key)) {\n field = key;\n\n if (isPrimitive(keyValue)) {\n if (fieldIsValid(field, '=')) {\n return { field, operator: '=', value: keyValue };\n }\n } else if (keyValue === null) {\n if (fieldIsValid(field, 'null')) {\n return { field, operator: 'null', value: keyValue };\n }\n } else if (isPojo(keyValue)) {\n let betweenRule: DefaultRuleType | false = false;\n let notRule: DefaultRuleType | DefaultRuleGroupType | false = false;\n const additionalOpKeys = objectKeys(additionalOperators).map(o => o.replace(/^\\$/, ''));\n const allOps = ['eq', 'ne', 'gte?', 'lte?', 'n?in', 'regex', 'not', ...additionalOpKeys];\n const acceptedOpsRegExp = new RegExp(`^\\\\$(${allOps.join('|')})$`);\n\n const operators = objectKeys(keyValue)\n .filter(o => acceptedOpsRegExp.test(o))\n // oxlint-disable-next-line no-array-sort\n .sort() as MongoDbSupportedOperators[];\n\n if (operators.length === 0) {\n return false;\n }\n\n if ('$not' in keyValue && isPojo(keyValue.$not)) {\n const invertedNotRule = processMongoDbQueryObject({ [field]: keyValue.$not });\n if (invertedNotRule) {\n if (isRuleGroupType(invertedNotRule)) {\n notRule = { ...invertedNotRule, not: true };\n } else {\n notRule = preventOperatorNegation\n ? { combinator: 'and', rules: [invertedNotRule], not: true }\n : {\n ...invertedNotRule,\n operator: defaultOperatorNegationMap[invertedNotRule.operator],\n };\n }\n }\n }\n\n if ('$gte' in keyValue && '$lte' in keyValue) {\n // This is (at least) a compact \"between\" clause\n betweenRule = {\n field,\n operator: 'between',\n value: listsAsArrays\n ? [keyValue.$gte, keyValue.$lte]\n : `${keyValue.$gte},${keyValue.$lte}`,\n };\n }\n\n const rules = operators\n // filter out $not\n .filter(op => !(notRule && op === '$not'))\n // filter out $gte and $lte if they were both present\n .filter(op => !(betweenRule && (op === '$gte' || op === '$lte')))\n .map(op =>\n op in additionalOperators && typeof additionalOperators[op] === 'function'\n ? additionalOperators[op](field, op, keyValue[op], otherOptions)\n : processMongoDbQueryBooleanOperator(field, op, keyValue[op])\n )\n .filter(Boolean) as (DefaultRuleGroupType | DefaultRuleType)[];\n\n if (notRule) {\n rules.unshift(notRule);\n }\n\n if (betweenRule) {\n rules.unshift(betweenRule);\n }\n\n if (rules.length === 0) {\n return false;\n }\n if (rules.length === 1) {\n return rules[0];\n }\n return { combinator: 'and', rules };\n }\n }\n\n return false;\n }\n\n function processMongoDbQueryObject(\n // oxlint-disable-next-line typescript/no-explicit-any\n mongoDbQueryObject: Record<string, any>\n ): DefaultRuleGroupType | DefaultRuleType | false {\n const rules = objectKeys(mongoDbQueryObject)\n .map(k => processMongoDbQueryObjectKey(k, mongoDbQueryObject[k]))\n .filter(Boolean) as DefaultRuleGroupType[];\n return rules.length === 1 ? rules[0] : rules.length > 1 ? { combinator: 'and', rules } : false;\n }\n\n const prepare = options.generateIDs ? prepareRuleGroup : <T>(g: T) => g;\n\n let mongoDbPOJO = mongoDbRules;\n if (typeof mongoDbRules === 'string') {\n try {\n mongoDbPOJO = JSON.parse(mongoDbRules);\n } catch {\n return prepare(emptyRuleGroup);\n }\n }\n\n // Bail if the mongoDbPOJO is not actually a POJO\n if (!isPojo(mongoDbPOJO)) {\n return prepare(emptyRuleGroup);\n }\n\n const result = processMongoDbQueryObject(mongoDbPOJO);\n const finalQuery: DefaultRuleGroupType = result\n ? isRuleGroupType(result)\n ? result\n : { combinator: 'and', rules: [result] }\n : emptyRuleGroup;\n return prepare(options.independentCombinators ? convertToIC(finalQuery) : finalQuery);\n}\n\nexport { parseMongoDB };\n"],"mappings":"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"}
@@ -1,27 +1,26 @@
1
- import { E as DefaultRuleGroupType, x as DefaultRuleGroupTypeIC } from "./index-DlVg-QXo.mjs";
2
-
1
+ import { T as DefaultRuleGroupTypeIC, j as DefaultRuleGroupType } from "./index-BSwFvkeI.mjs";
3
2
  //#region src/utils/parseSPARQL/parseSPARQL.d.ts
4
3
  /**
5
- * Options for {@link parseSPARQL}.
6
- */
4
+ * Options for {@link parseSPARQL}.
5
+ */
7
6
  interface ParseSPARQLOptions {
8
7
  independentCombinators?: boolean;
9
8
  }
10
9
  /**
11
- * Parses a SPARQL query string into a {@link DefaultRuleGroupType}.
12
- *
13
- * Accepts a full SPARQL query or a `FILTER` expression. Triple patterns are
14
- * consumed but discarded — only FILTER conditions are returned.
15
- *
16
- * @example
17
- * ```ts
18
- * // Full query — extracts FILTER conditions only
19
- * parseSPARQL('SELECT ?x WHERE { ?x foaf:name ?name . FILTER(?age > 30) }');
20
- *
21
- * // Bare FILTER expression wrapped in a stub query
22
- * parseSPARQL('?age > 30 && ?name != "Alice"');
23
- * ```
24
- */
10
+ * Parses a SPARQL query string into a {@link DefaultRuleGroupType}.
11
+ *
12
+ * Accepts a full SPARQL query or a `FILTER` expression. Triple patterns are
13
+ * consumed but discarded — only FILTER conditions are returned.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * // Full query — extracts FILTER conditions only
18
+ * parseSPARQL('SELECT ?x WHERE { ?x foaf:name ?name . FILTER(?age > 30) }');
19
+ *
20
+ * // Bare FILTER expression wrapped in a stub query
21
+ * parseSPARQL('?age > 30 && ?name != "Alice"');
22
+ * ```
23
+ */
25
24
  declare function parseSPARQL(sparql: string): DefaultRuleGroupType;
26
25
  declare function parseSPARQL(sparql: string, options: Omit<ParseSPARQLOptions, "independentCombinators"> & {
27
26
  independentCombinators?: false;
@@ -1,27 +1,26 @@
1
- import { E as DefaultRuleGroupType, x as DefaultRuleGroupTypeIC } from "./index-DlVg-QXo.js";
2
-
1
+ import { T as DefaultRuleGroupTypeIC, j as DefaultRuleGroupType } from "./index-BSwFvkeI.js";
3
2
  //#region src/utils/parseSPARQL/parseSPARQL.d.ts
4
3
  /**
5
- * Options for {@link parseSPARQL}.
6
- */
4
+ * Options for {@link parseSPARQL}.
5
+ */
7
6
  interface ParseSPARQLOptions {
8
7
  independentCombinators?: boolean;
9
8
  }
10
9
  /**
11
- * Parses a SPARQL query string into a {@link DefaultRuleGroupType}.
12
- *
13
- * Accepts a full SPARQL query or a `FILTER` expression. Triple patterns are
14
- * consumed but discarded — only FILTER conditions are returned.
15
- *
16
- * @example
17
- * ```ts
18
- * // Full query — extracts FILTER conditions only
19
- * parseSPARQL('SELECT ?x WHERE { ?x foaf:name ?name . FILTER(?age > 30) }');
20
- *
21
- * // Bare FILTER expression wrapped in a stub query
22
- * parseSPARQL('?age > 30 && ?name != "Alice"');
23
- * ```
24
- */
10
+ * Parses a SPARQL query string into a {@link DefaultRuleGroupType}.
11
+ *
12
+ * Accepts a full SPARQL query or a `FILTER` expression. Triple patterns are
13
+ * consumed but discarded — only FILTER conditions are returned.
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * // Full query — extracts FILTER conditions only
18
+ * parseSPARQL('SELECT ?x WHERE { ?x foaf:name ?name . FILTER(?age > 30) }');
19
+ *
20
+ * // Bare FILTER expression wrapped in a stub query
21
+ * parseSPARQL('?age > 30 && ?name != "Alice"');
22
+ * ```
23
+ */
25
24
  declare function parseSPARQL(sparql: string): DefaultRuleGroupType;
26
25
  declare function parseSPARQL(sparql: string, options: Omit<ParseSPARQLOptions, "independentCombinators"> & {
27
26
  independentCombinators?: false;
@@ -1 +1 @@
1
- {"version":3,"file":"parseSPARQL.js","names":["SparqlParser"],"sources":["../src/utils/parseSPARQL/parseSPARQL.ts"],"sourcesContent":["import { Parser as SparqlParser } from '@traqula/parser-sparql-1-2';\nimport type {\n DefaultRuleGroupType,\n DefaultRuleGroupTypeAny,\n DefaultRuleGroupTypeIC,\n DefaultRuleType,\n} from '../../types';\n\n// Reuse a single parser instance (Chevrotain-backed; creating parsers is expensive)\nlet parserInstance: SparqlParser | undefined;\nconst getParser = (): SparqlParser => {\n if (!parserInstance) {\n parserInstance = new SparqlParser();\n }\n return parserInstance;\n};\n\n// ─── Traqula AST Type Subset ─────────────────────────────────────────────────\n\ninterface TraqulaQuery {\n type: 'query';\n subType: string;\n where?: TraqulaPatternGroup;\n [key: string]: unknown;\n}\n\ninterface TraqulaPatternGroup {\n type: 'pattern';\n subType: 'group';\n patterns: TraqulaPattern[];\n}\n\ntype TraqulaPattern =\n | TraqulaBgp\n | TraqulaOptional\n | TraqulaFilter\n | TraqulaPatternGroup\n | TraqulaUnion\n | { type: 'pattern'; subType: string; [key: string]: unknown }\n | TraqulaQuery;\n\ninterface TraqulaBgp {\n type: 'pattern';\n subType: 'bgp';\n triples: TraqulaTriple[];\n}\n\ninterface TraqulaOptional {\n type: 'pattern';\n subType: 'optional';\n patterns: TraqulaPattern[];\n}\n\ninterface TraqulaFilter {\n type: 'pattern';\n subType: 'filter';\n expression: TraqulaExpression;\n}\n\ninterface TraqulaUnion {\n type: 'pattern';\n subType: 'union';\n patterns: TraqulaPatternGroup[];\n}\n\ninterface TraqulaTriple {\n type: 'triple';\n subject: TraqulaTerm;\n predicate: TraqulaTerm;\n object: TraqulaTerm;\n}\n\ninterface TraqulaTerm {\n type: 'term' | 'path' | 'wildcard';\n subType?: string;\n value?: string;\n prefix?: string;\n langOrIri?: unknown;\n [key: string]: unknown;\n}\n\ninterface TraqulaExpression {\n type: 'expression' | 'term';\n subType: string;\n operator?: string;\n args?: (TraqulaExpression | TraqulaTerm)[];\n value?: string;\n prefix?: string;\n langOrIri?: unknown;\n [key: string]: unknown;\n}\n\n// ─── AST Walker ──────────────────────────────────────────────────────────────\n\n/** Serializes a Traqula term into a user-facing string. */\nconst termToString = (term: TraqulaTerm): string => {\n if (term.type === 'term') {\n switch (term.subType) {\n case 'variable':\n return `?${term.value}`;\n case 'namedNode':\n if (term.prefix !== undefined && term.prefix !== '') {\n return `${term.prefix}:${term.value}`;\n }\n return term.value ?? '';\n case 'literal':\n return term.value ?? '';\n case 'blankNode':\n return `_:${(term as { label?: string }).label ?? ''}`;\n default:\n return term.value ?? '';\n }\n }\n return '';\n};\n\n/** Extracts a literal JS value from a Traqula term. */\nconst termToLiteralValue = (term: TraqulaTerm | TraqulaExpression): unknown => {\n if (term.type === 'term' && term.subType === 'literal') {\n const raw = term.value ?? '';\n if (term.langOrIri && typeof term.langOrIri === 'object') {\n const iri = term.langOrIri as TraqulaTerm;\n const datatype = iri.value ?? '';\n if (\n datatype.endsWith('#integer') ||\n datatype.endsWith('#decimal') ||\n datatype.endsWith('#double') ||\n datatype.endsWith('#float')\n ) {\n return Number(raw);\n }\n if (datatype.endsWith('#boolean')) {\n return raw === 'true';\n }\n }\n const num = Number(raw);\n if (raw !== '' && !Number.isNaN(num)) return num;\n return raw;\n }\n if (term.type === 'term' && term.subType === 'variable') {\n return `?${term.value}`;\n }\n if (term.type === 'term' && term.subType === 'namedNode') {\n return termToString(term as TraqulaTerm);\n }\n return term.value ?? '';\n};\n\n/** Walks patterns, extracting only FILTER expressions (skipping BGP triples). */\nconst visitPatterns = (\n patterns: TraqulaPattern[],\n out: (DefaultRuleType | DefaultRuleGroupType)[]\n): void => {\n for (const p of patterns) {\n if (p.type === 'pattern') {\n switch (p.subType) {\n case 'bgp':\n // Skip triple patterns — Phase 1 only extracts filter conditions\n break;\n case 'optional':\n visitPatterns((p as TraqulaOptional).patterns, out);\n break;\n case 'filter':\n visitFilter((p as TraqulaFilter).expression, out);\n break;\n case 'group':\n visitPatterns((p as TraqulaPatternGroup).patterns, out);\n break;\n case 'union': {\n const union = p as TraqulaUnion;\n const subRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n for (const branch of union.patterns) {\n const branchRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitPatterns(branch.patterns, branchRules);\n if (branchRules.length === 1) {\n subRules.push(branchRules[0]);\n } else if (branchRules.length > 1) {\n subRules.push({ combinator: 'and', rules: branchRules });\n }\n }\n if (subRules.length > 0) {\n out.push({ combinator: 'or', rules: subRules });\n }\n break;\n }\n default:\n break;\n }\n }\n }\n};\n\n/** Maps a SPARQL comparison operator string to an RQB operator. */\nconst sparqlOpToRqb: Record<string, string> = {\n '=': '=',\n '!=': '!=',\n '<': '<',\n '>': '>',\n '<=': '<=',\n '>=': '>=',\n};\n\n/** Converts a FILTER expression into rules. */\nconst visitFilter = (\n expr: TraqulaExpression,\n out: (DefaultRuleType | DefaultRuleGroupType)[]\n): void => {\n if (expr.type === 'expression' && expr.subType === 'operation') {\n const op = expr.operator ?? '';\n const args = expr.args ?? [];\n\n // Logical operators\n if (op === '&&') {\n for (const arg of args) {\n visitFilter(arg as TraqulaExpression, out);\n }\n return;\n }\n if (op === '||') {\n const subRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n for (const arg of args) {\n const branchRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitFilter(arg as TraqulaExpression, branchRules);\n subRules.push(...branchRules);\n }\n out.push({ combinator: 'or', rules: subRules });\n return;\n }\n\n // Negation\n if (op === '!') {\n if (args.length === 1) {\n const inner = args[0] as TraqulaExpression;\n // !BOUND(x) → null check\n if (\n inner.type === 'expression' &&\n inner.subType === 'operation' &&\n inner.operator === 'bound'\n ) {\n const field = termToString((inner.args?.[0] ?? {}) as TraqulaTerm);\n out.push({ field, operator: 'null', value: null } as DefaultRuleType);\n return;\n }\n const innerRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitFilter(inner, innerRules);\n if (innerRules.length === 1 && !('combinator' in innerRules[0])) {\n out.push(negateRule(innerRules[0]));\n } else {\n out.push({ combinator: 'and', not: true, rules: innerRules });\n }\n return;\n }\n }\n\n // Comparison operators\n if (op in sparqlOpToRqb && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1] as TraqulaExpression);\n out.push({ field, operator: sparqlOpToRqb[op], value } as DefaultRuleType);\n return;\n }\n\n // BOUND(?x) → notNull\n if (op === 'bound' && args.length === 1) {\n const field = termToString(args[0] as TraqulaTerm);\n out.push({ field, operator: 'notNull', value: null } as DefaultRuleType);\n return;\n }\n\n // String functions\n if (op === 'contains' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1] as TraqulaExpression);\n out.push({ field, operator: 'contains', value } as DefaultRuleType);\n return;\n }\n if (op === 'strstarts' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1] as TraqulaExpression);\n out.push({ field, operator: 'beginsWith', value } as DefaultRuleType);\n return;\n }\n if (op === 'strends' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1] as TraqulaExpression);\n out.push({ field, operator: 'endsWith', value } as DefaultRuleType);\n return;\n }\n }\n};\n\n/** Negates a rule by converting its operator. */\nconst negateRule = (rule: DefaultRuleType): DefaultRuleType => {\n const negMap: Record<string, string> = {\n contains: 'doesNotContain',\n beginsWith: 'doesNotBeginWith',\n endsWith: 'doesNotEndWith',\n notNull: 'null',\n null: 'notNull',\n '=': '!=',\n '!=': '=',\n '<': '>=',\n '>': '<=',\n '<=': '>',\n '>=': '<',\n };\n return { ...rule, operator: negMap[rule.operator] ?? rule.operator } as DefaultRuleType;\n};\n\n/**\n * Ensures all prefixed names in a SPARQL query have corresponding PREFIX\n * declarations so the parser accepts them without requiring full URIs.\n */\nconst ensurePrefixes = (sparql: string): string => {\n const declaredPrefixes = new Set<string>();\n const prefixDeclRegex = /PREFIX\\s+(\\w*):/gi;\n let m: RegExpExecArray | null;\n while ((m = prefixDeclRegex.exec(sparql)) !== null) {\n declaredPrefixes.add(m[1].toLowerCase());\n }\n\n const usedPrefixes = new Set<string>();\n const prefixUsageRegex = /\\b(\\w+):\\w+/g;\n while ((m = prefixUsageRegex.exec(sparql)) !== null) {\n const prefix = m[1];\n if (/^https?$/i.test(prefix) || /^urn$/i.test(prefix)) continue;\n const before = sparql.slice(0, m.index);\n const lastOpen = before.lastIndexOf('<');\n const lastClose = before.lastIndexOf('>');\n if (lastOpen > lastClose) continue;\n if (!declaredPrefixes.has(prefix.toLowerCase())) {\n usedPrefixes.add(prefix);\n }\n }\n\n if (usedPrefixes.size === 0) return sparql;\n\n const stubs = [...usedPrefixes].map(p => `PREFIX ${p}: <urn:rqb:prefix:${p}:>`).join('\\n');\n return stubs + '\\n' + sparql;\n};\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Options for {@link parseSPARQL}.\n */\nexport interface ParseSPARQLOptions {\n independentCombinators?: boolean;\n}\n\n/**\n * Parses a SPARQL query string into a {@link DefaultRuleGroupType}.\n *\n * Accepts a full SPARQL query or a `FILTER` expression. Triple patterns are\n * consumed but discarded — only FILTER conditions are returned.\n *\n * @example\n * ```ts\n * // Full query — extracts FILTER conditions only\n * parseSPARQL('SELECT ?x WHERE { ?x foaf:name ?name . FILTER(?age > 30) }');\n *\n * // Bare FILTER expression wrapped in a stub query\n * parseSPARQL('?age > 30 && ?name != \"Alice\"');\n * ```\n */\nexport function parseSPARQL(sparql: string): DefaultRuleGroupType;\nexport function parseSPARQL(\n sparql: string,\n options: Omit<ParseSPARQLOptions, 'independentCombinators'> & {\n independentCombinators?: false;\n }\n): DefaultRuleGroupType;\nexport function parseSPARQL(\n sparql: string,\n options: Omit<ParseSPARQLOptions, 'independentCombinators'> & {\n independentCombinators: true;\n }\n): DefaultRuleGroupTypeIC;\nexport function parseSPARQL(\n sparql: string,\n _options?: ParseSPARQLOptions\n): DefaultRuleGroupTypeAny {\n const trimmed = sparql.trim();\n if (!trimmed) return { combinator: 'and', rules: [] };\n\n // Auto-detect input shape\n let input = trimmed;\n if (/^\\s*(select|prefix|construct|describe|ask)\\b/i.test(input)) {\n // Full SPARQL query — parse as-is\n } else {\n // Bare expression — wrap in a stub query with FILTER\n input = `SELECT * WHERE { FILTER(${input}) }`;\n }\n\n const prepared = ensurePrefixes(input);\n\n let ast: unknown;\n try {\n ast = getParser().parse(prepared);\n } catch {\n return { combinator: 'and', rules: [] };\n }\n\n const typed = ast as TraqulaQuery;\n if (!typed || typed.type !== 'query' || !typed.where) {\n return { combinator: 'and', rules: [] };\n }\n\n const rules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitPatterns(typed.where.patterns ?? [], rules);\n return { combinator: 'and', rules };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"parseSPARQL.js","names":["SparqlParser"],"sources":["../src/utils/parseSPARQL/parseSPARQL.ts"],"sourcesContent":["import { Parser as SparqlParser } from '@traqula/parser-sparql-1-2';\nimport type {\n DefaultRuleGroupType,\n DefaultRuleGroupTypeAny,\n DefaultRuleGroupTypeIC,\n DefaultRuleType,\n} from '../../types';\n\n// Reuse a single parser instance (Chevrotain-backed; creating parsers is expensive)\nlet parserInstance: SparqlParser | undefined;\nconst getParser = (): SparqlParser => {\n if (!parserInstance) {\n parserInstance = new SparqlParser();\n }\n return parserInstance;\n};\n\n// ─── Traqula AST Type Subset ─────────────────────────────────────────────────\n\ninterface TraqulaQuery {\n type: 'query';\n subType: string;\n where?: TraqulaPatternGroup;\n [key: string]: unknown;\n}\n\ninterface TraqulaPatternGroup {\n type: 'pattern';\n subType: 'group';\n patterns: TraqulaPattern[];\n}\n\ntype TraqulaPattern =\n | TraqulaBgp\n | TraqulaOptional\n | TraqulaFilter\n | TraqulaPatternGroup\n | TraqulaUnion\n | { type: 'pattern'; subType: string; [key: string]: unknown }\n | TraqulaQuery;\n\ninterface TraqulaBgp {\n type: 'pattern';\n subType: 'bgp';\n triples: TraqulaTriple[];\n}\n\ninterface TraqulaOptional {\n type: 'pattern';\n subType: 'optional';\n patterns: TraqulaPattern[];\n}\n\ninterface TraqulaFilter {\n type: 'pattern';\n subType: 'filter';\n expression: TraqulaExpression;\n}\n\ninterface TraqulaUnion {\n type: 'pattern';\n subType: 'union';\n patterns: TraqulaPatternGroup[];\n}\n\ninterface TraqulaTriple {\n type: 'triple';\n subject: TraqulaTerm;\n predicate: TraqulaTerm;\n object: TraqulaTerm;\n}\n\ninterface TraqulaTerm {\n type: 'term' | 'path' | 'wildcard';\n subType?: string;\n value?: string;\n prefix?: string;\n langOrIri?: unknown;\n [key: string]: unknown;\n}\n\ninterface TraqulaExpression {\n type: 'expression' | 'term';\n subType: string;\n operator?: string;\n args?: (TraqulaExpression | TraqulaTerm)[];\n value?: string;\n prefix?: string;\n langOrIri?: unknown;\n [key: string]: unknown;\n}\n\n// ─── AST Walker ──────────────────────────────────────────────────────────────\n\n/** Serializes a Traqula term into a user-facing string. */\nconst termToString = (term: TraqulaTerm): string => {\n if (term.type === 'term') {\n switch (term.subType) {\n case 'variable':\n return `?${term.value}`;\n case 'namedNode':\n if (term.prefix !== undefined && term.prefix !== '') {\n return `${term.prefix}:${term.value}`;\n }\n return term.value ?? '';\n case 'literal':\n return term.value ?? '';\n case 'blankNode':\n return `_:${(term as { label?: string }).label ?? ''}`;\n default:\n return term.value ?? '';\n }\n }\n return '';\n};\n\n/** Extracts a literal JS value from a Traqula term. */\nconst termToLiteralValue = (term: TraqulaTerm | TraqulaExpression): unknown => {\n if (term.type === 'term' && term.subType === 'literal') {\n const raw = term.value ?? '';\n if (term.langOrIri && typeof term.langOrIri === 'object') {\n const iri = term.langOrIri as TraqulaTerm;\n const datatype = iri.value ?? '';\n if (\n datatype.endsWith('#integer') ||\n datatype.endsWith('#decimal') ||\n datatype.endsWith('#double') ||\n datatype.endsWith('#float')\n ) {\n return Number(raw);\n }\n if (datatype.endsWith('#boolean')) {\n return raw === 'true';\n }\n }\n const num = Number(raw);\n if (raw !== '' && !Number.isNaN(num)) return num;\n return raw;\n }\n if (term.type === 'term' && term.subType === 'variable') {\n return `?${term.value}`;\n }\n if (term.type === 'term' && term.subType === 'namedNode') {\n return termToString(term as TraqulaTerm);\n }\n return term.value ?? '';\n};\n\n/** Walks patterns, extracting only FILTER expressions (skipping BGP triples). */\nconst visitPatterns = (\n patterns: TraqulaPattern[],\n out: (DefaultRuleType | DefaultRuleGroupType)[]\n): void => {\n for (const p of patterns) {\n if (p.type === 'pattern') {\n switch (p.subType) {\n case 'bgp':\n // Skip triple patterns — Phase 1 only extracts filter conditions\n break;\n case 'optional':\n visitPatterns((p as TraqulaOptional).patterns, out);\n break;\n case 'filter':\n visitFilter((p as TraqulaFilter).expression, out);\n break;\n case 'group':\n visitPatterns((p as TraqulaPatternGroup).patterns, out);\n break;\n case 'union': {\n const union = p as TraqulaUnion;\n const subRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n for (const branch of union.patterns) {\n const branchRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitPatterns(branch.patterns, branchRules);\n if (branchRules.length === 1) {\n subRules.push(branchRules[0]);\n } else if (branchRules.length > 1) {\n subRules.push({ combinator: 'and', rules: branchRules });\n }\n }\n if (subRules.length > 0) {\n out.push({ combinator: 'or', rules: subRules });\n }\n break;\n }\n default:\n break;\n }\n }\n }\n};\n\n/** Maps a SPARQL comparison operator string to an RQB operator. */\nconst sparqlOpToRqb: Record<string, string> = {\n '=': '=',\n '!=': '!=',\n '<': '<',\n '>': '>',\n '<=': '<=',\n '>=': '>=',\n};\n\n/** Converts a FILTER expression into rules. */\nconst visitFilter = (\n expr: TraqulaExpression,\n out: (DefaultRuleType | DefaultRuleGroupType)[]\n): void => {\n if (expr.type === 'expression' && expr.subType === 'operation') {\n const op = expr.operator ?? '';\n const args = expr.args ?? [];\n\n // Logical operators\n if (op === '&&') {\n for (const arg of args) {\n visitFilter(arg as TraqulaExpression, out);\n }\n return;\n }\n if (op === '||') {\n const subRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n for (const arg of args) {\n const branchRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitFilter(arg as TraqulaExpression, branchRules);\n subRules.push(...branchRules);\n }\n out.push({ combinator: 'or', rules: subRules });\n return;\n }\n\n // Negation\n if (op === '!') {\n if (args.length === 1) {\n const inner = args[0] as TraqulaExpression;\n // !BOUND(x) → null check\n if (\n inner.type === 'expression' &&\n inner.subType === 'operation' &&\n inner.operator === 'bound'\n ) {\n const field = termToString((inner.args?.[0] ?? {}) as TraqulaTerm);\n out.push({ field, operator: 'null', value: null } as DefaultRuleType);\n return;\n }\n const innerRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitFilter(inner, innerRules);\n if (innerRules.length === 1 && !('combinator' in innerRules[0])) {\n out.push(negateRule(innerRules[0]));\n } else {\n out.push({ combinator: 'and', not: true, rules: innerRules });\n }\n return;\n }\n }\n\n // Comparison operators\n if (op in sparqlOpToRqb && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1]);\n out.push({ field, operator: sparqlOpToRqb[op], value } as DefaultRuleType);\n return;\n }\n\n // BOUND(?x) → notNull\n if (op === 'bound' && args.length === 1) {\n const field = termToString(args[0] as TraqulaTerm);\n out.push({ field, operator: 'notNull', value: null } as DefaultRuleType);\n return;\n }\n\n // String functions\n if (op === 'contains' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1]);\n out.push({ field, operator: 'contains', value } as DefaultRuleType);\n return;\n }\n if (op === 'strstarts' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1]);\n out.push({ field, operator: 'beginsWith', value } as DefaultRuleType);\n return;\n }\n if (op === 'strends' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1]);\n out.push({ field, operator: 'endsWith', value } as DefaultRuleType);\n return;\n }\n }\n};\n\n/** Negates a rule by converting its operator. */\nconst negateRule = (rule: DefaultRuleType): DefaultRuleType => {\n const negMap: Record<string, string> = {\n contains: 'doesNotContain',\n beginsWith: 'doesNotBeginWith',\n endsWith: 'doesNotEndWith',\n notNull: 'null',\n null: 'notNull',\n '=': '!=',\n '!=': '=',\n '<': '>=',\n '>': '<=',\n '<=': '>',\n '>=': '<',\n };\n return { ...rule, operator: negMap[rule.operator] ?? rule.operator } as DefaultRuleType;\n};\n\n/**\n * Ensures all prefixed names in a SPARQL query have corresponding PREFIX\n * declarations so the parser accepts them without requiring full URIs.\n */\nconst ensurePrefixes = (sparql: string): string => {\n const declaredPrefixes = new Set<string>();\n const prefixDeclRegex = /PREFIX\\s+(\\w*):/gi;\n let m: RegExpExecArray | null;\n while ((m = prefixDeclRegex.exec(sparql)) !== null) {\n declaredPrefixes.add(m[1].toLowerCase());\n }\n\n const usedPrefixes = new Set<string>();\n const prefixUsageRegex = /\\b(\\w+):\\w+/g;\n while ((m = prefixUsageRegex.exec(sparql)) !== null) {\n const prefix = m[1];\n if (/^https?$/i.test(prefix) || /^urn$/i.test(prefix)) continue;\n const before = sparql.slice(0, m.index);\n const lastOpen = before.lastIndexOf('<');\n const lastClose = before.lastIndexOf('>');\n if (lastOpen > lastClose) continue;\n if (!declaredPrefixes.has(prefix.toLowerCase())) {\n usedPrefixes.add(prefix);\n }\n }\n\n if (usedPrefixes.size === 0) return sparql;\n\n const stubs = [...usedPrefixes].map(p => `PREFIX ${p}: <urn:rqb:prefix:${p}:>`).join('\\n');\n return stubs + '\\n' + sparql;\n};\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Options for {@link parseSPARQL}.\n */\nexport interface ParseSPARQLOptions {\n independentCombinators?: boolean;\n}\n\n/**\n * Parses a SPARQL query string into a {@link DefaultRuleGroupType}.\n *\n * Accepts a full SPARQL query or a `FILTER` expression. Triple patterns are\n * consumed but discarded — only FILTER conditions are returned.\n *\n * @example\n * ```ts\n * // Full query — extracts FILTER conditions only\n * parseSPARQL('SELECT ?x WHERE { ?x foaf:name ?name . FILTER(?age > 30) }');\n *\n * // Bare FILTER expression wrapped in a stub query\n * parseSPARQL('?age > 30 && ?name != \"Alice\"');\n * ```\n */\nexport function parseSPARQL(sparql: string): DefaultRuleGroupType;\nexport function parseSPARQL(\n sparql: string,\n options: Omit<ParseSPARQLOptions, 'independentCombinators'> & {\n independentCombinators?: false;\n }\n): DefaultRuleGroupType;\nexport function parseSPARQL(\n sparql: string,\n options: Omit<ParseSPARQLOptions, 'independentCombinators'> & {\n independentCombinators: true;\n }\n): DefaultRuleGroupTypeIC;\nexport function parseSPARQL(\n sparql: string,\n _options?: ParseSPARQLOptions\n): DefaultRuleGroupTypeAny {\n const trimmed = sparql.trim();\n if (!trimmed) return { combinator: 'and', rules: [] };\n\n // Auto-detect input shape\n let input = trimmed;\n if (/^\\s*(select|prefix|construct|describe|ask)\\b/i.test(input)) {\n // Full SPARQL query — parse as-is\n } else {\n // Bare expression — wrap in a stub query with FILTER\n input = `SELECT * WHERE { FILTER(${input}) }`;\n }\n\n const prepared = ensurePrefixes(input);\n\n let ast: unknown;\n try {\n ast = getParser().parse(prepared);\n } catch {\n return { combinator: 'and', rules: [] };\n }\n\n const typed = ast as TraqulaQuery;\n if (!typed || typed.type !== 'query' || !typed.where) {\n return { combinator: 'and', rules: [] };\n }\n\n const rules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitPatterns(typed.where.patterns ?? [], rules);\n return { combinator: 'and', rules };\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"parseSPARQL.mjs","names":["SparqlParser"],"sources":["../src/utils/parseSPARQL/parseSPARQL.ts"],"sourcesContent":["import { Parser as SparqlParser } from '@traqula/parser-sparql-1-2';\nimport type {\n DefaultRuleGroupType,\n DefaultRuleGroupTypeAny,\n DefaultRuleGroupTypeIC,\n DefaultRuleType,\n} from '../../types';\n\n// Reuse a single parser instance (Chevrotain-backed; creating parsers is expensive)\nlet parserInstance: SparqlParser | undefined;\nconst getParser = (): SparqlParser => {\n if (!parserInstance) {\n parserInstance = new SparqlParser();\n }\n return parserInstance;\n};\n\n// ─── Traqula AST Type Subset ─────────────────────────────────────────────────\n\ninterface TraqulaQuery {\n type: 'query';\n subType: string;\n where?: TraqulaPatternGroup;\n [key: string]: unknown;\n}\n\ninterface TraqulaPatternGroup {\n type: 'pattern';\n subType: 'group';\n patterns: TraqulaPattern[];\n}\n\ntype TraqulaPattern =\n | TraqulaBgp\n | TraqulaOptional\n | TraqulaFilter\n | TraqulaPatternGroup\n | TraqulaUnion\n | { type: 'pattern'; subType: string; [key: string]: unknown }\n | TraqulaQuery;\n\ninterface TraqulaBgp {\n type: 'pattern';\n subType: 'bgp';\n triples: TraqulaTriple[];\n}\n\ninterface TraqulaOptional {\n type: 'pattern';\n subType: 'optional';\n patterns: TraqulaPattern[];\n}\n\ninterface TraqulaFilter {\n type: 'pattern';\n subType: 'filter';\n expression: TraqulaExpression;\n}\n\ninterface TraqulaUnion {\n type: 'pattern';\n subType: 'union';\n patterns: TraqulaPatternGroup[];\n}\n\ninterface TraqulaTriple {\n type: 'triple';\n subject: TraqulaTerm;\n predicate: TraqulaTerm;\n object: TraqulaTerm;\n}\n\ninterface TraqulaTerm {\n type: 'term' | 'path' | 'wildcard';\n subType?: string;\n value?: string;\n prefix?: string;\n langOrIri?: unknown;\n [key: string]: unknown;\n}\n\ninterface TraqulaExpression {\n type: 'expression' | 'term';\n subType: string;\n operator?: string;\n args?: (TraqulaExpression | TraqulaTerm)[];\n value?: string;\n prefix?: string;\n langOrIri?: unknown;\n [key: string]: unknown;\n}\n\n// ─── AST Walker ──────────────────────────────────────────────────────────────\n\n/** Serializes a Traqula term into a user-facing string. */\nconst termToString = (term: TraqulaTerm): string => {\n if (term.type === 'term') {\n switch (term.subType) {\n case 'variable':\n return `?${term.value}`;\n case 'namedNode':\n if (term.prefix !== undefined && term.prefix !== '') {\n return `${term.prefix}:${term.value}`;\n }\n return term.value ?? '';\n case 'literal':\n return term.value ?? '';\n case 'blankNode':\n return `_:${(term as { label?: string }).label ?? ''}`;\n default:\n return term.value ?? '';\n }\n }\n return '';\n};\n\n/** Extracts a literal JS value from a Traqula term. */\nconst termToLiteralValue = (term: TraqulaTerm | TraqulaExpression): unknown => {\n if (term.type === 'term' && term.subType === 'literal') {\n const raw = term.value ?? '';\n if (term.langOrIri && typeof term.langOrIri === 'object') {\n const iri = term.langOrIri as TraqulaTerm;\n const datatype = iri.value ?? '';\n if (\n datatype.endsWith('#integer') ||\n datatype.endsWith('#decimal') ||\n datatype.endsWith('#double') ||\n datatype.endsWith('#float')\n ) {\n return Number(raw);\n }\n if (datatype.endsWith('#boolean')) {\n return raw === 'true';\n }\n }\n const num = Number(raw);\n if (raw !== '' && !Number.isNaN(num)) return num;\n return raw;\n }\n if (term.type === 'term' && term.subType === 'variable') {\n return `?${term.value}`;\n }\n if (term.type === 'term' && term.subType === 'namedNode') {\n return termToString(term as TraqulaTerm);\n }\n return term.value ?? '';\n};\n\n/** Walks patterns, extracting only FILTER expressions (skipping BGP triples). */\nconst visitPatterns = (\n patterns: TraqulaPattern[],\n out: (DefaultRuleType | DefaultRuleGroupType)[]\n): void => {\n for (const p of patterns) {\n if (p.type === 'pattern') {\n switch (p.subType) {\n case 'bgp':\n // Skip triple patterns — Phase 1 only extracts filter conditions\n break;\n case 'optional':\n visitPatterns((p as TraqulaOptional).patterns, out);\n break;\n case 'filter':\n visitFilter((p as TraqulaFilter).expression, out);\n break;\n case 'group':\n visitPatterns((p as TraqulaPatternGroup).patterns, out);\n break;\n case 'union': {\n const union = p as TraqulaUnion;\n const subRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n for (const branch of union.patterns) {\n const branchRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitPatterns(branch.patterns, branchRules);\n if (branchRules.length === 1) {\n subRules.push(branchRules[0]);\n } else if (branchRules.length > 1) {\n subRules.push({ combinator: 'and', rules: branchRules });\n }\n }\n if (subRules.length > 0) {\n out.push({ combinator: 'or', rules: subRules });\n }\n break;\n }\n default:\n break;\n }\n }\n }\n};\n\n/** Maps a SPARQL comparison operator string to an RQB operator. */\nconst sparqlOpToRqb: Record<string, string> = {\n '=': '=',\n '!=': '!=',\n '<': '<',\n '>': '>',\n '<=': '<=',\n '>=': '>=',\n};\n\n/** Converts a FILTER expression into rules. */\nconst visitFilter = (\n expr: TraqulaExpression,\n out: (DefaultRuleType | DefaultRuleGroupType)[]\n): void => {\n if (expr.type === 'expression' && expr.subType === 'operation') {\n const op = expr.operator ?? '';\n const args = expr.args ?? [];\n\n // Logical operators\n if (op === '&&') {\n for (const arg of args) {\n visitFilter(arg as TraqulaExpression, out);\n }\n return;\n }\n if (op === '||') {\n const subRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n for (const arg of args) {\n const branchRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitFilter(arg as TraqulaExpression, branchRules);\n subRules.push(...branchRules);\n }\n out.push({ combinator: 'or', rules: subRules });\n return;\n }\n\n // Negation\n if (op === '!') {\n if (args.length === 1) {\n const inner = args[0] as TraqulaExpression;\n // !BOUND(x) → null check\n if (\n inner.type === 'expression' &&\n inner.subType === 'operation' &&\n inner.operator === 'bound'\n ) {\n const field = termToString((inner.args?.[0] ?? {}) as TraqulaTerm);\n out.push({ field, operator: 'null', value: null } as DefaultRuleType);\n return;\n }\n const innerRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitFilter(inner, innerRules);\n if (innerRules.length === 1 && !('combinator' in innerRules[0])) {\n out.push(negateRule(innerRules[0]));\n } else {\n out.push({ combinator: 'and', not: true, rules: innerRules });\n }\n return;\n }\n }\n\n // Comparison operators\n if (op in sparqlOpToRqb && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1] as TraqulaExpression);\n out.push({ field, operator: sparqlOpToRqb[op], value } as DefaultRuleType);\n return;\n }\n\n // BOUND(?x) → notNull\n if (op === 'bound' && args.length === 1) {\n const field = termToString(args[0] as TraqulaTerm);\n out.push({ field, operator: 'notNull', value: null } as DefaultRuleType);\n return;\n }\n\n // String functions\n if (op === 'contains' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1] as TraqulaExpression);\n out.push({ field, operator: 'contains', value } as DefaultRuleType);\n return;\n }\n if (op === 'strstarts' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1] as TraqulaExpression);\n out.push({ field, operator: 'beginsWith', value } as DefaultRuleType);\n return;\n }\n if (op === 'strends' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1] as TraqulaExpression);\n out.push({ field, operator: 'endsWith', value } as DefaultRuleType);\n return;\n }\n }\n};\n\n/** Negates a rule by converting its operator. */\nconst negateRule = (rule: DefaultRuleType): DefaultRuleType => {\n const negMap: Record<string, string> = {\n contains: 'doesNotContain',\n beginsWith: 'doesNotBeginWith',\n endsWith: 'doesNotEndWith',\n notNull: 'null',\n null: 'notNull',\n '=': '!=',\n '!=': '=',\n '<': '>=',\n '>': '<=',\n '<=': '>',\n '>=': '<',\n };\n return { ...rule, operator: negMap[rule.operator] ?? rule.operator } as DefaultRuleType;\n};\n\n/**\n * Ensures all prefixed names in a SPARQL query have corresponding PREFIX\n * declarations so the parser accepts them without requiring full URIs.\n */\nconst ensurePrefixes = (sparql: string): string => {\n const declaredPrefixes = new Set<string>();\n const prefixDeclRegex = /PREFIX\\s+(\\w*):/gi;\n let m: RegExpExecArray | null;\n while ((m = prefixDeclRegex.exec(sparql)) !== null) {\n declaredPrefixes.add(m[1].toLowerCase());\n }\n\n const usedPrefixes = new Set<string>();\n const prefixUsageRegex = /\\b(\\w+):\\w+/g;\n while ((m = prefixUsageRegex.exec(sparql)) !== null) {\n const prefix = m[1];\n if (/^https?$/i.test(prefix) || /^urn$/i.test(prefix)) continue;\n const before = sparql.slice(0, m.index);\n const lastOpen = before.lastIndexOf('<');\n const lastClose = before.lastIndexOf('>');\n if (lastOpen > lastClose) continue;\n if (!declaredPrefixes.has(prefix.toLowerCase())) {\n usedPrefixes.add(prefix);\n }\n }\n\n if (usedPrefixes.size === 0) return sparql;\n\n const stubs = [...usedPrefixes].map(p => `PREFIX ${p}: <urn:rqb:prefix:${p}:>`).join('\\n');\n return stubs + '\\n' + sparql;\n};\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Options for {@link parseSPARQL}.\n */\nexport interface ParseSPARQLOptions {\n independentCombinators?: boolean;\n}\n\n/**\n * Parses a SPARQL query string into a {@link DefaultRuleGroupType}.\n *\n * Accepts a full SPARQL query or a `FILTER` expression. Triple patterns are\n * consumed but discarded — only FILTER conditions are returned.\n *\n * @example\n * ```ts\n * // Full query — extracts FILTER conditions only\n * parseSPARQL('SELECT ?x WHERE { ?x foaf:name ?name . FILTER(?age > 30) }');\n *\n * // Bare FILTER expression wrapped in a stub query\n * parseSPARQL('?age > 30 && ?name != \"Alice\"');\n * ```\n */\nexport function parseSPARQL(sparql: string): DefaultRuleGroupType;\nexport function parseSPARQL(\n sparql: string,\n options: Omit<ParseSPARQLOptions, 'independentCombinators'> & {\n independentCombinators?: false;\n }\n): DefaultRuleGroupType;\nexport function parseSPARQL(\n sparql: string,\n options: Omit<ParseSPARQLOptions, 'independentCombinators'> & {\n independentCombinators: true;\n }\n): DefaultRuleGroupTypeIC;\nexport function parseSPARQL(\n sparql: string,\n _options?: ParseSPARQLOptions\n): DefaultRuleGroupTypeAny {\n const trimmed = sparql.trim();\n if (!trimmed) return { combinator: 'and', rules: [] };\n\n // Auto-detect input shape\n let input = trimmed;\n if (/^\\s*(select|prefix|construct|describe|ask)\\b/i.test(input)) {\n // Full SPARQL query — parse as-is\n } else {\n // Bare expression — wrap in a stub query with FILTER\n input = `SELECT * WHERE { FILTER(${input}) }`;\n }\n\n const prepared = ensurePrefixes(input);\n\n let ast: unknown;\n try {\n ast = getParser().parse(prepared);\n } catch {\n return { combinator: 'and', rules: [] };\n }\n\n const typed = ast as TraqulaQuery;\n if (!typed || typed.type !== 'query' || !typed.where) {\n return { combinator: 'and', rules: [] };\n }\n\n const rules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitPatterns(typed.where.patterns ?? [], rules);\n return { combinator: 'and', rules };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"parseSPARQL.mjs","names":["SparqlParser"],"sources":["../src/utils/parseSPARQL/parseSPARQL.ts"],"sourcesContent":["import { Parser as SparqlParser } from '@traqula/parser-sparql-1-2';\nimport type {\n DefaultRuleGroupType,\n DefaultRuleGroupTypeAny,\n DefaultRuleGroupTypeIC,\n DefaultRuleType,\n} from '../../types';\n\n// Reuse a single parser instance (Chevrotain-backed; creating parsers is expensive)\nlet parserInstance: SparqlParser | undefined;\nconst getParser = (): SparqlParser => {\n if (!parserInstance) {\n parserInstance = new SparqlParser();\n }\n return parserInstance;\n};\n\n// ─── Traqula AST Type Subset ─────────────────────────────────────────────────\n\ninterface TraqulaQuery {\n type: 'query';\n subType: string;\n where?: TraqulaPatternGroup;\n [key: string]: unknown;\n}\n\ninterface TraqulaPatternGroup {\n type: 'pattern';\n subType: 'group';\n patterns: TraqulaPattern[];\n}\n\ntype TraqulaPattern =\n | TraqulaBgp\n | TraqulaOptional\n | TraqulaFilter\n | TraqulaPatternGroup\n | TraqulaUnion\n | { type: 'pattern'; subType: string; [key: string]: unknown }\n | TraqulaQuery;\n\ninterface TraqulaBgp {\n type: 'pattern';\n subType: 'bgp';\n triples: TraqulaTriple[];\n}\n\ninterface TraqulaOptional {\n type: 'pattern';\n subType: 'optional';\n patterns: TraqulaPattern[];\n}\n\ninterface TraqulaFilter {\n type: 'pattern';\n subType: 'filter';\n expression: TraqulaExpression;\n}\n\ninterface TraqulaUnion {\n type: 'pattern';\n subType: 'union';\n patterns: TraqulaPatternGroup[];\n}\n\ninterface TraqulaTriple {\n type: 'triple';\n subject: TraqulaTerm;\n predicate: TraqulaTerm;\n object: TraqulaTerm;\n}\n\ninterface TraqulaTerm {\n type: 'term' | 'path' | 'wildcard';\n subType?: string;\n value?: string;\n prefix?: string;\n langOrIri?: unknown;\n [key: string]: unknown;\n}\n\ninterface TraqulaExpression {\n type: 'expression' | 'term';\n subType: string;\n operator?: string;\n args?: (TraqulaExpression | TraqulaTerm)[];\n value?: string;\n prefix?: string;\n langOrIri?: unknown;\n [key: string]: unknown;\n}\n\n// ─── AST Walker ──────────────────────────────────────────────────────────────\n\n/** Serializes a Traqula term into a user-facing string. */\nconst termToString = (term: TraqulaTerm): string => {\n if (term.type === 'term') {\n switch (term.subType) {\n case 'variable':\n return `?${term.value}`;\n case 'namedNode':\n if (term.prefix !== undefined && term.prefix !== '') {\n return `${term.prefix}:${term.value}`;\n }\n return term.value ?? '';\n case 'literal':\n return term.value ?? '';\n case 'blankNode':\n return `_:${(term as { label?: string }).label ?? ''}`;\n default:\n return term.value ?? '';\n }\n }\n return '';\n};\n\n/** Extracts a literal JS value from a Traqula term. */\nconst termToLiteralValue = (term: TraqulaTerm | TraqulaExpression): unknown => {\n if (term.type === 'term' && term.subType === 'literal') {\n const raw = term.value ?? '';\n if (term.langOrIri && typeof term.langOrIri === 'object') {\n const iri = term.langOrIri as TraqulaTerm;\n const datatype = iri.value ?? '';\n if (\n datatype.endsWith('#integer') ||\n datatype.endsWith('#decimal') ||\n datatype.endsWith('#double') ||\n datatype.endsWith('#float')\n ) {\n return Number(raw);\n }\n if (datatype.endsWith('#boolean')) {\n return raw === 'true';\n }\n }\n const num = Number(raw);\n if (raw !== '' && !Number.isNaN(num)) return num;\n return raw;\n }\n if (term.type === 'term' && term.subType === 'variable') {\n return `?${term.value}`;\n }\n if (term.type === 'term' && term.subType === 'namedNode') {\n return termToString(term as TraqulaTerm);\n }\n return term.value ?? '';\n};\n\n/** Walks patterns, extracting only FILTER expressions (skipping BGP triples). */\nconst visitPatterns = (\n patterns: TraqulaPattern[],\n out: (DefaultRuleType | DefaultRuleGroupType)[]\n): void => {\n for (const p of patterns) {\n if (p.type === 'pattern') {\n switch (p.subType) {\n case 'bgp':\n // Skip triple patterns — Phase 1 only extracts filter conditions\n break;\n case 'optional':\n visitPatterns((p as TraqulaOptional).patterns, out);\n break;\n case 'filter':\n visitFilter((p as TraqulaFilter).expression, out);\n break;\n case 'group':\n visitPatterns((p as TraqulaPatternGroup).patterns, out);\n break;\n case 'union': {\n const union = p as TraqulaUnion;\n const subRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n for (const branch of union.patterns) {\n const branchRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitPatterns(branch.patterns, branchRules);\n if (branchRules.length === 1) {\n subRules.push(branchRules[0]);\n } else if (branchRules.length > 1) {\n subRules.push({ combinator: 'and', rules: branchRules });\n }\n }\n if (subRules.length > 0) {\n out.push({ combinator: 'or', rules: subRules });\n }\n break;\n }\n default:\n break;\n }\n }\n }\n};\n\n/** Maps a SPARQL comparison operator string to an RQB operator. */\nconst sparqlOpToRqb: Record<string, string> = {\n '=': '=',\n '!=': '!=',\n '<': '<',\n '>': '>',\n '<=': '<=',\n '>=': '>=',\n};\n\n/** Converts a FILTER expression into rules. */\nconst visitFilter = (\n expr: TraqulaExpression,\n out: (DefaultRuleType | DefaultRuleGroupType)[]\n): void => {\n if (expr.type === 'expression' && expr.subType === 'operation') {\n const op = expr.operator ?? '';\n const args = expr.args ?? [];\n\n // Logical operators\n if (op === '&&') {\n for (const arg of args) {\n visitFilter(arg as TraqulaExpression, out);\n }\n return;\n }\n if (op === '||') {\n const subRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n for (const arg of args) {\n const branchRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitFilter(arg as TraqulaExpression, branchRules);\n subRules.push(...branchRules);\n }\n out.push({ combinator: 'or', rules: subRules });\n return;\n }\n\n // Negation\n if (op === '!') {\n if (args.length === 1) {\n const inner = args[0] as TraqulaExpression;\n // !BOUND(x) → null check\n if (\n inner.type === 'expression' &&\n inner.subType === 'operation' &&\n inner.operator === 'bound'\n ) {\n const field = termToString((inner.args?.[0] ?? {}) as TraqulaTerm);\n out.push({ field, operator: 'null', value: null } as DefaultRuleType);\n return;\n }\n const innerRules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitFilter(inner, innerRules);\n if (innerRules.length === 1 && !('combinator' in innerRules[0])) {\n out.push(negateRule(innerRules[0]));\n } else {\n out.push({ combinator: 'and', not: true, rules: innerRules });\n }\n return;\n }\n }\n\n // Comparison operators\n if (op in sparqlOpToRqb && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1]);\n out.push({ field, operator: sparqlOpToRqb[op], value } as DefaultRuleType);\n return;\n }\n\n // BOUND(?x) → notNull\n if (op === 'bound' && args.length === 1) {\n const field = termToString(args[0] as TraqulaTerm);\n out.push({ field, operator: 'notNull', value: null } as DefaultRuleType);\n return;\n }\n\n // String functions\n if (op === 'contains' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1]);\n out.push({ field, operator: 'contains', value } as DefaultRuleType);\n return;\n }\n if (op === 'strstarts' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1]);\n out.push({ field, operator: 'beginsWith', value } as DefaultRuleType);\n return;\n }\n if (op === 'strends' && args.length === 2) {\n const field = termToString(args[0] as TraqulaTerm);\n const value = termToLiteralValue(args[1]);\n out.push({ field, operator: 'endsWith', value } as DefaultRuleType);\n return;\n }\n }\n};\n\n/** Negates a rule by converting its operator. */\nconst negateRule = (rule: DefaultRuleType): DefaultRuleType => {\n const negMap: Record<string, string> = {\n contains: 'doesNotContain',\n beginsWith: 'doesNotBeginWith',\n endsWith: 'doesNotEndWith',\n notNull: 'null',\n null: 'notNull',\n '=': '!=',\n '!=': '=',\n '<': '>=',\n '>': '<=',\n '<=': '>',\n '>=': '<',\n };\n return { ...rule, operator: negMap[rule.operator] ?? rule.operator } as DefaultRuleType;\n};\n\n/**\n * Ensures all prefixed names in a SPARQL query have corresponding PREFIX\n * declarations so the parser accepts them without requiring full URIs.\n */\nconst ensurePrefixes = (sparql: string): string => {\n const declaredPrefixes = new Set<string>();\n const prefixDeclRegex = /PREFIX\\s+(\\w*):/gi;\n let m: RegExpExecArray | null;\n while ((m = prefixDeclRegex.exec(sparql)) !== null) {\n declaredPrefixes.add(m[1].toLowerCase());\n }\n\n const usedPrefixes = new Set<string>();\n const prefixUsageRegex = /\\b(\\w+):\\w+/g;\n while ((m = prefixUsageRegex.exec(sparql)) !== null) {\n const prefix = m[1];\n if (/^https?$/i.test(prefix) || /^urn$/i.test(prefix)) continue;\n const before = sparql.slice(0, m.index);\n const lastOpen = before.lastIndexOf('<');\n const lastClose = before.lastIndexOf('>');\n if (lastOpen > lastClose) continue;\n if (!declaredPrefixes.has(prefix.toLowerCase())) {\n usedPrefixes.add(prefix);\n }\n }\n\n if (usedPrefixes.size === 0) return sparql;\n\n const stubs = [...usedPrefixes].map(p => `PREFIX ${p}: <urn:rqb:prefix:${p}:>`).join('\\n');\n return stubs + '\\n' + sparql;\n};\n\n// ─── Public API ──────────────────────────────────────────────────────────────\n\n/**\n * Options for {@link parseSPARQL}.\n */\nexport interface ParseSPARQLOptions {\n independentCombinators?: boolean;\n}\n\n/**\n * Parses a SPARQL query string into a {@link DefaultRuleGroupType}.\n *\n * Accepts a full SPARQL query or a `FILTER` expression. Triple patterns are\n * consumed but discarded — only FILTER conditions are returned.\n *\n * @example\n * ```ts\n * // Full query — extracts FILTER conditions only\n * parseSPARQL('SELECT ?x WHERE { ?x foaf:name ?name . FILTER(?age > 30) }');\n *\n * // Bare FILTER expression wrapped in a stub query\n * parseSPARQL('?age > 30 && ?name != \"Alice\"');\n * ```\n */\nexport function parseSPARQL(sparql: string): DefaultRuleGroupType;\nexport function parseSPARQL(\n sparql: string,\n options: Omit<ParseSPARQLOptions, 'independentCombinators'> & {\n independentCombinators?: false;\n }\n): DefaultRuleGroupType;\nexport function parseSPARQL(\n sparql: string,\n options: Omit<ParseSPARQLOptions, 'independentCombinators'> & {\n independentCombinators: true;\n }\n): DefaultRuleGroupTypeIC;\nexport function parseSPARQL(\n sparql: string,\n _options?: ParseSPARQLOptions\n): DefaultRuleGroupTypeAny {\n const trimmed = sparql.trim();\n if (!trimmed) return { combinator: 'and', rules: [] };\n\n // Auto-detect input shape\n let input = trimmed;\n if (/^\\s*(select|prefix|construct|describe|ask)\\b/i.test(input)) {\n // Full SPARQL query — parse as-is\n } else {\n // Bare expression — wrap in a stub query with FILTER\n input = `SELECT * WHERE { FILTER(${input}) }`;\n }\n\n const prepared = ensurePrefixes(input);\n\n let ast: unknown;\n try {\n ast = getParser().parse(prepared);\n } catch {\n return { combinator: 'and', rules: [] };\n }\n\n const typed = ast as TraqulaQuery;\n if (!typed || typed.type !== 'query' || !typed.where) {\n return { combinator: 'and', rules: [] };\n }\n\n const rules: (DefaultRuleType | DefaultRuleGroupType)[] = [];\n visitPatterns(typed.where.patterns ?? [], rules);\n return { combinator: 'and', rules };\n}\n"],"mappings":"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"}