Skip to content

Commit 72008ed

Browse files
committed
Updated formatQuery documentation for v4.5.0
1 parent d3782a2 commit 72008ed

File tree

1 file changed

+48
-15
lines changed

1 file changed

+48
-15
lines changed

docs/api/export.mdx

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ Use the `formatQuery` function to export queries in various formats. The functio
1313
function formatQuery(
1414
query: RuleGroupTypeAny,
1515
options?: ExportFormat | FormatQueryOptions
16-
): string | ParameterizedSQL | ParameterizedNamedSQL;
16+
): string | ParameterizedSQL | ParameterizedNamedSQL | RQBJsonLogic;
1717
```
1818

19-
`formatQuery` parses a given query into one of the following formats:
19+
`formatQuery` converts a given query into one of the following formats:
2020

2121
- JSON (with or without `id`s)
2222
- SQL `WHERE` clause
@@ -88,7 +88,7 @@ The output will be a multi-line string representation of the query using 2 space
8888

8989
### JSON without identifiers
9090

91-
To export the internal query representation without formatting (single-line, no indentation) and without the `id` attribute on each object, use the "json_without_ids" format. This is useful if you need to serialize the query for storage.
91+
To export the internal query representation without formatting (single-line, no indentation) and without the `id` or `path` attributes on each object, use the "json_without_ids" format. This is useful if you need to serialize the query for storage.
9292

9393
```ts
9494
formatQuery(query, 'json_without_ids');
@@ -255,7 +255,7 @@ formatQuery(query, { format: 'sql', parseNumbers: true });
255255

256256
:::info
257257

258-
To avoid information loss, this option is more strict about what qualifies as "numeric" than [the standard `parseFloat` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat). Put simply, `parseFloat` works with any string that _starts_ with a numeric sequence, ignoring the rest of the string beginning with the first non-numeric character. When `parseNumbers` is `true`, `formatQuery` will only convert a `value` to a `number` if it appears to be numeric _in its entirety_ (after trimming whitespace).
258+
To avoid information loss, this option is more strict about what qualifies as "numeric" than [the standard `parseFloat` function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat). To oversimplify a bit, `parseFloat` works with any string that _starts_ with a numeric sequence, ignoring the rest of the string beginning with the first non-numeric character. In contrast, when `parseNumbers` is `true`, `formatQuery` will only convert a `value` to a `number` if it appears to be numeric _in its entirety_ (after trimming whitespace).
259259

260260
The following expressions all evaluate to `true`:
261261

@@ -277,7 +277,7 @@ formatQuery(
277277

278278
### Value processor
279279

280-
If you need to control the way the value portion of the output is processed, you can specify a custom `valueProcessor` (only applicable for "sql" format).
280+
If you need to control the way the value portion of the output is processed, you can specify a custom `valueProcessor` (only applicable for certain formats).
281281

282282
```ts
283283
const query: RuleGroupType = {
@@ -297,24 +297,57 @@ const query: RuleGroupType = {
297297
],
298298
};
299299

300-
const valueProcessor = (field, operator, value) => {
300+
const customValueProcessor = (field, operator, value) => {
301301
if (operator === 'in') {
302302
// Assuming `value` is an array, such as from a multi-select
303-
return `(${value.map(v => `"${v.trim()}"`).join(',')})`;
303+
return `(${value.map(v => `"${v.trim()}"`).join(', ')})`;
304304
}
305+
// Fall back to the default value processor for other operators
305306
return defaultValueProcessor(field, operator, value);
306307
};
307308

308-
formatQuery(query, { format: 'sql', valueProcessor });
309-
// Returns: "(instrument in ('Guitar','Vocals') and lastName = 'Vai')"
309+
formatQuery(query, { format: 'sql', valueProcessor: customValueProcessor });
310+
// Returns: "(instrument in ('Guitar', 'Vocals') and lastName = 'Vai')"
310311
```
311312

312313
:::caution
313314

314-
When using the "mongodb" export format, `valueProcessor` functions must produce the entire MongoDB rule object and not just the value portion like with other formats.
315+
When using the "mongodb", "cel", or "spel" export formats, `valueProcessor` functions must produce the entire MongoDB rule object or CEL/SpEL rule string, not just the expression on the right-hand side of the operator like with SQL-based formats.
315316

316317
:::
317318

319+
#### Enhanced `valueProcessor` behavior
320+
321+
`formatQuery` will invoke custom `valueProcessor` functions with different arguments based on the function's `length` property, which is the number of arguments a function accepts excluding those with default values.
322+
323+
If the `valueProcessor` function accepts fewer than three (3) arguments, it will be called like this:
324+
325+
```ts
326+
valueProcessor(rule, { parseNumbers });
327+
```
328+
329+
The first argument is the `RuleType` object directly from the query. The second argument is of type `ValueProcessorOptions`, which is equivalent to `Pick<FormatQueryOptions, "parseNumbers">`).
330+
331+
Invoking `valueProcessor` with the full `RuleType` object provides access to much more information about each rule. Standard properties that were previously unavailable include `path`, `id`, and `disabled`, but any custom properties will also be accessible.
332+
333+
The default value processors have not changed from the legacy function signature, but alternate functions using the new `fn(rule, options)` signature are now available:
334+
335+
- `defaultValueProcessorByRule` (for SQL-based formats)
336+
- `defaultValueProcessorCELByRule`
337+
- `defaultValueProcessorMongoDBByRule`
338+
- `defaultValueProcessorSpELByRule`
339+
340+
To maintain the legacy signature (`valueProcessor(field, operator, value, valueSource)`), make sure your custom `valueProcessor` function accepts at least three arguments _with no default values_ (i.e. do not use `=` for the first three arguments). For example, the following code will log `length: 1` and the function would be called with the `(rule, options)` arguments:
341+
342+
```ts
343+
const valueProcessor = (field: string, operator = '=', value = '') => '...';
344+
console.log(`length: ${valueProcessor.length}`);
345+
```
346+
347+
Removing `= ...` from the `operator` and `value` argument declarations would increase the function's `length` to 3.
348+
349+
If you use TypeScript, these conditions will be enforced automatically.
350+
318351
### Quote field names
319352

