@sisense/sdk-data 1.28.0 → 1.29.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/dist/cjs/dimensional-model/attributes.d.ts +2 -2
  2. package/dist/cjs/dimensional-model/attributes.js +7 -7
  3. package/dist/cjs/dimensional-model/base.d.ts +7 -1
  4. package/dist/cjs/dimensional-model/base.js +2 -1
  5. package/dist/cjs/dimensional-model/filters/filter-config-utils.d.ts +4 -0
  6. package/dist/cjs/dimensional-model/filters/filter-config-utils.js +5 -2
  7. package/dist/cjs/dimensional-model/filters/filter-relations.d.ts +187 -0
  8. package/dist/cjs/dimensional-model/filters/filter-relations.js +532 -0
  9. package/dist/cjs/dimensional-model/filters/helpers.d.ts +112 -0
  10. package/dist/cjs/dimensional-model/filters/helpers.js +178 -0
  11. package/dist/cjs/dimensional-model/filters/index.d.ts +2 -0
  12. package/dist/cjs/dimensional-model/filters/index.js +18 -0
  13. package/dist/cjs/dimensional-model/filters/utils/attribute-measure-util.d.ts +1 -35
  14. package/dist/cjs/dimensional-model/filters/utils/attribute-measure-util.js +37 -101
  15. package/dist/cjs/dimensional-model/interfaces.d.ts +2 -0
  16. package/dist/cjs/dimensional-model/measures/factory.js +1 -32
  17. package/dist/cjs/dimensional-model/measures/measures.d.ts +3 -3
  18. package/dist/cjs/dimensional-model/measures/measures.js +10 -9
  19. package/dist/cjs/index.d.ts +1 -1
  20. package/dist/cjs/index.js +1 -1
  21. package/dist/cjs/interfaces.d.ts +2 -2
  22. package/dist/cjs/utils.d.ts +74 -2
  23. package/dist/cjs/utils.js +138 -3
  24. package/dist/dimensional-model/attributes.d.ts +2 -2
  25. package/dist/dimensional-model/attributes.js +7 -7
  26. package/dist/dimensional-model/base.d.ts +7 -1
  27. package/dist/dimensional-model/base.js +2 -1
  28. package/dist/dimensional-model/filters/filter-config-utils.d.ts +4 -0
  29. package/dist/dimensional-model/filters/filter-config-utils.js +5 -2
  30. package/dist/dimensional-model/filters/filter-relations.d.ts +187 -0
  31. package/dist/dimensional-model/filters/filter-relations.js +507 -0
  32. package/dist/dimensional-model/filters/helpers.d.ts +112 -0
  33. package/dist/dimensional-model/filters/helpers.js +169 -0
  34. package/dist/dimensional-model/filters/index.d.ts +2 -0
  35. package/dist/dimensional-model/filters/index.js +2 -0
  36. package/dist/dimensional-model/filters/utils/attribute-measure-util.d.ts +1 -35
  37. package/dist/dimensional-model/filters/utils/attribute-measure-util.js +36 -74
  38. package/dist/dimensional-model/interfaces.d.ts +2 -0
  39. package/dist/dimensional-model/measures/factory.js +2 -30
  40. package/dist/dimensional-model/measures/measures.d.ts +3 -3
  41. package/dist/dimensional-model/measures/measures.js +10 -9
  42. package/dist/index.d.ts +1 -1
  43. package/dist/index.js +1 -1
  44. package/dist/interfaces.d.ts +2 -2
  45. package/dist/tsconfig.prod.cjs.tsbuildinfo +1 -1
  46. package/dist/utils.d.ts +74 -2
  47. package/dist/utils.js +133 -2
  48. package/package.json +4 -3
  49. package/dist/cjs/dimensional-model/filter-relations.d.ts +0 -9
  50. package/dist/cjs/dimensional-model/filter-relations.js +0 -18
  51. package/dist/dimensional-model/filter-relations.d.ts +0 -9
  52. package/dist/dimensional-model/filter-relations.js +0 -14
