Merge pull request #14922 from Budibase/chore/search-filter-typing
Search filter typing
This commit is contained in:
commit
86aabcc629
|
@ -8,7 +8,7 @@ import {
|
||||||
import * as actions from "../automations/actions"
|
import * as actions from "../automations/actions"
|
||||||
import * as automationUtils from "../automations/automationUtils"
|
import * as automationUtils from "../automations/automationUtils"
|
||||||
import { replaceFakeBindings } from "../automations/loopUtils"
|
import { replaceFakeBindings } from "../automations/loopUtils"
|
||||||
import { dataFilters, helpers } from "@budibase/shared-core"
|
import { dataFilters, helpers, utils } from "@budibase/shared-core"
|
||||||
import { default as AutomationEmitter } from "../events/AutomationEmitter"
|
import { default as AutomationEmitter } from "../events/AutomationEmitter"
|
||||||
import { generateAutomationMetadataID, isProdAppID } from "../db/utils"
|
import { generateAutomationMetadataID, isProdAppID } from "../db/utils"
|
||||||
import { definitions as triggerDefs } from "../automations/triggerInfo"
|
import { definitions as triggerDefs } from "../automations/triggerInfo"
|
||||||
|
@ -23,10 +23,12 @@ import {
|
||||||
AutomationStatus,
|
AutomationStatus,
|
||||||
AutomationStep,
|
AutomationStep,
|
||||||
AutomationStepStatus,
|
AutomationStepStatus,
|
||||||
|
BranchSearchFilters,
|
||||||
BranchStep,
|
BranchStep,
|
||||||
|
isLogicalSearchOperator,
|
||||||
LoopStep,
|
LoopStep,
|
||||||
SearchFilters,
|
|
||||||
UserBindings,
|
UserBindings,
|
||||||
|
isBasicSearchOperator,
|
||||||
} from "@budibase/types"
|
} from "@budibase/types"
|
||||||
import { AutomationContext, TriggerOutput } from "../definitions/automations"
|
import { AutomationContext, TriggerOutput } from "../definitions/automations"
|
||||||
import { WorkerCallback } from "./definitions"
|
import { WorkerCallback } from "./definitions"
|
||||||
|
@ -547,34 +549,51 @@ class Orchestrator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private async evaluateBranchCondition(
|
private async evaluateBranchCondition(
|
||||||
conditions: SearchFilters
|
conditions: BranchSearchFilters
|
||||||
): Promise<boolean> {
|
): Promise<boolean> {
|
||||||
const toFilter: Record<string, any> = {}
|
const toFilter: Record<string, any> = {}
|
||||||
|
|
||||||
const processedConditions = dataFilters.recurseSearchFilters(
|
const recurseSearchFilters = (
|
||||||
conditions,
|
filters: BranchSearchFilters
|
||||||
filter => {
|
): BranchSearchFilters => {
|
||||||
Object.entries(filter).forEach(([_, value]) => {
|
for (const filterKey of Object.keys(
|
||||||
Object.entries(value).forEach(([field, val]) => {
|
filters
|
||||||
|
) as (keyof typeof filters)[]) {
|
||||||
|
if (!filters[filterKey]) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isLogicalSearchOperator(filterKey)) {
|
||||||
|
filters[filterKey].conditions = filters[filterKey].conditions.map(
|
||||||
|
condition => recurseSearchFilters(condition)
|
||||||
|
)
|
||||||
|
} else if (isBasicSearchOperator(filterKey)) {
|
||||||
|
for (const [field, value] of Object.entries(filters[filterKey])) {
|
||||||
const fromContext = processStringSync(
|
const fromContext = processStringSync(
|
||||||
field,
|
field,
|
||||||
this.processContext(this.context)
|
this.processContext(this.context)
|
||||||
)
|
)
|
||||||
toFilter[field] = fromContext
|
toFilter[field] = fromContext
|
||||||
|
|
||||||
if (typeof val === "string" && findHBSBlocks(val).length > 0) {
|
if (typeof value === "string" && findHBSBlocks(value).length > 0) {
|
||||||
const processedVal = processStringSync(
|
const processedVal = processStringSync(
|
||||||
val,
|
value,
|
||||||
this.processContext(this.context)
|
this.processContext(this.context)
|
||||||
)
|
)
|
||||||
|
|
||||||
value[field] = processedVal
|
filters[filterKey][field] = processedVal
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
})
|
} else {
|
||||||
return filter
|
// We want to types to complain if we extend BranchSearchFilters, but not to throw if the request comes with some extra data. It will just be ignored
|
||||||
|
utils.unreachable(filterKey, { doNotThrow: true })
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
|
||||||
|
return filters
|
||||||
|
}
|
||||||
|
|
||||||
|
const processedConditions = recurseSearchFilters(conditions)
|
||||||
|
|
||||||
const result = dataFilters.runQuery([toFilter], processedConditions)
|
const result = dataFilters.runQuery([toFilter], processedConditions)
|
||||||
return result.length > 0
|
return result.length > 0
|
||||||
|
|
|
@ -142,25 +142,6 @@ export function recurseLogicalOperators(
|
||||||
return filters
|
return filters
|
||||||
}
|
}
|
||||||
|
|
||||||
export function recurseSearchFilters(
|
|
||||||
filters: SearchFilters,
|
|
||||||
processFn: (filter: SearchFilters) => SearchFilters
|
|
||||||
): SearchFilters {
|
|
||||||
// Process the current level
|
|
||||||
filters = processFn(filters)
|
|
||||||
|
|
||||||
// Recurse through logical operators
|
|
||||||
for (const logical of LOGICAL_OPERATORS) {
|
|
||||||
if (filters[logical]) {
|
|
||||||
filters[logical]!.conditions = filters[logical]!.conditions.map(
|
|
||||||
condition => recurseSearchFilters(condition, processFn)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return filters
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes any fields that contain empty strings that would cause inconsistent
|
* Removes any fields that contain empty strings that would cause inconsistent
|
||||||
* behaviour with how backend tables are filtered (no value means no filter).
|
* behaviour with how backend tables are filtered (no value means no filter).
|
||||||
|
|
|
@ -26,9 +26,16 @@ const FILTER_ALLOWED_KEYS: (keyof SearchFilter)[] = [
|
||||||
|
|
||||||
export function unreachable(
|
export function unreachable(
|
||||||
value: never,
|
value: never,
|
||||||
message = `No such case in exhaustive switch: ${value}`
|
opts?: {
|
||||||
|
message?: string
|
||||||
|
doNotThrow?: boolean
|
||||||
|
}
|
||||||
) {
|
) {
|
||||||
throw new Error(message)
|
const message = opts?.message || `No such case in exhaustive switch: ${value}`
|
||||||
|
const doNotThrow = !!opts?.doNotThrow
|
||||||
|
if (!doNotThrow) {
|
||||||
|
throw new Error(message)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function parallelForeach<T>(
|
export async function parallelForeach<T>(
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import { SortOrder } from "../../../api"
|
import { SortOrder } from "../../../api"
|
||||||
import { SearchFilters, EmptyFilterOption } from "../../../sdk"
|
import {
|
||||||
|
SearchFilters,
|
||||||
|
EmptyFilterOption,
|
||||||
|
BasicOperator,
|
||||||
|
LogicalOperator,
|
||||||
|
} from "../../../sdk"
|
||||||
import { HttpMethod } from "../query"
|
import { HttpMethod } from "../query"
|
||||||
import { Row } from "../row"
|
import { Row } from "../row"
|
||||||
import { LoopStepType, EmailAttachment, AutomationResults } from "./automation"
|
import { LoopStepType, EmailAttachment, AutomationResults } from "./automation"
|
||||||
|
@ -118,9 +123,17 @@ export type BranchStepInputs = {
|
||||||
export type Branch = {
|
export type Branch = {
|
||||||
id: any
|
id: any
|
||||||
name: string
|
name: string
|
||||||
condition: SearchFilters
|
condition: BranchSearchFilters
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export type BranchSearchFilters = Pick<
|
||||||
|
SearchFilters,
|
||||||
|
| BasicOperator.EQUAL
|
||||||
|
| BasicOperator.NOT_EQUAL
|
||||||
|
| LogicalOperator.AND
|
||||||
|
| LogicalOperator.OR
|
||||||
|
>
|
||||||
|
|
||||||
export type MakeIntegrationInputs = {
|
export type MakeIntegrationInputs = {
|
||||||
url: string
|
url: string
|
||||||
body: any
|
body: any
|
||||||
|
|
Loading…
Reference in New Issue