320353
Some database engines wrap field names in backticks (`` ` ``). This can be configured with the `quoteFieldNamesWith` option.
@@ -352,7 +385,7 @@ The `fallbackExpression` is a string that will be part of the output when `forma
352385

353386
### Value sources
354387

355-
When the `valueSource` property for a rule is set to "field", `formatQuery` will place the bare, unquoted value (which should be a valid field name) in the result for the "sql", "parameterized", "parameterized_named", "mongodb", and "cel" formats. No parameters will be generated for such rules.
388+
When the `valueSource` property for a rule is set to "field", `formatQuery` will place the bare, unquoted value (which should be a valid field name) in the result for the "sql", "parameterized", "parameterized_named", "mongodb", "cel", and "spel" formats. No parameters will be generated for such rules.
356389

357390
```ts
358391
const pf = formatQuery(
@@ -382,7 +415,7 @@ Any rule where the `field` or `operator` matches the placeholder value (default
382415

383416
## Validation
384417

385-
The validation options (`validator` and `fields` – see [Validation](./validation) for more information) only affect the output when `format` is "sql", "parameterized", "parameterized_named", "mongodb", or "cel". If the `validator` function returns `false`, the `fallbackExpression` will be returned. Otherwise, groups and rules marked as invalid (either by the validation map produced by the `validator` function or the result of the field-based `validator` function) will be ignored.
418+
The validation options (`validator` and `fields` – see [Validation](./validation) for more information) only affect the output when `format` is not "json" or "json_without_ids". If the `validator` function returns `false`, the `fallbackExpression` will be returned. Otherwise, groups and rules marked as invalid (either by the validation map produced by the `validator` function or the result of the field-based `validator` function) will be ignored.
386419

387420
Example:
388421

@@ -431,8 +464,8 @@ formatQuery(query, {
431464

432465
### Automatic validation
433466

434-
A basic form of validation will be used by `formatQuery` for the "in", "notIn", "between", and "notBetween" operators when the output format is "sql", "parameterized", "parameterized_named", "mongodb", or "cel". This validation is used regardless of the presence of any `validator` options either at the query or field level:
467+
A basic form of validation will be used by `formatQuery` for the "in", "notIn", "between", and "notBetween" operators when the output format is not "json" or "json_without_ids". This validation is used regardless of the presence of any `validator` options at either the query level or field level:
435468

436469
- Rules that specify an "in" or "notIn" `operator` will be deemed invalid if the rule's `value` is neither an array with at least one element (i.e. `value.length > 0`) nor a non-empty string.
437-
- Rules that specify a "between" or "notBetween" `operator` will be deemed invalid if the rule's `value` is neither an array of length two (`value.length === 2`) nor a string with exactly one comma that isn't the first or last character (i.e. `value.split(',').length === 2` and neither element is an empty string).
438-
- Rules where the following expression is true will be deemed invalid: `field === placeholderFieldName || operator === placeholderOperatorName`.
470+
- Rules that specify a "between" or "notBetween" `operator` will be deemed invalid if the rule's `value` is neither an array with length of at least two (`value.length >= 2`) nor a string with at least one comma that isn't the first or last character (i.e. `value.split(',').length >= 2`, and neither element is an empty string).
471+
- Rules where either the `field` or `operator` match their respective placeholder will be deemed invalid (`field === placeholderFieldName || operator === placeholderOperatorName`).

0 commit comments

Comments
 (0)