From b3df1c2370383e2ae032ebcaa47e5b2542a7e917 Mon Sep 17 00:00:00 2001 From: derekpierre Date: Thu, 3 Oct 2024 18:13:39 -0400 Subject: [PATCH] Add support for if-then-else condition. --- .../src/conditions/if-then-else-condition.ts | 22 ++++++++++++++ packages/taco/src/conditions/index.ts | 1 + .../taco/src/conditions/multi-condition.ts | 19 ++++++++++-- .../src/conditions/schemas/if-then-else.ts | 30 +++++++++++++++++++ packages/taco/src/conditions/schemas/utils.ts | 2 ++ 5 files changed, 71 insertions(+), 3 deletions(-) create mode 100644 packages/taco/src/conditions/if-then-else-condition.ts create mode 100644 packages/taco/src/conditions/schemas/if-then-else.ts diff --git a/packages/taco/src/conditions/if-then-else-condition.ts b/packages/taco/src/conditions/if-then-else-condition.ts new file mode 100644 index 00000000..79d99b49 --- /dev/null +++ b/packages/taco/src/conditions/if-then-else-condition.ts @@ -0,0 +1,22 @@ +import { Condition } from './condition'; +import { + IfThenElseConditionProps, + ifThenElseConditionSchema, + IfThenElseConditionType, +} from './schemas/if-then-else'; +import { OmitConditionType } from './shared'; + +export { + IfThenElseConditionProps, + ifThenElseConditionSchema, + IfThenElseConditionType, +} from './schemas/if-then-else'; + +export class IfThenElseCondition extends Condition { + constructor(value: OmitConditionType) { + super(ifThenElseConditionSchema, { + conditionType: IfThenElseConditionType, + ...value, + }); + } +} diff --git a/packages/taco/src/conditions/index.ts b/packages/taco/src/conditions/index.ts index 3ec09a76..0c8c3d5c 100644 --- a/packages/taco/src/conditions/index.ts +++ b/packages/taco/src/conditions/index.ts @@ -6,5 +6,6 @@ export * as condition from './condition'; export * as conditionExpr from './condition-expr'; export { ConditionFactory } from './condition-factory'; export * as context from './context'; +export * as ifThenElse from './if-then-else-condition'; export * as sequential from './sequential'; export { base, predefined }; diff --git a/packages/taco/src/conditions/multi-condition.ts b/packages/taco/src/conditions/multi-condition.ts index 542b0933..434ab812 100644 --- a/packages/taco/src/conditions/multi-condition.ts +++ b/packages/taco/src/conditions/multi-condition.ts @@ -1,13 +1,15 @@ import { CompoundConditionType } from './compound-condition'; import { ConditionProps } from './condition'; +import { IfThenElseConditionType } from './if-then-else-condition'; import { ConditionVariableProps, SequentialConditionType } from './sequential'; export const maxNestedDepth = (maxDepth: number) => - (condition: ConditionProps, currentDepth = 1) => { + (condition: ConditionProps, currentDepth = 1): boolean => { if ( condition.conditionType === CompoundConditionType || - condition.conditionType === SequentialConditionType + condition.conditionType === SequentialConditionType || + condition.conditionType === IfThenElseConditionType ) { if (currentDepth > maxDepth) { // no more multi-condition types allowed at this level @@ -18,11 +20,22 @@ export const maxNestedDepth = return condition.operands.every((child: ConditionProps) => maxNestedDepth(maxDepth)(child, currentDepth + 1), ); - } else { + } else if (condition.conditionType === SequentialConditionType) { return condition.conditionVariables.every( (child: ConditionVariableProps) => maxNestedDepth(maxDepth)(child.condition, currentDepth + 1), ); + } else { + // if-then-else condition + const ifThenElseConditions = []; + ifThenElseConditions.push(condition.ifCondition); + ifThenElseConditions.push(condition.thenCondition); + if (typeof condition.elseCondition !== 'boolean') { + ifThenElseConditions.push(condition.elseCondition); + } + return ifThenElseConditions.every((child: ConditionProps) => + maxNestedDepth(maxDepth)(child, currentDepth + 1), + ); } } diff --git a/packages/taco/src/conditions/schemas/if-then-else.ts b/packages/taco/src/conditions/schemas/if-then-else.ts new file mode 100644 index 00000000..cbe35fc5 --- /dev/null +++ b/packages/taco/src/conditions/schemas/if-then-else.ts @@ -0,0 +1,30 @@ +import { z } from 'zod'; + +import { maxNestedDepth } from '../multi-condition'; + +import { baseConditionSchema } from './common'; +import { anyConditionSchema } from './utils'; + +export const IfThenElseConditionType = 'if-then-else'; + +export const ifThenElseConditionSchema: z.ZodSchema = z.lazy(() => + baseConditionSchema + .extend({ + conditionType: z + .literal(IfThenElseConditionType) + .default(IfThenElseConditionType), + ifCondition: anyConditionSchema, + thenCondition: anyConditionSchema, + elseCondition: z.union([anyConditionSchema, z.boolean()]), + }) + .refine( + (condition) => maxNestedDepth(2)(condition), + { + message: 'Exceeded max nested depth of 2 for multi-condition type', + }, // Max nested depth of 2 + ), +); + +export type IfThenElseConditionProps = z.infer< + typeof ifThenElseConditionSchema +>; diff --git a/packages/taco/src/conditions/schemas/utils.ts b/packages/taco/src/conditions/schemas/utils.ts index c84cc8d3..4f5e919e 100644 --- a/packages/taco/src/conditions/schemas/utils.ts +++ b/packages/taco/src/conditions/schemas/utils.ts @@ -3,6 +3,7 @@ import { z } from 'zod'; import { compoundConditionSchema } from '../compound-condition'; import { contractConditionSchema } from './contract'; +import { ifThenElseConditionSchema } from './if-then-else'; import { jsonApiConditionSchema } from './json-api'; import { rpcConditionSchema } from './rpc'; import { sequentialConditionSchema } from './sequential'; @@ -16,5 +17,6 @@ export const anyConditionSchema: z.ZodSchema = z.lazy(() => compoundConditionSchema, jsonApiConditionSchema, sequentialConditionSchema, + ifThenElseConditionSchema, ]), );