@@ -0,0 +1,507 @@
1
+ /* eslint-disable @typescript-eslint/default-param-last */
2
+ import { DimensionalLevelAttribute, isCascadingFilter, } from '../../index.js';
3
+ import { cloneDeep, isArray } from 'lodash-es';
4
+ import { TranslatableError } from '../../translation/translatable-error.js';
5
+ /**
6
+ * Type guard for checking if the provided filters are FilterRelations.
7
+ *
8
+ * @param filters - The filters to check.
9
+ * @returns `true` if the filters are FilterRelations, `false` otherwise.
10
+ * @group Filter Utilities
11
+ */
12
+ export function isFilterRelations(filters) {
13
+ return (!!filters &&
14
+ 'operator' in filters &&
15
+ (filters.operator === 'AND' || filters.operator === 'OR') &&
16
+ !!filters.right &&
17
+ !!filters.left);
18
+ }
19
+ /**
20
+ * Merges source filters with target filters and recalculates relations.
21
+ *
22
+ * @param sourceFilters - The source filters or filter relations to merge.
23
+ * @param targetFilters - The target filters or filter relations to merge with.
24
+ * @returns Updated source filters merged with target filters. If the source filters are FilterRelations, the relations are recalculated.
25
+ * @internal
26
+ */
27
+ export function mergeFiltersOrFilterRelations(sourceFilters = [], targetFilters = []) {
28
+ if (!isFilterRelations(sourceFilters) && !isFilterRelations(targetFilters)) {
29
+ return mergeFilters(sourceFilters, targetFilters);
30
+ }
31
+ const { filters: pureSourceFilters, relations: sourceRelations } = splitFiltersAndRelations(sourceFilters);
32
+ const pureTargetFilters = getFiltersArray(targetFilters);
33
+ const mergedFilters = mergeFilters(pureSourceFilters, pureTargetFilters);
34
+ const mergedRelations = calculateNewRelations(pureSourceFilters, sourceRelations, mergedFilters);
35
+ return combineFiltersAndRelations(mergedFilters, mergedRelations);
36
+ }
37
+ /**
38
+ * Splits filters or filter relations into filters and relations rules.
39
+ * @internal
40
+ */
41
+ export function splitFiltersAndRelations(filtersOrFilterRelations) {
42
+ if (!filtersOrFilterRelations) {
43
+ return { filters: [], relations: null };
44
+ }
45
+ if (isArray(filtersOrFilterRelations)) {
46
+ return { filters: filtersOrFilterRelations, relations: null };
47
+ }
48
+ const filtersSet = new Set();
49
+ function traverse(node) {
50
+ if (isFilterNode(node)) {
51
+ filtersSet.add(node);
52
+ return { instanceid: node.config.guid };
53
+ }
54
+ if (isFilterRelations(node)) {
55
+ const left = traverse(node.left);
56
+ const right = traverse(node.right);
57
+ return { left, right, operator: node.operator };
58
+ }
59
+ throw new UnknownRelationsNodeError();
60
+ }
61
+ const relations = traverse(filtersOrFilterRelations);
62
+ return {
63
+ filters: Array.from(filtersSet),
64
+ relations,
65
+ };
66
+ }
67
+ /**
68
+ * Returns pure filters array from the given filters or filter relations.
69
+ * @internal
70
+ */
71
+ export function getFiltersArray(filtersOrFilterRelations) {
72
+ if (!filtersOrFilterRelations) {
73
+ return [];
74
+ }
75
+ return splitFiltersAndRelations(filtersOrFilterRelations).filters;
76
+ }
77
+ /**
78
+ * Combines filters and relations into a single FilterRelations object.
79
+ * If the relations are empty or relations are trivial (single node), the filters are returned as is.
80
+ * @internal
81
+ */
82
+ export function combineFiltersAndRelations(filters, relations) {
83
+ if (!relations || isTrivialSingleNodeRelations(relations)) {
84
+ return filters;
85
+ }
86
+ const resultRelations = traverse(relations);
87
+ return isFilterNode(resultRelations) ? [resultRelations] : resultRelations;
88
+ function traverse(node) {
89
+ if (isRelationsRuleIdNode(node)) {
90
+ return filters.find((filter) => filter.config.guid === node.instanceid);
91
+ }
92
+ if (isRelationsRule(node)) {
93
+ return {
94
+ left: traverse(node.left),
95
+ right: traverse(node.right),
96
+ operator: node.operator,
97
+ };
98
+ }
99
+ throw new UnknownRelationsNodeError();
100
+ }
101
+ }
102
+ /** Type guard for checking if a node is a single relations node (trivial case when relations are needless).
103
+ * @internal
104
+ */
105
+ export function isTrivialSingleNodeRelations(relations) {
106
+ return !!relations && 'instanceid' in relations;
107
+ }
108
+ /**
109
+ * Calculates new relations based on the changes in filters.
110
+ * @internal
111
+ */
112
+ export function calculateNewRelations(prevFilters, prevRelations, newFilters) {
113
+ // If there are no previous relations - no need to recalculate them
114
+ if (prevRelations === null) {
115
+ return null;
116
+ }
117
+ const performedActions = diffFilters(prevFilters, newFilters);
118
+ if (performedActions.length === 0) {
119
+ return prevRelations;
120
+ }
121
+ return performedActions.reduce((relations, action) => {
122
+ switch (action.type) {
123
+ case 'add':
124
+ return addFilterToRelations(action.payload, relations);
125
+ case 'remove':
126
+ return removeFilterFromRelations(action.payload, relations);
127
+ }
128
+ }, prevRelations);
129
+ }
130
+ /**
131
+ * Compares two filters and determines if they are equal in terms of relations.
132
+ */
133
+ function areFiltersEqualForRelations(filter1, filter2) {
134
+ return filter1.config.guid === filter2.config.guid;
135
+ }
136
+ /**
137
+ * Replaces a filter in the relations tree with a new filter.
138
+ * @internal
139
+ */
140
+ export function getRelationsWithReplacedFilter(relations, filterToReplace, newFilter) {
141
+ if (!relations) {
142
+ return null;
143
+ }
144
+ const replacedRelations = traverse(relations);
145
+ return replacedRelations;
146
+ function traverse(node) {
147
+ if (isRelationsRuleIdNode(node)) {
148
+ return node.instanceid === filterToReplace.config.guid
149
+ ? { instanceid: newFilter.config.guid }
150
+ : node;
151
+ }
152
+ if (isRelationsRule(node)) {
153
+ return {
154
+ left: traverse(node.left),
155
+ right: traverse(node.right),
156
+ operator: node.operator,
157
+ };
158
+ }
159
+ throw new UnknownRelationsNodeError();
160
+ }
161
+ }
162
+ /**
163
+ * Compares two arrays of Filter objects and determines the actions needed
164
+ * to transform prevFilters into newFilters.
165
+ *
166
+ * @param prevFilters - The original array of filters.
167
+ * @param newFilters - The updated array of filters.
168
+ * @param isEqualFilters - A function to determine if two filters are equal.
169
+ * @returns An array of FilterAction objects representing the changes.
170
+ */
171
+ function diffFilters(prevFilters, newFilters) {
172
+ const actions = [];
173
+ // Clone the arrays to avoid mutating the original data
174
+ const prevFiltersCopy = [...prevFilters];
175
+ const newFiltersCopy = [...newFilters];
176
+ // Determine removals
177
+ prevFiltersCopy.forEach((prevFilter) => {
178
+ const existsInNew = newFiltersCopy.some((newFilter) => areFiltersEqualForRelations(prevFilter, newFilter));
179
+ if (!existsInNew) {
180
+ actions.push({ type: 'remove', payload: prevFilter });
181
+ }
182
+ });
183
+ // Determine additions
184
+ newFiltersCopy.forEach((newFilter) => {
185
+ const existsInPrev = prevFiltersCopy.some((prevFilter) => areFiltersEqualForRelations(newFilter, prevFilter));
186
+ if (!existsInPrev) {
187
+ actions.push({ type: 'add', payload: newFilter });
188
+ }
189
+ });
190
+ return actions;
191
+ }
192
+ /**
193
+ * Adds a filter to root of relations tree as a new node connected with AND operator.
194
+ * If the relations tree is empty, the filter is added as the root node.
195
+ */
196
+ function addFilterToRelations(filter, relations) {
197
+ if (!relations) {
198
+ return { instanceid: filter.config.guid };
199
+ }
200
+ return {
201
+ left: relations,
202
+ right: { instanceid: filter.config.guid },
203
+ operator: 'AND',
204
+ };
205
+ }
206
+ /**
207
+ * Removes a filter from the relations tree.
208
+ * If the filter is not found, the relations tree is returned as is.
209
+ */
210
+ function removeFilterFromRelations(filter, relations) {
211
+ if (!relations) {
212
+ return null;
213
+ }
214
+ if (isTrivialSingleNodeRelations(relations)) {
215
+ return relations.instanceid === filter.config.guid ? null : relations;
216
+ }
217
+ const leftAfterRemoval = removeFilterFromRelations(filter, relations.left);
218
+ const rightAfterRemoval = removeFilterFromRelations(filter, relations.right);
219
+ if (leftAfterRemoval === null && !!rightAfterRemoval) {
220
+ return rightAfterRemoval;
221
+ }
222
+ if (rightAfterRemoval === null && !!leftAfterRemoval) {
223
+ return leftAfterRemoval;
224
+ }
225
+ if (leftAfterRemoval === null && rightAfterRemoval === null) {
226
+ return null;
227
+ }
228
+ return {
229
+ left: leftAfterRemoval,
230
+ right: rightAfterRemoval,
231
+ operator: relations.operator,
232
+ };
233
+ }
234
+ /**
235
+ * Converts filter relations model from Fusion to internal CSDK filter relations rules.
236
+ * @internal
237
+ */
238
+ export function convertFilterRelationsModelToRelationRules(filterRelationsModel, filters) {
239
+ if (!filterRelationsModel) {
240
+ return null;
241
+ }
242
+ function traverse(node) {
243
+ if (isModelIdNode(node)) {
244
+ return { instanceid: node.instanceId };
245
+ }
246
+ if (isModelBracketNode(node)) {
247
+ return traverse(node.value);
248
+ }
249
+ if (isModelRelationNode(node)) {
250
+ const newNode = {
251
+ operator: node.operator,
252
+ left: traverse(node.left),
253
+ right: traverse(node.right),
254
+ };
255
+ return newNode;
256
+ }
257
+ if (isModelCascadeNode(node)) {
258
+ // CSDK filter relations model work with cascading filters as with a single node.
259
+ const cascadingFilterForThisCascade = filters.find((filter) => {
260
+ if (!isCascadingFilter(filter)) {
261
+ return false;
262
+ }
263
+ const levelIds = filter.filters.map((f) => f.config.guid);
264
+ return node.levels.every((levelFilter) => levelIds.includes(levelFilter.instanceId));
265
+ });
266
+ if (cascadingFilterForThisCascade) {
267
+ return { instanceid: cascadingFilterForThisCascade.config.guid };
268
+ }
269
+ throw new Error('Broken filter relations model. Cascading filter not found.');
270
+ }
271
+ throw new Error('Broken filter relations model. Unknown node type.');
272
+ }
273
+ return traverse(filterRelationsModel);
274
+ }
275
+ function isModelIdNode(node) {
276
+ return 'instanceId' in node;
277
+ }
278
+ function isModelBracketNode(node) {
279
+ return 'value' in node;
280
+ }
281
+ function isModelRelationNode(node) {
282
+ return 'operator' in node;
283
+ }
284
+ function isModelCascadeNode(node) {
285
+ return 'levels' in node && isArray(node.levels);
286
+ }
287
+ /**
288
+ * @internal
289
+ */
290
+ export function isRelationsRuleIdNode(node) {
291
+ return 'instanceid' in node;
292
+ }
293
+ /**
294
+ * @internal
295
+ */
296
+ export function isRelationsRule(node) {
297
+ return 'operator' in node;
298
+ }
299
+ function isFilterNode(node) {
300
+ return 'config' in node && 'guid' in node.config;
301
+ }
302
+ /**
303
+ * Converts internal CSDK filter relations rules to filter relations model for Fusion.
304
+ * @internal
305
+ */
306
+ export function filterRelationRulesToFilterRelationsModel(filterRelationRules, filters) {
307
+ if (!filterRelationRules) {
308
+ return undefined;
309
+ }
310
+ function traverse(node) {
311
+ if (isRelationsRuleIdNode(node)) {
312
+ // Check if this instanceid corresponds to a cascading filter
313
+ const filter = filters.find((f) => f.config.guid === node.instanceid);
314
+ if (filter && isCascadingFilter(filter)) {
315
+ // Build a CascadingIdentifier node
316
+ const levels = filter.filters.map((levelFilter) => ({
317
+ type: 'Identifier',
318
+ instanceId: levelFilter.config.guid,
319
+ }));
320
+ return {
321
+ type: 'CascadingIdentifier',
322
+ levels,
323
+ };
324
+ }
325
+ else {
326
+ // Build an Identifier node
327
+ return {
328
+ type: 'Identifier',
329
+ instanceId: node.instanceid,
330
+ };
331
+ }
332
+ }
333
+ else if (isRelationsRule(node)) {
334
+ // Build a LogicalExpression node
335
+ return {
336
+ type: 'LogicalExpression',
337
+ operator: node.operator,
338
+ left: traverse(node.left),
339
+ right: traverse(node.right),
340
+ };
341
+ }
342
+ else {
343
+ throw new Error('Unknown node type in filter relations rules.');
344
+ }
345
+ }
346
+ return traverse(filterRelationRules);
347
+ }
348
+ /**
349
+ * @internal
350
+ */
351
+ export function findFilterByGuid(filters, guid) {
352
+ return filters.find((filter) => filter.config.guid === guid);
353
+ }
354
+ /**
355
+ * Error thrown when an unknown node type is encountered in filter relations.
356
+ * @internal
357
+ */
358
+ export class UnknownRelationsNodeError extends Error {
359
+ constructor() {
360
+ super('Broken filter relations. Unknown node type.');
361
+ }
362
+ }
363
+ /**
364
+ * @internal
365
+ */
366
+ export function isOpenBracketDescriptionNode(node) {
367
+ return node.nodeType === 'openBracket';
368
+ }
369
+ /**
370
+ * @internal
371
+ */
372
+ export function isCloseBracketDescriptionNode(node) {
373
+ return node.nodeType === 'closeBracket';
374
+ }
375
+ /**
376
+ * @internal
377
+ */
378
+ export function isAttributeDescriptionNode(node) {
379
+ return node.nodeType === 'attribute';
380
+ }
381
+ /**
382
+ * @internal
383
+ */
384
+ export function isOperatorDescriptionNode(node) {
385
+ return node.nodeType === 'operator';
386
+ }
387
+ /**
388
+ * Gets a unique identifier for a filter, combining its attribute expression and granularity if available.
389
+ *
390
+ * @param {Filter} filter - The filter object to generate the unique identifier for.
391
+ * @returns {string} - The unique identifier for the filter.
392
+ * @internal
393
+ */
394
+ export function getFilterCompareId(filter) {
395
+ if (isCascadingFilter(filter)) {
396
+ return filter.filters.map(getFilterCompareId).join('-');
397
+ }
398
+ // TODO: remove fallback on 'filter.jaql()' after removing temporal 'jaql()' workaround from filter translation layer
399
+ const { attribute: filterAttribute } = filter;
400
+ const filterJaql = filter.jaql().jaql;
401
+ const expression = filterAttribute.expression || filterJaql.dim;
402
+ const granularity = filterAttribute.granularity ||
403
+ ((filterJaql === null || filterJaql === void 0 ? void 0 : filterJaql.datatype) === 'datetime'
404
+ ? DimensionalLevelAttribute.translateJaqlToGranularity(filterJaql)
405
+ : '');
406
+ return `${expression}${granularity}`;
407
+ }
408
+ /**
409
+ * Merges two arrays of filter objects, prioritizing 'targetFilters' over 'sourceFilters',
410
+ * and removes duplicates based on filter compare id.
411
+ *
412
+ * Saves the 'sourceFilters' filters order, while adds new filters to the end of the array.
413
+ *
414
+ * @param {Filter[]} [sourceFilters=[]] - The source array of filter objects.
415
+ * @param {Filter[]} [targetFilters=[]] - The target array of filter objects.
416
+ * @returns {Filter[]} - The merged array of filter objects.
417
+ * @internal
418
+ */
419
+ export function mergeFilters(sourceFilters = [], targetFilters = []) {
420
+ const filters = [...sourceFilters];
421
+ targetFilters.forEach((filter) => {
422
+ const existingFilterIndex = filters.findIndex((existingFilter) => getFilterCompareId(filter) === getFilterCompareId(existingFilter));
423
+ const isFilterAlreadyExist = existingFilterIndex !== -1;
424
+ if (isFilterAlreadyExist) {
425
+ filters[existingFilterIndex] = filter;
426
+ }
427
+ else {
428
+ filters.push(filter);
429
+ }
430
+ });
431
+ return filters;
432
+ }
433
+ /**
434
+ * Replaces nodes of filter reations tree with fetched filters by instance id.
435
+ *
436
+ * @param filters - The filters.
437
+ * @param highlights - The highlights
438
+ * @param filterRelations - Fetched filter relations.
439
+ * @returns Filter relations with filters in nodes.
440
+ * @internal
441
+ */
442
+ /* eslint-disable-next-line sonarjs/cognitive-complexity */
443
+ export function getFilterRelationsFromJaql(filters, highlights, filterRelations) {
444
+ if (!filterRelations) {
445
+ return filters;
446
+ }
447
+ // If highlights are present, nodes in filter relations reference both filters and highlights
448
+ // and thus cannot be replaced with filters. Return filters in this case.
449
+ if (highlights.length) {
450
+ return filters;
451
+ }
452
+ const mergedFilterRelations = cloneDeep(filterRelations);
453
+ function traverse(node) {
454
+ if ('instanceid' in node) {
455
+ const filter = filters.find((filter) => filter.config.guid === node.instanceid);
456
+ if (!filter) {
457
+ throw new TranslatableError('errors.unknownFilterInFilterRelations');
458
+ }
459
+ return filter;
460
+ }
461
+ if ('operator' in node) {
462
+ const newNode = { operator: node.operator };
463
+ if ('left' in node) {
464
+ newNode.left = traverse(node.left);
465
+ }
466
+ if ('right' in node) {
467
+ newNode.right = traverse(node.right);
468
+ }
469
+ return newNode;
470
+ }
471
+ return node;
472
+ }
473
+ return traverse(mergedFilterRelations);
474
+ }
475
+ /**
476
+ * Converts filter relations model to filter relations jaql.
477
+ *
478
+ * @param filterRelations - Filter relations model.
479
+ * @returns Filter relations jaql.
480
+ * @internal
481
+ */
482
+ export function convertFilterRelationsModelToJaql(filterRelations) {
483
+ if (!filterRelations) {
484
+ return filterRelations;
485
+ }
486
+ const convertedFilterRelations = cloneDeep(filterRelations);
487
+ function traverse(node) {
488
+ if ('instanceId' in node) {
489
+ return { instanceid: node.instanceId };
490
+ }
491
+ if ('value' in node) {
492
+ return traverse(node.value);
493
+ }
494
+ if ('operator' in node) {
495
+ const newNode = { operator: node.operator };
496
+ if ('left' in node) {
497
+ newNode.left = traverse(node.left);
498
+ }
499
+ if ('right' in node) {
500
+ newNode.right = traverse(node.right);
501
+ }
502
+ return newNode;
503
+ }
504
+ return node;
505
+ }
506
+ return traverse(convertedFilterRelations);
507
+ }
@@ -0,0 +1,112 @@
1
+ import { Filter, FilterRelations } from '../../index.js';
2
+ /**
3
+ * Returns a function that adds a filter to existing filters or filter relations.
4
+ *
5
+ * @param filter - The filter to add.
6
+ * @returns A function that takes existing filters or filter relations and returns updated filters or filter relations with the new filter added.
7
+ * @group Filter Utilities
8
+ * @example
9
+ * ```ts
10
+ * // Using with an array of filters
11
+ * const originalFilters = [filterByAgeRange];
12
+ * const updatedFilters = withAddedFilter(filterByCost)(originalFilters);
13
+ * // [filterByAgeRange, filterByCost]
14
+ *
15
+ * // Using with filter relations
16
+ * const originalFilterRelations = filterFactory.logic.or(filterByAgeRange, filterByRevenue);
17
+ * const updatedFilterRelations = withAddedFilter(filterByCost)(originalFilterRelations);
18
+ * // (filterByAgeRange OR filterByRevenue) AND filterByCost
19
+ * ```
20
+ */
21
+ export declare function withAddedFilter(filter: Filter): (filters: Filter[] | FilterRelations | undefined) => Filter[] | FilterRelations;
22
+ /**
23
+ * Returns a function that adds multiple filters to existing filters or filter relations.
24
+ *
25
+ * @param filtersToAdd - An array of filters to add.
26
+ * @returns A function that takes existing filters or filter relations and returns updated filters or filter relations with the new filters added.
27
+ * @group Filter Utilities
28
+ * @example
29
+ * ```ts
30
+ * // Using with an array of filters
31
+ * const originalFilters = [filterByAgeRange];
32
+ * const updatedFilters = withAddedFilters([filterByCost, filterByRevenue])(originalFilters);
33
+ * // [filterByAgeRange, filterByCost, filterByRevenue]
34
+ *
35
+ * // Using with filter relations
36
+ * const originalFilterRelations = filterFactory.logic.or(filterByAgeRange, filterByRevenue);
37
+ * const updatedFilterRelations = withAddedFilters([filterByCost, filterByRevenue])(originalFilterRelations);
38
+ * // (filterByAgeRange OR filterByRevenue) AND filterByCost AND filterByRevenue
39
+ * ```
40
+ */
41
+ export declare function withAddedFilters(filtersToAdd: Filter[]): (filters: Filter[] | FilterRelations | undefined) => Filter[] | FilterRelations;
42
+ /**
43
+ * Returns a function that removes a filter from existing filters or filter relations.
44
+ *
45
+ * @param filterToRemove - The filter to remove.
46
+ * @returns A function that takes existing filters or filter relations and returns updated filters or filter relations without the specified filter.
47
+ * @group Filter Utilities
48
+ * @example
49
+ * ```ts
50
+ * // Using with an array of filters
51
+ * const originalFilters = [filterByAgeRange, filterByRevenue, filterByCost];
52
+ * const updatedFilters = withoutFilter(filterByCost)(originalFilters);
53
+ * // [filterByAgeRange, filterByRevenue]
54
+ *
55
+ * // Using with filter relations
56
+ * const originalFilterRelations = filterFactory.logic.or(filterByAgeRange, filterByRevenue);
57
+ * const updatedFiltersRelations = withoutFilter(filterByRevenue)(originalFilterRelations);
58
+ * // filterByAgeRange
59
+ * ```
60
+ */
61
+ export declare function withoutFilter(filterToRemove: Filter): (filters: Filter[] | FilterRelations | undefined) => Filter[] | FilterRelations;
62
+ /**
63
+ * Returns a function that removes multiple filters from existing filters or filter relations.
64
+ *
65
+ * @param filtersToRemove - An array of filters to remove.
66
+ * @returns A function that takes existing filters or filter relations and returns updated filters or filter relations without the specified filters.
67
+ * @group Filter Utilities
68
+ * @example
69
+ * ```ts
70
+ * // Using with an array of filters
71
+ * const originalFilters = [filterByAgeRange, filterByRevenue, filterByCost];
72
+ * const updatedFilters = withRemovedFilters([filterByRevenue, filterByCost])(originalFilters);
73
+ * // [filterByAgeRange]
74
+ *
75
+ * // Using with filter relations
76
+ * const originalFilterRelations = filterFactory.logic.or(filterByAgeRange, filterByRevenue);
77
+ * const updatedFiltersRelations = withRemovedFilters([filterByRevenue])(originalFilterRelations);
78
+ * // filterByAgeRange
79
+ * ```
80
+ */
81
+ export declare function withoutFilters(filtersToRemove: Filter[]): (filters: Filter[] | FilterRelations | undefined) => Filter[] | FilterRelations;
82
+ /**
83
+ * Returns a function that replaces a filter with a new filter in existing filters or filter relations.
84
+ *
85
+ * @param filterToReplace - The filter to replace.
86
+ * @param newFilter - The new filter to use as a replacement.
87
+ * @returns A function that takes existing filters or filter relations and returns updated filters or filter relations with the filter replaced.
88
+ * @group Filter Utilities
89
+ * @example
90
+ * ```ts
91
+ * // Using with an array of filters
92
+ * const originalFilters = [filterByAgeRange, filterByRevenue];
93
+ * const updatedFilters = withReplacedFilter(filterByRevenue, filterByCost)(originalFilters);
94
+ * // [filterByAgeRange, filterByCost]
95
+ *
96
+ * // Using with filter relations
97
+ * const originalFilterRelations = filterFactory.logic.or(filterByAgeRange, filterByRevenue);
98
+ * const updatedFilterRelations = withReplacedFilter(filterByRevenue, filterByCost)(originalFilterRelations);
99
+ * // (filterByAgeRange OR filterByCost)
100
+ * ```
101
+ */
102
+ export declare function withReplacedFilter(filterToReplace: Filter, newFilter: Filter): (filters: Filter[] | FilterRelations | undefined) => Filter[] | FilterRelations;
103
+ /**
104
+ * Finds a filter in an array of filters or filter relations.
105
+ * Returns the first filter that satisfies the provided search function.
106
+ * @group Filter Utilities
107
+ * @param filters - An array of filters or filter relations to search.
108
+ * @param searchFn - A function that takes a filter and returns a boolean indicating whether the filter satisfies the search criteria.
109
+ * @returns The first filter that satisfies the search function, or `undefined` if no filter is found.
110
+ *
111
+ */
112
+ export declare function findFilter(filters: Filter[] | FilterRelations | undefined, searchFn: (filter: Filter) => boolean): Filter | undefined;