From 466511d7add2e893421a18068995e407cb78dff9 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Thu, 19 Jun 2025 10:45:31 -0700 Subject: [PATCH 01/16] Add types to operator names --- sdk/typescript-schema/common/guards.spec.ts | 10 ++-- sdk/typescript-schema/common/operator.ts | 46 +++++++++---------- .../expression/count-expression.ts | 10 ++-- .../expression/date-expression.ts | 6 +-- .../expression/expression.ts | 8 ++-- .../expression/location-expression.ts | 6 +-- .../expression/path-expression.ts | 8 ++-- sdk/typescript-schema/operand/operand.ts | 6 +-- 8 files changed, 50 insertions(+), 50 deletions(-) diff --git a/sdk/typescript-schema/common/guards.spec.ts b/sdk/typescript-schema/common/guards.spec.ts index c6ea803..79004e3 100644 --- a/sdk/typescript-schema/common/guards.spec.ts +++ b/sdk/typescript-schema/common/guards.spec.ts @@ -1,6 +1,6 @@ import { isValidAudienceObject } from './guards'; import { Audience } from '../audience'; -import { UnaryOperator } from './operator'; +import { UnaryBoolOperator } from './operator'; describe('Guard Functions', () => { describe('isValidAudienceObject', () => { @@ -9,7 +9,7 @@ describe('Guard Functions', () => { const validAudience: Audience = { schema_version: '1.0.0', audience: { - operator: UnaryOperator.Exists, + operator: UnaryBoolOperator.Exists, operand: { model: 'user', path: 'id' } } }; @@ -37,7 +37,7 @@ describe('Guard Functions', () => { operator: 'and', expressions: [ { - operator: UnaryOperator.Exists, + operator: UnaryBoolOperator.Exists, operand: { model: 'user', path: 'id' } }, { @@ -82,7 +82,7 @@ describe('Guard Functions', () => { operator: 'and', expressions: [ { - operator: UnaryOperator.Exists, + operator: UnaryBoolOperator.Exists, operand: { model: 'user', path: 'id' } }, { @@ -111,7 +111,7 @@ describe('Guard Functions', () => { const validAudience: Audience = { schema_version: '1.0.0-beta.1', audience: { - operator: UnaryOperator.Exists, + operator: UnaryBoolOperator.Exists, operand: { model: 'user', path: 'id' } } }; diff --git a/sdk/typescript-schema/common/operator.ts b/sdk/typescript-schema/common/operator.ts index b84f540..63cf553 100644 --- a/sdk/typescript-schema/common/operator.ts +++ b/sdk/typescript-schema/common/operator.ts @@ -4,7 +4,7 @@ * - "not": Negates a boolean expression * - "exist": Checks if a value exists */ -export enum UnaryOperator { +export enum UnaryBoolOperator { Null = "null", NotNull = "not_null", Exists = "exists", @@ -19,8 +19,8 @@ export enum UnaryOperator { * - "matches": { value1: "pattern", value2: "text" } * - "contains": { value1: "string", value2: "substring" } */ -export type BinaryOperator = - "equals" +export type BinaryBoolOperator = + "equals" | "not_equals" | "less_than" | "less_than_equal" @@ -42,8 +42,8 @@ export type BinaryOperator = * - "match_any": { list: ["a", "b"], value: "a" } * - "in": { list: [1, 2, 3], value: 2 } */ -export type ListOperator = - "contains" +export type ListBoolOperator = + "contains" | "between" | "match_any" | "match_all" @@ -56,11 +56,11 @@ export type ListOperator = * - "multiply": { value1: 4, value2: 2 } // result: 8 * - "mod": { value1: 10, value2: 3 } // result: 1 */ -export type ArithmeticOperator = - "plus" - | "minus" - | "multiply" - | "divide" +export type ArithmeticNumberOperator = + "plus" + | "minus" + | "multiply" + | "divide" | "mod" /** @@ -71,13 +71,13 @@ export type ArithmeticOperator = * - "avg": [1, 2, 3] // result: 2 * - "count": [1, 2, 3] // result: 3 */ -export type AggregationOperator = - "min" - | "max" - | "sum" - | "avg" - | "list" - | "count" +export type AggregationNumberOperator = + "min" + | "max" + | "sum" + | "avg" + | "list" + | "count" /** * Represents operators for location-based comparisons. @@ -85,9 +85,9 @@ export type AggregationOperator = * - "within": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 } * - "equals": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } } */ -export type LocationOperator = - "within" - | "equals" +export type LocationBoolOperator = + "within" + | "equals" /** * Represents logical operators for combining multiple conditions. @@ -95,6 +95,6 @@ export type LocationOperator = * - "and": { condition1: true, condition2: true } // result: true * - "or": { condition1: true, condition2: false } // result: true */ -export type LogicalOperator = - "and" - | "or" \ No newline at end of file +export type LogicalBoolOperator = + "and" + | "or" diff --git a/sdk/typescript-schema/expression/count-expression.ts b/sdk/typescript-schema/expression/count-expression.ts index 13345b9..7b4fb64 100644 --- a/sdk/typescript-schema/expression/count-expression.ts +++ b/sdk/typescript-schema/expression/count-expression.ts @@ -1,5 +1,5 @@ import { Operand } from "../operand/operand"; -import { BinaryOperator, LogicalOperator } from "../common/operator"; +import { BinaryBoolOperator, LogicalBoolOperator } from "../common/operator"; /** * Represents a count expression, which can be a number, a binary operation, or a logical group. @@ -19,9 +19,9 @@ import { BinaryOperator, LogicalOperator } from "../common/operator"; * ] * } */ -export type CountExpression = +export type CountExpression = number - | - { operator: BinaryOperator, operand: Operand } + | + { operator: BinaryBoolOperator, operand: Operand } | // logical expression group - { operator: LogicalOperator, expressions: CountExpression[] } \ No newline at end of file + { operator: LogicalBoolOperator, expressions: CountExpression[] } diff --git a/sdk/typescript-schema/expression/date-expression.ts b/sdk/typescript-schema/expression/date-expression.ts index b946032..c6ef642 100644 --- a/sdk/typescript-schema/expression/date-expression.ts +++ b/sdk/typescript-schema/expression/date-expression.ts @@ -1,4 +1,4 @@ -import { BinaryOperator, LogicalOperator } from "../common/operator"; +import { BinaryBoolOperator, LogicalBoolOperator } from "../common/operator"; import { AbsoluteDate, RelativeDate } from "../operand/date-operand"; /** @@ -26,6 +26,6 @@ export type DateExpression = AbsoluteDate | RelativeDate | - { operator: BinaryOperator, operand: AbsoluteDate | RelativeDate } + { operator: BinaryBoolOperator, operand: AbsoluteDate | RelativeDate } | // logical expression group - { operator: LogicalOperator, expressions: DateExpression[] } \ No newline at end of file + { operator: LogicalBoolOperator, expressions: DateExpression[] } diff --git a/sdk/typescript-schema/expression/expression.ts b/sdk/typescript-schema/expression/expression.ts index 5752742..d44304d 100644 --- a/sdk/typescript-schema/expression/expression.ts +++ b/sdk/typescript-schema/expression/expression.ts @@ -1,5 +1,5 @@ import { Operand } from "../operand/operand"; -import { BinaryOperator, LogicalOperator, UnaryOperator } from "../common/operator"; +import { BinaryBoolOperator, LogicalBoolOperator, UnaryBoolOperator } from "../common/operator"; /** * Represents a complex expression that can evaluate to true, false, or noop. @@ -32,8 +32,8 @@ import { BinaryOperator, LogicalOperator, UnaryOperator } from "../common/operat */ export type Expression = // unary expression - { operator: UnaryOperator, operand: Operand } + { operator: UnaryBoolOperator, operand: Operand } | // binary expression - { operator: BinaryOperator, left: Operand, right: Operand } + { operator: BinaryBoolOperator, left: Operand, right: Operand } | // logical expression group - { operator: LogicalOperator, expressions: Expression[] } + { operator: LogicalBoolOperator, expressions: Expression[] } diff --git a/sdk/typescript-schema/expression/location-expression.ts b/sdk/typescript-schema/expression/location-expression.ts index 8f413f6..586f05d 100644 --- a/sdk/typescript-schema/expression/location-expression.ts +++ b/sdk/typescript-schema/expression/location-expression.ts @@ -1,5 +1,5 @@ import { Location } from "../common/location"; -import { LocationOperator, LogicalOperator } from "../common/operator"; +import { LocationBoolOperator, LogicalBoolOperator } from "../common/operator"; /** * Represents an expression that evaluates to a location or location-based condition. @@ -22,6 +22,6 @@ import { LocationOperator, LogicalOperator } from "../common/operator"; export type LocationExpression = Location | // location (left) expression - { operator: LocationOperator, operand: Location } + { operator: LocationBoolOperator, operand: Location } | // logical expression group - { operator: LogicalOperator, expressions: LocationExpression[] } \ No newline at end of file + { operator: LogicalBoolOperator, expressions: LocationExpression[] } diff --git a/sdk/typescript-schema/expression/path-expression.ts b/sdk/typescript-schema/expression/path-expression.ts index 8d72ad5..6d569ff 100644 --- a/sdk/typescript-schema/expression/path-expression.ts +++ b/sdk/typescript-schema/expression/path-expression.ts @@ -1,5 +1,5 @@ import { Operand } from "../operand/operand"; -import { UnaryOperator, BinaryOperator } from "../common/operator"; +import { UnaryBoolOperator, BinaryBoolOperator } from "../common/operator"; /** * Represents an expression that evaluates to a path or value. @@ -21,11 +21,11 @@ import { UnaryOperator, BinaryOperator } from "../common/operator"; * operand: { path: "user.age" } * } */ -export type PathExpression = +export type PathExpression = boolean | number | string | // unary expression - { operator: UnaryOperator, expression: PathExpression } + { operator: UnaryBoolOperator, expression: PathExpression } | // binary expression - { operator: BinaryOperator, operand: Operand }; \ No newline at end of file + { operator: BinaryBoolOperator, operand: Operand }; diff --git a/sdk/typescript-schema/operand/operand.ts b/sdk/typescript-schema/operand/operand.ts index 9852a5e..a16b837 100644 --- a/sdk/typescript-schema/operand/operand.ts +++ b/sdk/typescript-schema/operand/operand.ts @@ -1,6 +1,6 @@ import { DateOperand } from "./date-operand"; import { ModelPath } from "../common/model-path"; -import { AggregationOperator } from "../common/operator"; +import { AggregationNumberOperator } from "../common/operator"; import { Expression } from "../expression/expression"; /** @@ -37,5 +37,5 @@ export type Operand = | string | DateOperand | ModelPath - | { operator: AggregationOperator, group_by_model: string, operand: Operand, condition?: Expression }; - // | { operator: ArithmeticOperator, left: Operand, right: Operand }; \ No newline at end of file + | { operator: AggregationNumberOperator, group_by_model: string, operand: Operand, condition?: Expression }; +// | { operator: ArithmeticOperator, left: Operand, right: Operand }; From fefb09756959e0af5713d0847e87027abfa0f5ce Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Thu, 19 Jun 2025 11:18:19 -0700 Subject: [PATCH 02/16] Change a lot of things --- sdk/typescript-schema/common/operator.ts | 8 +++-- .../expression/boolean-expression.ts | 18 +++++++++++ .../expression/count-expression.ts | 27 ---------------- .../expression/date-expression.ts | 8 ++--- .../expression/expression.ts | 18 ++++++----- .../expression/location-expression.ts | 6 ++-- .../expression/number-expression.ts | 28 +++++++++++++++++ .../expression/path-expression.ts | 31 ------------------- .../expression/string-expression.ts | 5 +++ sdk/typescript-schema/index.ts | 17 +++++----- .../date-operand.ts => literal/date.ts} | 18 ++--------- .../operand.ts => literal/literal.ts} | 13 +++----- .../{common => literal}/location.ts | 2 +- .../{common => literal}/model-path.ts | 2 +- .../operand/location-operand.ts | 17 ---------- 15 files changed, 92 insertions(+), 126 deletions(-) create mode 100644 sdk/typescript-schema/expression/boolean-expression.ts delete mode 100644 sdk/typescript-schema/expression/count-expression.ts create mode 100644 sdk/typescript-schema/expression/number-expression.ts delete mode 100644 sdk/typescript-schema/expression/path-expression.ts create mode 100644 sdk/typescript-schema/expression/string-expression.ts rename sdk/typescript-schema/{operand/date-operand.ts => literal/date.ts} (72%) rename sdk/typescript-schema/{operand/operand.ts => literal/literal.ts} (61%) rename sdk/typescript-schema/{common => literal}/location.ts (99%) rename sdk/typescript-schema/{common => literal}/model-path.ts (99%) delete mode 100644 sdk/typescript-schema/operand/location-operand.ts diff --git a/sdk/typescript-schema/common/operator.ts b/sdk/typescript-schema/common/operator.ts index 63cf553..e99b79a 100644 --- a/sdk/typescript-schema/common/operator.ts +++ b/sdk/typescript-schema/common/operator.ts @@ -19,13 +19,17 @@ export enum UnaryBoolOperator { * - "matches": { value1: "pattern", value2: "text" } * - "contains": { value1: "string", value2: "substring" } */ -export type BinaryBoolOperator = +export type NumberBoolOperator = "equals" | "not_equals" | "less_than" | "less_than_equal" | "greater_than" | "greater_than_equal" + +export type StringBoolOperator = + "equals" + | "not_equals" | "matches" | "contains" | "not_contains" @@ -56,7 +60,7 @@ export type ListBoolOperator = * - "multiply": { value1: 4, value2: 2 } // result: 8 * - "mod": { value1: 10, value2: 3 } // result: 1 */ -export type ArithmeticNumberOperator = +export type BinaryNumberOperator = "plus" | "minus" | "multiply" diff --git a/sdk/typescript-schema/expression/boolean-expression.ts b/sdk/typescript-schema/expression/boolean-expression.ts new file mode 100644 index 0000000..509d503 --- /dev/null +++ b/sdk/typescript-schema/expression/boolean-expression.ts @@ -0,0 +1,18 @@ +import { ListBoolOperator, LocationBoolOperator, LogicalBoolOperator, NumberBoolOperator, StringBoolOperator } from "../common/operator"; +import { ModelPath } from "../literal/model-path"; +import { DateExpression } from "./date-expression"; +import { Expression } from "./expression"; +import { LocationExpression } from "./location-expression"; +import { NumberExpression } from "./number-expression"; +import { StringExpression } from "./string-expression"; + +export type BooleanExpression = + boolean + | ModelPath + | { operator: NumberBoolOperator, left: NumberExpression, right: NumberExpression } + | { operator: StringBoolOperator, left: StringExpression, right: StringExpression } + | { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } + | { operator: NumberBoolOperator, left: DateExpression, right: DateExpression } + | { operator: LogicalBoolOperator, left: BooleanExpression, right: BooleanExpression } + | { operator: LogicalBoolOperator, expressions: BooleanExpression[] } +// TODO: | { operator: ListBoolOperator, left: Expression, right: ListExpression } diff --git a/sdk/typescript-schema/expression/count-expression.ts b/sdk/typescript-schema/expression/count-expression.ts deleted file mode 100644 index 7b4fb64..0000000 --- a/sdk/typescript-schema/expression/count-expression.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Operand } from "../operand/operand"; -import { BinaryBoolOperator, LogicalBoolOperator } from "../common/operator"; - -/** - * Represents a count expression, which can be a number, a binary operation, or a logical group. - * Examples: - * 1. Simple count: - * 5 - * - * 2. Binary count expression: - * { operator: "greater_than", operand: { path: "event.count" } } - * - * 3. Logical group of count expressions: - * { - * operator: "and", - * expressions: [ - * 1, - * { operator: "greater_than", operand: { path: "event.count" } } - * ] - * } - */ -export type CountExpression = - number - | - { operator: BinaryBoolOperator, operand: Operand } - | // logical expression group - { operator: LogicalBoolOperator, expressions: CountExpression[] } diff --git a/sdk/typescript-schema/expression/date-expression.ts b/sdk/typescript-schema/expression/date-expression.ts index c6ef642..d41c4d7 100644 --- a/sdk/typescript-schema/expression/date-expression.ts +++ b/sdk/typescript-schema/expression/date-expression.ts @@ -1,5 +1,6 @@ import { BinaryBoolOperator, LogicalBoolOperator } from "../common/operator"; -import { AbsoluteDate, RelativeDate } from "../operand/date-operand"; +import { AbsoluteDate, RelativeDate } from "../literal/date"; +import { ModelPath } from "../literal/model-path"; /** * Represents an expression that evaluates to a date or date-based condition. @@ -25,7 +26,4 @@ import { AbsoluteDate, RelativeDate } from "../operand/date-operand"; export type DateExpression = AbsoluteDate | RelativeDate - | - { operator: BinaryBoolOperator, operand: AbsoluteDate | RelativeDate } - | // logical expression group - { operator: LogicalBoolOperator, expressions: DateExpression[] } + | ModelPath diff --git a/sdk/typescript-schema/expression/expression.ts b/sdk/typescript-schema/expression/expression.ts index d44304d..5378eca 100644 --- a/sdk/typescript-schema/expression/expression.ts +++ b/sdk/typescript-schema/expression/expression.ts @@ -1,5 +1,10 @@ -import { Operand } from "../operand/operand"; +import { Operand } from "../literal/literal"; import { BinaryBoolOperator, LogicalBoolOperator, UnaryBoolOperator } from "../common/operator"; +import { BooleanExpression } from "./boolean-expression"; +import { DateExpression } from "./date-expression"; +import { NumberExpression } from "./number-expression"; +import { LocationExpression } from "./location-expression"; +import { ModelPath } from "../literal/model-path"; /** * Represents a complex expression that can evaluate to true, false, or noop. @@ -31,9 +36,8 @@ import { BinaryBoolOperator, LogicalBoolOperator, UnaryBoolOperator } from "../c * } */ export type Expression = - // unary expression - { operator: UnaryBoolOperator, operand: Operand } - | // binary expression - { operator: BinaryBoolOperator, left: Operand, right: Operand } - | // logical expression group - { operator: LogicalBoolOperator, expressions: Expression[] } + BooleanExpression + | DateExpression + | NumberExpression + | LocationExpression + | ModelPath diff --git a/sdk/typescript-schema/expression/location-expression.ts b/sdk/typescript-schema/expression/location-expression.ts index 586f05d..dfa10ce 100644 --- a/sdk/typescript-schema/expression/location-expression.ts +++ b/sdk/typescript-schema/expression/location-expression.ts @@ -1,5 +1,6 @@ import { Location } from "../common/location"; import { LocationBoolOperator, LogicalBoolOperator } from "../common/operator"; +import { ModelPath } from "../literal/model-path"; /** * Represents an expression that evaluates to a location or location-based condition. @@ -21,7 +22,4 @@ import { LocationBoolOperator, LogicalBoolOperator } from "../common/operator"; */ export type LocationExpression = Location - | // location (left) expression - { operator: LocationBoolOperator, operand: Location } - | // logical expression group - { operator: LogicalBoolOperator, expressions: LocationExpression[] } + | ModelPath diff --git a/sdk/typescript-schema/expression/number-expression.ts b/sdk/typescript-schema/expression/number-expression.ts new file mode 100644 index 0000000..ee01ed2 --- /dev/null +++ b/sdk/typescript-schema/expression/number-expression.ts @@ -0,0 +1,28 @@ +import { Operand } from "../literal/literal"; +import { AggregationNumberOperator, BinaryBoolOperator, BinaryNumberOperator, LogicalBoolOperator } from "../common/operator"; +import { BooleanExpression } from "./boolean-expression"; +import { ModelPath } from "../literal/model-path"; + +/** + * Represents a count expression, which can be a number, a binary operation, or a logical group. + * Examples: + * 1. Simple count: + * 5 + * + * 2. Binary count expression: + * { operator: "greater_than", operand: { path: "event.count" } } + * + * 3. Logical group of count expressions: + * { + * operator: "and", + * expressions: [ + * 1, + * { operator: "greater_than", operand: { path: "event.count" } } + * ] + * } + */ +export type NumberExpression = + number + | ModelPath + | { operator: BinaryNumberOperator, left: NumberExpression, right: NumberExpression } + | { operator: AggregationNumberOperator, group_by_model: string, operand: NumberExpression, condition?: BooleanExpression } diff --git a/sdk/typescript-schema/expression/path-expression.ts b/sdk/typescript-schema/expression/path-expression.ts deleted file mode 100644 index 6d569ff..0000000 --- a/sdk/typescript-schema/expression/path-expression.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { Operand } from "../operand/operand"; -import { UnaryBoolOperator, BinaryBoolOperator } from "../common/operator"; - -/** - * Represents an expression that evaluates to a path or value. - * Examples: - * 1. Primitive values: - * true - * 42 - * "hello" - * - * 2. Unary expression (NOT): - * { - * operator: "not", - * expression: { operator: "equals", operand: { path: "status" } } - * } - * - * 3. Binary expression (comparing a path to a value): - * { - * operator: "equals", - * operand: { path: "user.age" } - * } - */ -export type PathExpression = - boolean - | number - | string - | // unary expression - { operator: UnaryBoolOperator, expression: PathExpression } - | // binary expression - { operator: BinaryBoolOperator, operand: Operand }; diff --git a/sdk/typescript-schema/expression/string-expression.ts b/sdk/typescript-schema/expression/string-expression.ts new file mode 100644 index 0000000..ab056c3 --- /dev/null +++ b/sdk/typescript-schema/expression/string-expression.ts @@ -0,0 +1,5 @@ +import { ModelPath } from "../literal/model-path"; + +export type StringExpression = + string + | ModelPath diff --git a/sdk/typescript-schema/index.ts b/sdk/typescript-schema/index.ts index dd6e5d2..ca334ca 100644 --- a/sdk/typescript-schema/index.ts +++ b/sdk/typescript-schema/index.ts @@ -6,20 +6,21 @@ export * from './audience'; // Export expression types export * from './expression/expression'; -export * from './expression/count-expression'; +export * from './expression/number-expression'; export * from './expression/date-expression'; export * from './expression/location-expression'; -export * from './expression/path-expression'; +export * from './expression/string-expression'; +export * from './expression/boolean-expression'; -// Export operand types -export * from './operand/operand'; -export * from './operand/location-operand'; -export * from './operand/date-operand'; +// Export literal types +export * from './literal/literal'; +export * from './literal/location'; +export * from './literal/date'; +export * from './literal/model-path'; // Export common types -export * from './common/location'; export * from './common/operator'; export * from './common/version'; // Export type guards -export * from './common/guards'; \ No newline at end of file +export * from './common/guards'; diff --git a/sdk/typescript-schema/operand/date-operand.ts b/sdk/typescript-schema/literal/date.ts similarity index 72% rename from sdk/typescript-schema/operand/date-operand.ts rename to sdk/typescript-schema/literal/date.ts index f07f27f..bd826b4 100644 --- a/sdk/typescript-schema/operand/date-operand.ts +++ b/sdk/typescript-schema/literal/date.ts @@ -58,18 +58,6 @@ export type RelativeDate = } }; -/** - * Represents a date value that can be either absolute or relative. - * Examples: - * 1. Absolute date: - * { date: { absolute: "2023-01-01T00:00:00Z" } } - * - * 2. Relative date (30 days ago): - * { date: { relative: { offset: -30, unit: "day" } } } - * - * 3. Relative date (start of current month): - * { date: { relative: { offset: 0, unit: "month", boundary: "start" } } } - */ -export type DateOperand = - { date: AbsoluteDate } - | { date: RelativeDate } \ No newline at end of file +export type DateLiteral = + AbsoluteDate + | RelativeDate diff --git a/sdk/typescript-schema/operand/operand.ts b/sdk/typescript-schema/literal/literal.ts similarity index 61% rename from sdk/typescript-schema/operand/operand.ts rename to sdk/typescript-schema/literal/literal.ts index a16b837..70e55a6 100644 --- a/sdk/typescript-schema/operand/operand.ts +++ b/sdk/typescript-schema/literal/literal.ts @@ -1,7 +1,5 @@ -import { DateOperand } from "./date-operand"; -import { ModelPath } from "../common/model-path"; -import { AggregationNumberOperator } from "../common/operator"; -import { Expression } from "../expression/expression"; +import { DateLiteral } from "./date"; +import { ModelPath } from "./model-path"; /** * Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations. @@ -31,11 +29,10 @@ import { Expression } from "../expression/expression"; * 5. Date operand: * { date: { absolute: "2023-01-01T00:00:00Z" } } */ -export type Operand = +export type Literal = boolean | number | string - | DateOperand + | DateLiteral | ModelPath - | { operator: AggregationNumberOperator, group_by_model: string, operand: Operand, condition?: Expression }; -// | { operator: ArithmeticOperator, left: Operand, right: Operand }; + | Location diff --git a/sdk/typescript-schema/common/location.ts b/sdk/typescript-schema/literal/location.ts similarity index 99% rename from sdk/typescript-schema/common/location.ts rename to sdk/typescript-schema/literal/location.ts index 6b78117..96d9587 100644 --- a/sdk/typescript-schema/common/location.ts +++ b/sdk/typescript-schema/literal/location.ts @@ -22,4 +22,4 @@ export type Location = { value: number, unit: DistanceUnit } -} \ No newline at end of file +} diff --git a/sdk/typescript-schema/common/model-path.ts b/sdk/typescript-schema/literal/model-path.ts similarity index 99% rename from sdk/typescript-schema/common/model-path.ts rename to sdk/typescript-schema/literal/model-path.ts index ec41859..1cef16c 100644 --- a/sdk/typescript-schema/common/model-path.ts +++ b/sdk/typescript-schema/literal/model-path.ts @@ -13,4 +13,4 @@ export type ModelPath = { model: string, path: string -} \ No newline at end of file +} diff --git a/sdk/typescript-schema/operand/location-operand.ts b/sdk/typescript-schema/operand/location-operand.ts deleted file mode 100644 index eed5fbe..0000000 --- a/sdk/typescript-schema/operand/location-operand.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { Location } from "../common/location"; - -/** - * Represents a location value that can be used in location-based expressions. - * Examples: - * 1. Simple location (latitude/longitude only): - * { location: { latitude: 40.7128, longitude: -74.0060 } } - * - * 2. Location with distance in miles: - * { location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } } - * - * 3. Location with distance in meters: - * { location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 1000, unit: "meters" } } } - */ -export type LocationOperand = { - location: Location -} \ No newline at end of file From b3af7bf482482eea7ce0305b0e921c5373242d09 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Thu, 19 Jun 2025 11:29:47 -0700 Subject: [PATCH 03/16] Fix imports --- sdk/typescript-schema/expression/boolean-expression.ts | 4 ++-- sdk/typescript-schema/expression/date-expression.ts | 1 - sdk/typescript-schema/expression/expression.ts | 2 -- sdk/typescript-schema/expression/location-expression.ts | 3 +-- sdk/typescript-schema/expression/number-expression.ts | 3 +-- 5 files changed, 4 insertions(+), 9 deletions(-) diff --git a/sdk/typescript-schema/expression/boolean-expression.ts b/sdk/typescript-schema/expression/boolean-expression.ts index 509d503..19eeae8 100644 --- a/sdk/typescript-schema/expression/boolean-expression.ts +++ b/sdk/typescript-schema/expression/boolean-expression.ts @@ -1,7 +1,6 @@ -import { ListBoolOperator, LocationBoolOperator, LogicalBoolOperator, NumberBoolOperator, StringBoolOperator } from "../common/operator"; +import { LocationBoolOperator, LogicalBoolOperator, NumberBoolOperator, StringBoolOperator, UnaryBoolOperator } from "../common/operator"; import { ModelPath } from "../literal/model-path"; import { DateExpression } from "./date-expression"; -import { Expression } from "./expression"; import { LocationExpression } from "./location-expression"; import { NumberExpression } from "./number-expression"; import { StringExpression } from "./string-expression"; @@ -9,6 +8,7 @@ import { StringExpression } from "./string-expression"; export type BooleanExpression = boolean | ModelPath + | { operator: UnaryBoolOperator, operand: ModelPath } | { operator: NumberBoolOperator, left: NumberExpression, right: NumberExpression } | { operator: StringBoolOperator, left: StringExpression, right: StringExpression } | { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } diff --git a/sdk/typescript-schema/expression/date-expression.ts b/sdk/typescript-schema/expression/date-expression.ts index d41c4d7..80f1f54 100644 --- a/sdk/typescript-schema/expression/date-expression.ts +++ b/sdk/typescript-schema/expression/date-expression.ts @@ -1,4 +1,3 @@ -import { BinaryBoolOperator, LogicalBoolOperator } from "../common/operator"; import { AbsoluteDate, RelativeDate } from "../literal/date"; import { ModelPath } from "../literal/model-path"; diff --git a/sdk/typescript-schema/expression/expression.ts b/sdk/typescript-schema/expression/expression.ts index 5378eca..f6b7210 100644 --- a/sdk/typescript-schema/expression/expression.ts +++ b/sdk/typescript-schema/expression/expression.ts @@ -1,5 +1,3 @@ -import { Operand } from "../literal/literal"; -import { BinaryBoolOperator, LogicalBoolOperator, UnaryBoolOperator } from "../common/operator"; import { BooleanExpression } from "./boolean-expression"; import { DateExpression } from "./date-expression"; import { NumberExpression } from "./number-expression"; diff --git a/sdk/typescript-schema/expression/location-expression.ts b/sdk/typescript-schema/expression/location-expression.ts index dfa10ce..dcfc8cc 100644 --- a/sdk/typescript-schema/expression/location-expression.ts +++ b/sdk/typescript-schema/expression/location-expression.ts @@ -1,5 +1,4 @@ -import { Location } from "../common/location"; -import { LocationBoolOperator, LogicalBoolOperator } from "../common/operator"; +import { Location } from "../literal/location"; import { ModelPath } from "../literal/model-path"; /** diff --git a/sdk/typescript-schema/expression/number-expression.ts b/sdk/typescript-schema/expression/number-expression.ts index ee01ed2..9e49302 100644 --- a/sdk/typescript-schema/expression/number-expression.ts +++ b/sdk/typescript-schema/expression/number-expression.ts @@ -1,5 +1,4 @@ -import { Operand } from "../literal/literal"; -import { AggregationNumberOperator, BinaryBoolOperator, BinaryNumberOperator, LogicalBoolOperator } from "../common/operator"; +import { AggregationNumberOperator, BinaryNumberOperator } from "../common/operator"; import { BooleanExpression } from "./boolean-expression"; import { ModelPath } from "../literal/model-path"; From 1a488a8ee2a2c0a2744b74d85286e1a5143891d3 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Thu, 19 Jun 2025 11:56:02 -0700 Subject: [PATCH 04/16] Add titles to everything --- sdk/typescript-schema/audience.ts | 10 ++-- .../expression/boolean-expression.ts | 53 ++++++++++++++++--- .../expression/date-expression.ts | 3 +- .../expression/expression.ts | 3 +- .../expression/location-expression.ts | 3 +- .../expression/number-expression.ts | 17 ++++-- .../expression/string-expression.ts | 3 ++ sdk/typescript-schema/literal/date.ts | 13 +++-- sdk/typescript-schema/literal/literal.ts | 4 +- sdk/typescript-schema/literal/location.ts | 6 ++- sdk/typescript-schema/literal/model-path.ts | 3 +- 11 files changed, 95 insertions(+), 23 deletions(-) diff --git a/sdk/typescript-schema/audience.ts b/sdk/typescript-schema/audience.ts index 2904f94..583a7db 100644 --- a/sdk/typescript-schema/audience.ts +++ b/sdk/typescript-schema/audience.ts @@ -2,7 +2,8 @@ import { Version } from "./common/version"; import { Expression } from "./expression/expression"; /** - * Represents a logical combination of audience expressions using AND/OR operators. + * @title AudienceDefinition + * @description Represents a logical combination of audience expressions using AND/OR operators. * Examples: * 1. Simple AND combination: * { @@ -77,7 +78,10 @@ import { Expression } from "./expression/expression"; * } * } */ -export type Audience = { +export interface Audience { schema_version: Version, + /** + * @title Audience + */ audience: Expression -} \ No newline at end of file +} diff --git a/sdk/typescript-schema/expression/boolean-expression.ts b/sdk/typescript-schema/expression/boolean-expression.ts index 19eeae8..e8d2353 100644 --- a/sdk/typescript-schema/expression/boolean-expression.ts +++ b/sdk/typescript-schema/expression/boolean-expression.ts @@ -1,18 +1,57 @@ import { LocationBoolOperator, LogicalBoolOperator, NumberBoolOperator, StringBoolOperator, UnaryBoolOperator } from "../common/operator"; import { ModelPath } from "../literal/model-path"; import { DateExpression } from "./date-expression"; +import { Expression } from "./expression"; import { LocationExpression } from "./location-expression"; import { NumberExpression } from "./number-expression"; import { StringExpression } from "./string-expression"; +/** + * @title UnaryBoolExpression + */ +type UnaryBoolExpression = { operator: UnaryBoolOperator, operand: Expression } + +/** + * @title NumberBoolExpression + */ +type NumberBoolExpression = { operator: NumberBoolOperator, left: NumberExpression, right: NumberExpression } + +/** + * @title StringBoolExpression + */ +type StringBoolExpression = { operator: StringBoolOperator, left: StringExpression, right: StringExpression } + +/** + * @title DateBoolExpression + */ +type DateBoolExpression = { operator: NumberBoolOperator, left: DateExpression, right: DateExpression } + +/** + * @title LogicalBoolExpression + */ +type LogicalBoolExpression = { operator: LogicalBoolOperator, left: BooleanExpression, right: BooleanExpression } + +/** + * @title LogicalManyBoolExpression + */ +type LogicalManyBoolExpression = { operator: LogicalBoolOperator, expressions: BooleanExpression[] } + +/** + * @title LocationBooleanExpression + */ +type LocationBooleanExpression = { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } + +/** + * @title BooleanExpression + */ export type BooleanExpression = boolean | ModelPath - | { operator: UnaryBoolOperator, operand: ModelPath } - | { operator: NumberBoolOperator, left: NumberExpression, right: NumberExpression } - | { operator: StringBoolOperator, left: StringExpression, right: StringExpression } - | { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } - | { operator: NumberBoolOperator, left: DateExpression, right: DateExpression } - | { operator: LogicalBoolOperator, left: BooleanExpression, right: BooleanExpression } - | { operator: LogicalBoolOperator, expressions: BooleanExpression[] } + | UnaryBoolExpression + | NumberBoolExpression + | StringBoolExpression + | DateBoolExpression + | LogicalBoolExpression + | LogicalManyBoolExpression + | LocationBooleanExpression // TODO: | { operator: ListBoolOperator, left: Expression, right: ListExpression } diff --git a/sdk/typescript-schema/expression/date-expression.ts b/sdk/typescript-schema/expression/date-expression.ts index 80f1f54..06aaa06 100644 --- a/sdk/typescript-schema/expression/date-expression.ts +++ b/sdk/typescript-schema/expression/date-expression.ts @@ -2,7 +2,8 @@ import { AbsoluteDate, RelativeDate } from "../literal/date"; import { ModelPath } from "../literal/model-path"; /** - * Represents an expression that evaluates to a date or date-based condition. + * @title BooleanExpression + * @description Represents an expression that evaluates to a date or date-based condition. * Examples: * 1. Absolute date: * { absolute: "2023-01-01T00:00:00Z" } diff --git a/sdk/typescript-schema/expression/expression.ts b/sdk/typescript-schema/expression/expression.ts index f6b7210..b53bf97 100644 --- a/sdk/typescript-schema/expression/expression.ts +++ b/sdk/typescript-schema/expression/expression.ts @@ -5,7 +5,8 @@ import { LocationExpression } from "./location-expression"; import { ModelPath } from "../literal/model-path"; /** - * Represents a complex expression that can evaluate to true, false, or noop. + * @title Expression + * @description Represents a complex expression that can evaluate to true, false, or noop. * Examples: * 1. Join expression (combining expressions from different models): * { diff --git a/sdk/typescript-schema/expression/location-expression.ts b/sdk/typescript-schema/expression/location-expression.ts index dcfc8cc..006449a 100644 --- a/sdk/typescript-schema/expression/location-expression.ts +++ b/sdk/typescript-schema/expression/location-expression.ts @@ -2,7 +2,8 @@ import { Location } from "../literal/location"; import { ModelPath } from "../literal/model-path"; /** - * Represents an expression that evaluates to a location or location-based condition. + * @title LocationExpression + * @description Represents an expression that evaluates to a location or location-based condition. * Examples: * 1. Simple location: * { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } diff --git a/sdk/typescript-schema/expression/number-expression.ts b/sdk/typescript-schema/expression/number-expression.ts index 9e49302..eb2787d 100644 --- a/sdk/typescript-schema/expression/number-expression.ts +++ b/sdk/typescript-schema/expression/number-expression.ts @@ -3,7 +3,18 @@ import { BooleanExpression } from "./boolean-expression"; import { ModelPath } from "../literal/model-path"; /** - * Represents a count expression, which can be a number, a binary operation, or a logical group. + * @title BinaryNumberExpression + */ +type BinaryNumberExpression = { operator: BinaryNumberOperator, left: NumberExpression, right: NumberExpression } + +/** + * @title AggregateNumberExpression + */ +type AggregateNumberExpression = { operator: AggregationNumberOperator, group_by_model: string, operand: NumberExpression, condition?: BooleanExpression } + +/** + * @title NumberExpression + * @description Represents a count expression, which can be a number, a binary operation, or a logical group. * Examples: * 1. Simple count: * 5 @@ -23,5 +34,5 @@ import { ModelPath } from "../literal/model-path"; export type NumberExpression = number | ModelPath - | { operator: BinaryNumberOperator, left: NumberExpression, right: NumberExpression } - | { operator: AggregationNumberOperator, group_by_model: string, operand: NumberExpression, condition?: BooleanExpression } + | BinaryNumberExpression + | AggregateNumberExpression diff --git a/sdk/typescript-schema/expression/string-expression.ts b/sdk/typescript-schema/expression/string-expression.ts index ab056c3..40533d9 100644 --- a/sdk/typescript-schema/expression/string-expression.ts +++ b/sdk/typescript-schema/expression/string-expression.ts @@ -1,5 +1,8 @@ import { ModelPath } from "../literal/model-path"; +/** + * @title StringExpression + */ export type StringExpression = string | ModelPath diff --git a/sdk/typescript-schema/literal/date.ts b/sdk/typescript-schema/literal/date.ts index bd826b4..45c089d 100644 --- a/sdk/typescript-schema/literal/date.ts +++ b/sdk/typescript-schema/literal/date.ts @@ -1,5 +1,6 @@ /** - * Represents units of time that can be used in relative date calculations. + * @title DateUnit + * @description Represents units of time that can be used in relative date calculations. * Examples: * - 'second': 1 second * - 'minute': 60 seconds @@ -21,7 +22,8 @@ export type DateUnit = | 'year'; /** - * Represents an absolute date/time value. + * @title AbsoluteDate + * @description Represents an absolute date/time value. * Examples: * 1. ISO 8601 date: * { absolute: "2023-01-01T00:00:00Z" } @@ -38,7 +40,8 @@ export type AbsoluteDate = }; /** - * Represents a date/time relative to the current time. + * @title RelativeDate + * @description Represents a date/time relative to the current time. * Examples: * 1. 7 days ago: * { relative: { offset: -7, unit: "day" } } @@ -57,7 +60,9 @@ export type RelativeDate = boundary?: "start" | "end" } }; - +/** + * @title DateLiteral + */ export type DateLiteral = AbsoluteDate | RelativeDate diff --git a/sdk/typescript-schema/literal/literal.ts b/sdk/typescript-schema/literal/literal.ts index 70e55a6..6b99595 100644 --- a/sdk/typescript-schema/literal/literal.ts +++ b/sdk/typescript-schema/literal/literal.ts @@ -1,8 +1,10 @@ import { DateLiteral } from "./date"; import { ModelPath } from "./model-path"; +import { Location } from "./location"; /** - * Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations. + * @title Literal + * @description Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations. * Examples: * 1. Primitive values: * true diff --git a/sdk/typescript-schema/literal/location.ts b/sdk/typescript-schema/literal/location.ts index 96d9587..56eb242 100644 --- a/sdk/typescript-schema/literal/location.ts +++ b/sdk/typescript-schema/literal/location.ts @@ -1,10 +1,14 @@ +/** + * @title DistanceUnit + */ export type DistanceUnit = "meters" | "miles" | "kilometers"; /** - * Represents a geographic location, optionally with a distance constraint. + * @title Location + * @description Represents a geographic location, optionally with a distance constraint. * Examples: * 1. Simple location: * { "latitude": 37.7749, "longitude": -122.4194 } diff --git a/sdk/typescript-schema/literal/model-path.ts b/sdk/typescript-schema/literal/model-path.ts index 1cef16c..c775ffb 100644 --- a/sdk/typescript-schema/literal/model-path.ts +++ b/sdk/typescript-schema/literal/model-path.ts @@ -1,5 +1,6 @@ /** - * Represents a model path reference within a data model. + * @title ModelPath + * @description Represents a model path reference within a data model. * Examples: * 1. Simple model path: * { "model": "user", "path": "email" } From 34b14bcde24db94dfb1cfe9d97b7c754208508f4 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Thu, 19 Jun 2025 12:08:19 -0700 Subject: [PATCH 05/16] Update JSON schema + fix audience titles --- schema/audience-definition-schema.json | 504 +++++++++--------- sdk/typescript-schema/audience.ts | 12 +- .../schema/audience-schema.json | 504 +++++++++--------- .../scripts/add_titles_to_schema.sh | 67 --- .../scripts/gen_schema_with_titles.sh | 6 +- 5 files changed, 487 insertions(+), 606 deletions(-) delete mode 100755 sdk/typescript-schema/scripts/add_titles_to_schema.sh diff --git a/schema/audience-definition-schema.json b/schema/audience-definition-schema.json index 14ecc6d..363ed22 100644 --- a/schema/audience-definition-schema.json +++ b/schema/audience-definition-schema.json @@ -3,7 +3,7 @@ "definitions": { "AbsoluteDate": { "additionalProperties": false, - "description": "Represents an absolute date/time value. Examples: 1. ISO 8601 date: { absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Date only: { absolute: \"2023-01-01\" }\n\n3. Date with timezone: { absolute: \"2023-01-01T00:00:00-05:00\" }", + "description": "Represents an absolute date/time value.\nExamples:\n1. ISO 8601 date:\n{ absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Date only:\n{ absolute: \"2023-01-01\" }\n\n3. Date with timezone:\n{ absolute: \"2023-01-01T00:00:00-05:00\" }", "properties": { "absolute": { "type": "string" @@ -12,9 +12,10 @@ "required": [ "absolute" ], + "title": "AbsoluteDate", "type": "object" }, - "AggregationOperator": { + "AggregationNumberOperator": { "description": "Represents operators for aggregating multiple values. Examples:\n- \"min\": [1, 2, 3] // result: 1\n- \"max\": [1, 2, 3] // result: 3\n- \"avg\": [1, 2, 3] // result: 2\n- \"count\": [1, 2, 3] // result: 3", "enum": [ "min", @@ -26,23 +27,12 @@ ], "type": "string" }, - "ArithmeticOperator": { - "description": "Represents mathematical operators for numeric calculations. Examples:\n- \"plus\": { value1: 5, value2: 3 } // result: 8\n- \"multiply\": { value1: 4, value2: 2 } // result: 8\n- \"mod\": { value1: 10, value2: 3 } // result: 1", - "enum": [ - "plus", - "minus", - "multiply", - "divide", - "mod" - ], - "type": "string" - }, "Audience": { "additionalProperties": false, - "description": "Represents a complete audience definition with a root logical expression. Examples: 1. Simple audience: { \"schema_version\": \"1.0.0\", \"audience\": { \"operator\": \"and\", \"expressions\": [ { \"model\": \"user\", \"expression\": { \"operator\": \"exists\", \"operand\": { \"path\": \"id\" } } }, { \"model\": \"purchase\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } } ] } }\n\n2. Audience with nested logic: { \"schema_version\": \"1.0.0\", \"audience\": { \"operator\": \"or\", \"expressions\": [ { \"model\": \"user\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" } }, { \"operator\": \"and\", \"expressions\": [ { \"model\": \"signup\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } }, { \"model\": \"user\", \"expression\": { \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 } } ] } ] } }", + "description": "Represents a complete audience definition with a root logical expression.\nExamples:\n1. Simple audience:\n{\n\"schema_version\": \"1.0.0\",\n\"audience\": {\n\"operator\": \"and\",\n\"expressions\": [\n{ \"model\": \"user\", \"expression\": { \"operator\": \"exists\", \"operand\": { \"path\": \"id\" } } },\n{ \"model\": \"purchase\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } }\n]\n}\n}\n\n2. Audience with nested logic:\n{\n\"schema_version\": \"1.0.0\",\n\"audience\": {\n\"operator\": \"or\",\n\"expressions\": [\n{ \"model\": \"user\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" } },\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"model\": \"signup\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } },\n{ \"model\": \"user\", \"expression\": { \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 } }\n]\n}\n]\n}\n}", "properties": { "audience": { - "$ref": "#/definitions/Expression", + "$ref": "#/definitions/BooleanExpression", "title": "Audience" }, "schema_version": { @@ -53,157 +43,201 @@ "schema_version", "audience" ], - "type": "object", - "title": "AudienceDefinition" + "title": "AudienceDefinition", + "type": "object" }, - "BinaryOperator": { - "description": "Represents binary operators that compare two values. Examples:\n- \"equals\": { value1: 5, value2: 5 }\n- \"less_than\": { value1: 3, value2: 5 }\n- \"matches\": { value1: \"pattern\", value2: \"text\" }\n- \"contains\": { value1: \"string\", value2: \"substring\" }", + "BinaryNumberOperator": { + "description": "Represents mathematical operators for numeric calculations. Examples:\n- \"plus\": { value1: 5, value2: 3 } // result: 8\n- \"multiply\": { value1: 4, value2: 2 } // result: 8\n- \"mod\": { value1: 10, value2: 3 } // result: 1", "enum": [ - "equals", - "not_equals", - "less_than", - "less_than_equal", - "greater_than", - "greater_than_equal", - "matches", - "contains", - "not_contains", - "starts_with", - "not_starts_with", - "ends_with", - "not_ends_with" + "plus", + "minus", + "multiply", + "divide", + "mod" ], "type": "string" }, - "CountExpression": { + "BooleanExpression": { "anyOf": [ { - "type": "number" + "type": "boolean" + }, + { + "$ref": "#/definitions/ModelPath" }, { "additionalProperties": false, "properties": { "operand": { - "$ref": "#/definitions/Operand" + "$ref": "#/definitions/Expression" }, "operator": { - "$ref": "#/definitions/BinaryOperator" + "$ref": "#/definitions/UnaryBoolOperator" } }, "required": [ "operator", "operand" ], + "title": "UnaryBoolExpression", "type": "object" }, { "additionalProperties": false, "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/CountExpression" - }, - "type": "array" + "left": { + "$ref": "#/definitions/NumberExpression" }, "operator": { - "$ref": "#/definitions/LogicalOperator" + "$ref": "#/definitions/NumberBoolOperator" + }, + "right": { + "$ref": "#/definitions/NumberExpression" } }, "required": [ "operator", - "expressions" + "left", + "right" ], + "title": "NumberBoolExpression", "type": "object" - } - ], - "description": "Represents a count expression, which can be a number, a binary operation, or a logical group. Examples: 1. Simple count: 5\n\n2. Binary count expression: { operator: \"greater_than\", operand: { path: \"event.count\" } }\n\n3. Logical group of count expressions: { operator: \"and\", expressions: [ 1, { operator: \"greater_than\", operand: { path: \"event.count\" } } ] }" - }, - "DateExpression": { - "anyOf": [ - { - "$ref": "#/definitions/AbsoluteDate" }, { - "$ref": "#/definitions/RelativeDate" + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/StringExpression" + }, + "operator": { + "$ref": "#/definitions/StringBoolOperator" + }, + "right": { + "$ref": "#/definitions/StringExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "StringBoolExpression", + "type": "object" }, { "additionalProperties": false, "properties": { - "operand": { - "anyOf": [ - { - "$ref": "#/definitions/AbsoluteDate" - }, - { - "$ref": "#/definitions/RelativeDate" - } - ] + "left": { + "$ref": "#/definitions/DateExpression" }, "operator": { - "$ref": "#/definitions/BinaryOperator" + "$ref": "#/definitions/NumberBoolOperator" + }, + "right": { + "$ref": "#/definitions/DateExpression" } }, "required": [ "operator", - "operand" + "left", + "right" ], + "title": "DateBoolExpression", "type": "object" }, { "additionalProperties": false, "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/DateExpression" - }, - "type": "array" + "left": { + "$ref": "#/definitions/BooleanExpression" }, "operator": { - "$ref": "#/definitions/LogicalOperator" + "$ref": "#/definitions/LogicalBoolOperator" + }, + "right": { + "$ref": "#/definitions/BooleanExpression" } }, "required": [ "operator", - "expressions" + "left", + "right" ], + "title": "LogicalBoolExpression", "type": "object" - } - ], - "description": "Represents an expression that evaluates to a date or date-based condition. Examples: 1. Absolute date: { absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Relative date: { relative: { offset: -30, unit: \"day\" } }\n\n3. Date with binary operator: { operator: \"greater_than\", operand: { absolute: \"2023-01-01T00:00:00Z\" } }\n\n4. Logical combination of dates: { operator: \"and\", expressions: [ { absolute: \"2023-01-01T00:00:00Z\" }, { operator: \"less_than\", operand: { relative: { offset: 0, unit: \"month\", boundary: \"end\" } } } ] }" - }, - "DateOperand": { - "anyOf": [ + }, { "additionalProperties": false, "properties": { - "date": { - "$ref": "#/definitions/AbsoluteDate" + "expressions": { + "items": { + "$ref": "#/definitions/BooleanExpression" + }, + "type": "array" + }, + "operator": { + "$ref": "#/definitions/LogicalBoolOperator" } }, "required": [ - "date" + "operator", + "expressions" ], - "type": "object", - "title": "AbsoluteDateOperand" + "title": "LogicalManyBoolExpression", + "type": "object" }, { "additionalProperties": false, "properties": { - "date": { - "$ref": "#/definitions/RelativeDate" + "left": { + "$ref": "#/definitions/LocationExpression" + }, + "operator": { + "$ref": "#/definitions/LocationBoolOperator" + }, + "right": { + "$ref": "#/definitions/LocationExpression" } }, "required": [ - "date" + "operator", + "left", + "right" ], - "type": "object", - "title": "RelativeDateOperand" + "title": "LocationBooleanExpression", + "type": "object" + } + ], + "title": "BooleanExpression" + }, + "DateExpression": { + "anyOf": [ + { + "$ref": "#/definitions/AbsoluteDate" + }, + { + "$ref": "#/definitions/RelativeDate" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "description": "Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: \"day\" } }\n\n3. Date with binary operator:\n{ operator: \"greater_than\", operand: { absolute: \"2023-01-01T00:00:00Z\" } }\n\n4. Logical combination of dates:\n{\noperator: \"and\",\nexpressions: [\n{ absolute: \"2023-01-01T00:00:00Z\" },\n{ operator: \"less_than\", operand: { relative: { offset: 0, unit: \"month\", boundary: \"end\" } } }\n]\n}", + "title": "BooleanExpression" + }, + "DateLiteral": { + "anyOf": [ + { + "$ref": "#/definitions/AbsoluteDate" + }, + { + "$ref": "#/definitions/RelativeDate" } ], - "description": "Represents a date value that can be either absolute or relative. Examples: 1. Absolute date: { date: { absolute: \"2023-01-01T00:00:00Z\" } }\n\n2. Relative date (30 days ago): { date: { relative: { offset: -30, unit: \"day\" } } }\n\n3. Relative date (start of current month): { date: { relative: { offset: 0, unit: \"month\", boundary: \"start\" } } }" + "title": "DateLiteral" }, "DateUnit": { - "description": "Represents units of time that can be used in relative date calculations. Examples:\n- 'second': 1 second\n- 'minute': 60 seconds\n- 'hour': 60 minutes\n- 'day': 24 hours\n- 'week': 7 days\n- 'month': ~30 days\n- 'quarter': 3 months\n- 'year': 12 months", + "description": "Represents units of time that can be used in relative date calculations.\nExamples:\n- 'second': 1 second\n- 'minute': 60 seconds\n- 'hour': 60 minutes\n- 'day': 24 hours\n- 'week': 7 days\n- 'month': ~30 days\n- 'quarter': 3 months\n- 'year': 12 months", "enum": [ "second", "minute", @@ -214,6 +248,7 @@ "quarter", "year" ], + "title": "DateUnit", "type": "string" }, "DistanceUnit": { @@ -222,72 +257,31 @@ "miles", "kilometers" ], + "title": "DistanceUnit", "type": "string" }, "Expression": { "anyOf": [ { - "additionalProperties": false, - "properties": { - "operand": { - "$ref": "#/definitions/Operand" - }, - "operator": { - "$ref": "#/definitions/UnaryOperator" - } - }, - "required": [ - "operator", - "operand" - ], - "type": "object", - "title": "UnaryExpression" + "$ref": "#/definitions/BooleanExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/Operand" - }, - "operator": { - "$ref": "#/definitions/BinaryOperator" - }, - "right": { - "$ref": "#/definitions/Operand" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "type": "object", - "title": "BinaryExpression" + "$ref": "#/definitions/DateExpression" }, { - "additionalProperties": false, - "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/Expression" - }, - "type": "array" - }, - "operator": { - "$ref": "#/definitions/LogicalOperator" - } - }, - "required": [ - "operator", - "expressions" - ], - "type": "object", - "title": "LogicalExpression" + "$ref": "#/definitions/NumberExpression" + }, + { + "$ref": "#/definitions/LocationExpression" + }, + { + "$ref": "#/definitions/ModelPath" } ], - "description": "Represents a complex expression that can evaluate to true, false, or noop. Examples: 1. Join expression (combining expressions from different models): { \"model\": \"user\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"age\" }, \"right\": 18 } }\n\n2. Logical expression (AND): { \"operator\": \"and\", \"expressions\": [ { \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" }, { \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 } ] }\n\n3. Location expression: { \"operator\": \"within\", \"left\": { \"location\": { \"latitude\": 37.7749, \"longitude\": -122.4194, \"distance\": { \"value\": 10, \"unit\": \"miles\" } } }, \"right\": { \"model\": \"user\", \"path\": \"location\" } }" + "description": "Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n\"model\": \"user\",\n\"expression\": {\n\"operator\": \"equals\",\n\"left\": { \"path\": \"age\" },\n\"right\": 18\n}\n}\n\n2. Logical expression (AND):\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" },\n{ \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 }\n]\n}\n\n3. Location expression:\n{\n\"operator\": \"within\",\n\"left\": { \"location\": { \"latitude\": 37.7749, \"longitude\": -122.4194, \"distance\": { \"value\": 10, \"unit\": \"miles\" } } },\n\"right\": { \"model\": \"user\", \"path\": \"location\" }\n}", + "title": "Expression" }, - "ListOperator": { + "ListBoolOperator": { "description": "Represents operators that work with lists of values. Examples:\n- \"contains\": { list: [1, 2, 3], value: 2 }\n- \"between\": { list: [1, 10], value: 5 }\n- \"match_any\": { list: [\"a\", \"b\"], value: \"a\" }\n- \"in\": { list: [1, 2, 3], value: 2 }", "enum": [ "contains", @@ -298,9 +292,33 @@ ], "type": "string" }, + "Literal": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/DateLiteral" + }, + { + "$ref": "#/definitions/ModelPath" + }, + { + "$ref": "#/definitions/Location" + } + ], + "description": "Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n\"hello\"\n\n2. Path reference:\n{ path: \"user.age\" }\n\n3. Arithmetic operation:\n{\noperator: \"plus\",\nleft: { path: \"price\" },\nright: { path: \"tax\" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: \"multiply\",\nleft: { operator: \"plus\", left: { path: \"base_price\" }, right: { path: \"shipping\" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: \"2023-01-01T00:00:00Z\" } }", + "title": "Literal" + }, "Location": { "additionalProperties": false, - "description": "Represents a geographic location, optionally with a distance constraint. Examples: 1. Simple location: { \"latitude\": 37.7749, \"longitude\": -122.4194 }\n\n2. Location with distance in miles: { \"latitude\": 40.7128, \"longitude\": -74.0060, \"distance\": { \"value\": 10, \"unit\": \"miles\" } }\n\n3. Location with distance in kilometers: { \"latitude\": 51.5074, \"longitude\": -0.1278, \"distance\": { \"value\": 5, \"unit\": \"kilometers\" } }", + "description": "Represents a geographic location, optionally with a distance constraint.\nExamples:\n1. Simple location:\n{ \"latitude\": 37.7749, \"longitude\": -122.4194 }\n\n2. Location with distance in miles:\n{ \"latitude\": 40.7128, \"longitude\": -74.0060, \"distance\": { \"value\": 10, \"unit\": \"miles\" } }\n\n3. Location with distance in kilometers:\n{ \"latitude\": 51.5074, \"longitude\": -0.1278, \"distance\": { \"value\": 5, \"unit\": \"kilometers\" } }", "properties": { "distance": { "additionalProperties": false, @@ -329,73 +347,30 @@ "latitude", "longitude" ], + "title": "Location", "type": "object" }, + "LocationBoolOperator": { + "description": "Represents operators for location-based comparisons. Examples:\n- \"within\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 }\n- \"equals\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } }", + "enum": [ + "within", + "equals" + ], + "type": "string" + }, "LocationExpression": { "anyOf": [ { "$ref": "#/definitions/Location" }, { - "additionalProperties": false, - "properties": { - "operand": { - "$ref": "#/definitions/Location" - }, - "operator": { - "$ref": "#/definitions/LocationOperator" - } - }, - "required": [ - "operator", - "operand" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/LocationExpression" - }, - "type": "array" - }, - "operator": { - "$ref": "#/definitions/LogicalOperator" - } - }, - "required": [ - "operator", - "expressions" - ], - "type": "object" - } - ], - "description": "Represents an expression that evaluates to a location or location-based condition. Examples: 1. Simple location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }\n\n2. Location with operator: { operator: \"within\", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Logical combination of locations: { operator: \"or\", expressions: [ { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }, { operator: \"within\", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: \"miles\" } } } ] }" - }, - "LocationOperand": { - "additionalProperties": false, - "description": "Represents a location value that can be used in location-based expressions. Examples: 1. Simple location (latitude/longitude only): { location: { latitude: 40.7128, longitude: -74.0060 } }\n\n2. Location with distance in miles: { location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Location with distance in meters: { location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 1000, unit: \"meters\" } } }", - "properties": { - "location": { - "$ref": "#/definitions/Location" + "$ref": "#/definitions/ModelPath" } - }, - "required": [ - "location" - ], - "type": "object" - }, - "LocationOperator": { - "description": "Represents operators for location-based comparisons. Examples:\n- \"within\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 }\n- \"equals\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } }", - "enum": [ - "within", - "equals" ], - "type": "string" + "description": "Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }\n\n2. Location with operator:\n{ operator: \"within\", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Logical combination of locations:\n{\noperator: \"or\",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } },\n{ operator: \"within\", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: \"miles\" } } }\n]\n}", + "title": "LocationExpression" }, - "LogicalOperator": { + "LogicalBoolOperator": { "description": "Represents logical operators for combining multiple conditions. Examples:\n- \"and\": { condition1: true, condition2: true } // result: true\n- \"or\": { condition1: true, condition2: false } // result: true", "enum": [ "and", @@ -405,7 +380,7 @@ }, "ModelPath": { "additionalProperties": false, - "description": "Represents a model path reference within a data model. Examples: 1. Simple model path: { \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path: { \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path: { \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", + "description": "Represents a model path reference within a data model.\nExamples:\n1. Simple model path:\n{ \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path:\n{ \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path:\n{ \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", "properties": { "model": { "type": "string" @@ -418,106 +393,81 @@ "model", "path" ], + "title": "ModelPath", "type": "object" }, - "Operand": { + "NumberBoolOperator": { + "description": "Represents binary operators that compare two values. Examples:\n- \"equals\": { value1: 5, value2: 5 }\n- \"less_than\": { value1: 3, value2: 5 }\n- \"matches\": { value1: \"pattern\", value2: \"text\" }\n- \"contains\": { value1: \"string\", value2: \"substring\" }", + "enum": [ + "equals", + "not_equals", + "less_than", + "less_than_equal", + "greater_than", + "greater_than_equal" + ], + "type": "string" + }, + "NumberExpression": { "anyOf": [ - { - "type": "boolean" - }, { "type": "number" }, - { - "type": "string" - }, - { - "$ref": "#/definitions/DateOperand" - }, { "$ref": "#/definitions/ModelPath" }, { "additionalProperties": false, "properties": { - "condition": { - "$ref": "#/definitions/Expression" - }, - "group_by_model": { - "type": "string" - }, - "operand": { - "$ref": "#/definitions/Operand" + "left": { + "$ref": "#/definitions/NumberExpression" }, "operator": { - "$ref": "#/definitions/AggregationOperator" - } - }, - "required": [ - "operator", - "group_by_model", - "operand" - ], - "type": "object", - "title": "ModelAggregationOperand" - } - ], - "description": "Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations. Examples: 1. Primitive values: true 42 \"hello\"\n\n2. Path reference: { path: \"user.age\" }\n\n3. Arithmetic operation: { operator: \"plus\", left: { path: \"price\" }, right: { path: \"tax\" } }\n\n4. Nested arithmetic operation: { operator: \"multiply\", left: { operator: \"plus\", left: { path: \"base_price\" }, right: { path: \"shipping\" } }, right: 1.1 }\n\n5. Date operand: { date: { absolute: \"2023-01-01T00:00:00Z\" } }" - }, - "PathExpression": { - "anyOf": [ - { - "type": "boolean", - "title": "BooleanPathExpression" - }, - { - "type": "number", - "title": "NumberPathExpression" - }, - { - "type": "string", - "title": "StringPathExpression" - }, - { - "additionalProperties": false, - "properties": { - "expression": { - "$ref": "#/definitions/PathExpression" + "$ref": "#/definitions/BinaryNumberOperator" }, - "operator": { - "$ref": "#/definitions/UnaryOperator" + "right": { + "$ref": "#/definitions/NumberExpression" } }, "required": [ "operator", - "expression" + "left", + "right" ], - "type": "object", - "title": "UnaryPathExpression" + "title": "BinaryNumberExpression", + "type": "object" }, { "additionalProperties": false, "properties": { + "condition": { + "$ref": "#/definitions/BooleanExpression" + }, + "group_by_model": { + "type": "string" + }, "operand": { - "$ref": "#/definitions/Operand" + "$ref": "#/definitions/NumberExpression" }, "operator": { - "$ref": "#/definitions/BinaryOperator" + "$ref": "#/definitions/AggregationNumberOperator" } }, "required": [ "operator", + "group_by_model", "operand" ], - "type": "object", - "title": "BinaryPathExpression" + "title": "AggregateNumberExpression", + "type": "object" } ], - "description": "Represents an expression that evaluates to a path or value. Examples: 1. Primitive values: true 42 \"hello\"\n\n2. Unary expression (NOT): { operator: \"not\", expression: { operator: \"equals\", operand: { path: \"status\" } } }\n\n3. Binary expression (comparing a path to a value): { operator: \"equals\", operand: { path: \"user.age\" } }" + "description": "Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n\n3. Logical group of count expressions:\n{\noperator: \"and\",\nexpressions: [\n1,\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n]\n}", + "title": "NumberExpression" }, "RelativeDate": { "additionalProperties": false, - "description": "Represents a date/time relative to the current time. Examples: 1. 7 days ago: { relative: { offset: -7, unit: \"day\" } }\n\n2. Start of current month: { relative: { offset: 0, unit: \"month\", boundary: \"start\" } }\n\n3. End of previous quarter: { relative: { offset: -1, unit: \"quarter\", boundary: \"end\" } }", + "description": "Represents a date/time relative to the current time.\nExamples:\n1. 7 days ago:\n{ relative: { offset: -7, unit: \"day\" } }\n\n2. Start of current month:\n{ relative: { offset: 0, unit: \"month\", boundary: \"start\" } }\n\n3. End of previous quarter:\n{ relative: { offset: -1, unit: \"quarter\", boundary: \"end\" } }", "properties": { "relative": { "additionalProperties": false, @@ -546,9 +496,35 @@ "required": [ "relative" ], + "title": "RelativeDate", "type": "object" }, - "UnaryOperator": { + "StringBoolOperator": { + "enum": [ + "equals", + "not_equals", + "matches", + "contains", + "not_contains", + "starts_with", + "not_starts_with", + "ends_with", + "not_ends_with" + ], + "type": "string" + }, + "StringExpression": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "StringExpression" + }, + "UnaryBoolOperator": { "description": "Represents unary operators that operate on a single value. Examples:\n- \"not\": Negates a boolean expression\n- \"exist\": Checks if a value exists", "enum": [ "null", @@ -582,4 +558,4 @@ "type": "object" } } -} +} \ No newline at end of file diff --git a/sdk/typescript-schema/audience.ts b/sdk/typescript-schema/audience.ts index 583a7db..5aee5c2 100644 --- a/sdk/typescript-schema/audience.ts +++ b/sdk/typescript-schema/audience.ts @@ -1,9 +1,8 @@ import { Version } from "./common/version"; -import { Expression } from "./expression/expression"; +import { BooleanExpression } from "./expression/boolean-expression"; /** - * @title AudienceDefinition - * @description Represents a logical combination of audience expressions using AND/OR operators. + * Represents a logical combination of audience expressions using AND/OR operators. * Examples: * 1. Simple AND combination: * { @@ -46,7 +45,8 @@ import { Expression } from "./expression/expression"; */ /** - * Represents a complete audience definition with a root logical expression. + * @title AudienceDefinition + * @description Represents a complete audience definition with a root logical expression. * Examples: * 1. Simple audience: * { @@ -78,10 +78,10 @@ import { Expression } from "./expression/expression"; * } * } */ -export interface Audience { +export type Audience = { schema_version: Version, /** * @title Audience */ - audience: Expression + audience: BooleanExpression } diff --git a/sdk/typescript-schema/schema/audience-schema.json b/sdk/typescript-schema/schema/audience-schema.json index 14ecc6d..363ed22 100644 --- a/sdk/typescript-schema/schema/audience-schema.json +++ b/sdk/typescript-schema/schema/audience-schema.json @@ -3,7 +3,7 @@ "definitions": { "AbsoluteDate": { "additionalProperties": false, - "description": "Represents an absolute date/time value. Examples: 1. ISO 8601 date: { absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Date only: { absolute: \"2023-01-01\" }\n\n3. Date with timezone: { absolute: \"2023-01-01T00:00:00-05:00\" }", + "description": "Represents an absolute date/time value.\nExamples:\n1. ISO 8601 date:\n{ absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Date only:\n{ absolute: \"2023-01-01\" }\n\n3. Date with timezone:\n{ absolute: \"2023-01-01T00:00:00-05:00\" }", "properties": { "absolute": { "type": "string" @@ -12,9 +12,10 @@ "required": [ "absolute" ], + "title": "AbsoluteDate", "type": "object" }, - "AggregationOperator": { + "AggregationNumberOperator": { "description": "Represents operators for aggregating multiple values. Examples:\n- \"min\": [1, 2, 3] // result: 1\n- \"max\": [1, 2, 3] // result: 3\n- \"avg\": [1, 2, 3] // result: 2\n- \"count\": [1, 2, 3] // result: 3", "enum": [ "min", @@ -26,23 +27,12 @@ ], "type": "string" }, - "ArithmeticOperator": { - "description": "Represents mathematical operators for numeric calculations. Examples:\n- \"plus\": { value1: 5, value2: 3 } // result: 8\n- \"multiply\": { value1: 4, value2: 2 } // result: 8\n- \"mod\": { value1: 10, value2: 3 } // result: 1", - "enum": [ - "plus", - "minus", - "multiply", - "divide", - "mod" - ], - "type": "string" - }, "Audience": { "additionalProperties": false, - "description": "Represents a complete audience definition with a root logical expression. Examples: 1. Simple audience: { \"schema_version\": \"1.0.0\", \"audience\": { \"operator\": \"and\", \"expressions\": [ { \"model\": \"user\", \"expression\": { \"operator\": \"exists\", \"operand\": { \"path\": \"id\" } } }, { \"model\": \"purchase\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } } ] } }\n\n2. Audience with nested logic: { \"schema_version\": \"1.0.0\", \"audience\": { \"operator\": \"or\", \"expressions\": [ { \"model\": \"user\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" } }, { \"operator\": \"and\", \"expressions\": [ { \"model\": \"signup\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } }, { \"model\": \"user\", \"expression\": { \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 } } ] } ] } }", + "description": "Represents a complete audience definition with a root logical expression.\nExamples:\n1. Simple audience:\n{\n\"schema_version\": \"1.0.0\",\n\"audience\": {\n\"operator\": \"and\",\n\"expressions\": [\n{ \"model\": \"user\", \"expression\": { \"operator\": \"exists\", \"operand\": { \"path\": \"id\" } } },\n{ \"model\": \"purchase\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } }\n]\n}\n}\n\n2. Audience with nested logic:\n{\n\"schema_version\": \"1.0.0\",\n\"audience\": {\n\"operator\": \"or\",\n\"expressions\": [\n{ \"model\": \"user\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" } },\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"model\": \"signup\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } },\n{ \"model\": \"user\", \"expression\": { \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 } }\n]\n}\n]\n}\n}", "properties": { "audience": { - "$ref": "#/definitions/Expression", + "$ref": "#/definitions/BooleanExpression", "title": "Audience" }, "schema_version": { @@ -53,157 +43,201 @@ "schema_version", "audience" ], - "type": "object", - "title": "AudienceDefinition" + "title": "AudienceDefinition", + "type": "object" }, - "BinaryOperator": { - "description": "Represents binary operators that compare two values. Examples:\n- \"equals\": { value1: 5, value2: 5 }\n- \"less_than\": { value1: 3, value2: 5 }\n- \"matches\": { value1: \"pattern\", value2: \"text\" }\n- \"contains\": { value1: \"string\", value2: \"substring\" }", + "BinaryNumberOperator": { + "description": "Represents mathematical operators for numeric calculations. Examples:\n- \"plus\": { value1: 5, value2: 3 } // result: 8\n- \"multiply\": { value1: 4, value2: 2 } // result: 8\n- \"mod\": { value1: 10, value2: 3 } // result: 1", "enum": [ - "equals", - "not_equals", - "less_than", - "less_than_equal", - "greater_than", - "greater_than_equal", - "matches", - "contains", - "not_contains", - "starts_with", - "not_starts_with", - "ends_with", - "not_ends_with" + "plus", + "minus", + "multiply", + "divide", + "mod" ], "type": "string" }, - "CountExpression": { + "BooleanExpression": { "anyOf": [ { - "type": "number" + "type": "boolean" + }, + { + "$ref": "#/definitions/ModelPath" }, { "additionalProperties": false, "properties": { "operand": { - "$ref": "#/definitions/Operand" + "$ref": "#/definitions/Expression" }, "operator": { - "$ref": "#/definitions/BinaryOperator" + "$ref": "#/definitions/UnaryBoolOperator" } }, "required": [ "operator", "operand" ], + "title": "UnaryBoolExpression", "type": "object" }, { "additionalProperties": false, "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/CountExpression" - }, - "type": "array" + "left": { + "$ref": "#/definitions/NumberExpression" }, "operator": { - "$ref": "#/definitions/LogicalOperator" + "$ref": "#/definitions/NumberBoolOperator" + }, + "right": { + "$ref": "#/definitions/NumberExpression" } }, "required": [ "operator", - "expressions" + "left", + "right" ], + "title": "NumberBoolExpression", "type": "object" - } - ], - "description": "Represents a count expression, which can be a number, a binary operation, or a logical group. Examples: 1. Simple count: 5\n\n2. Binary count expression: { operator: \"greater_than\", operand: { path: \"event.count\" } }\n\n3. Logical group of count expressions: { operator: \"and\", expressions: [ 1, { operator: \"greater_than\", operand: { path: \"event.count\" } } ] }" - }, - "DateExpression": { - "anyOf": [ - { - "$ref": "#/definitions/AbsoluteDate" }, { - "$ref": "#/definitions/RelativeDate" + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/StringExpression" + }, + "operator": { + "$ref": "#/definitions/StringBoolOperator" + }, + "right": { + "$ref": "#/definitions/StringExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "StringBoolExpression", + "type": "object" }, { "additionalProperties": false, "properties": { - "operand": { - "anyOf": [ - { - "$ref": "#/definitions/AbsoluteDate" - }, - { - "$ref": "#/definitions/RelativeDate" - } - ] + "left": { + "$ref": "#/definitions/DateExpression" }, "operator": { - "$ref": "#/definitions/BinaryOperator" + "$ref": "#/definitions/NumberBoolOperator" + }, + "right": { + "$ref": "#/definitions/DateExpression" } }, "required": [ "operator", - "operand" + "left", + "right" ], + "title": "DateBoolExpression", "type": "object" }, { "additionalProperties": false, "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/DateExpression" - }, - "type": "array" + "left": { + "$ref": "#/definitions/BooleanExpression" }, "operator": { - "$ref": "#/definitions/LogicalOperator" + "$ref": "#/definitions/LogicalBoolOperator" + }, + "right": { + "$ref": "#/definitions/BooleanExpression" } }, "required": [ "operator", - "expressions" + "left", + "right" ], + "title": "LogicalBoolExpression", "type": "object" - } - ], - "description": "Represents an expression that evaluates to a date or date-based condition. Examples: 1. Absolute date: { absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Relative date: { relative: { offset: -30, unit: \"day\" } }\n\n3. Date with binary operator: { operator: \"greater_than\", operand: { absolute: \"2023-01-01T00:00:00Z\" } }\n\n4. Logical combination of dates: { operator: \"and\", expressions: [ { absolute: \"2023-01-01T00:00:00Z\" }, { operator: \"less_than\", operand: { relative: { offset: 0, unit: \"month\", boundary: \"end\" } } } ] }" - }, - "DateOperand": { - "anyOf": [ + }, { "additionalProperties": false, "properties": { - "date": { - "$ref": "#/definitions/AbsoluteDate" + "expressions": { + "items": { + "$ref": "#/definitions/BooleanExpression" + }, + "type": "array" + }, + "operator": { + "$ref": "#/definitions/LogicalBoolOperator" } }, "required": [ - "date" + "operator", + "expressions" ], - "type": "object", - "title": "AbsoluteDateOperand" + "title": "LogicalManyBoolExpression", + "type": "object" }, { "additionalProperties": false, "properties": { - "date": { - "$ref": "#/definitions/RelativeDate" + "left": { + "$ref": "#/definitions/LocationExpression" + }, + "operator": { + "$ref": "#/definitions/LocationBoolOperator" + }, + "right": { + "$ref": "#/definitions/LocationExpression" } }, "required": [ - "date" + "operator", + "left", + "right" ], - "type": "object", - "title": "RelativeDateOperand" + "title": "LocationBooleanExpression", + "type": "object" + } + ], + "title": "BooleanExpression" + }, + "DateExpression": { + "anyOf": [ + { + "$ref": "#/definitions/AbsoluteDate" + }, + { + "$ref": "#/definitions/RelativeDate" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "description": "Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: \"day\" } }\n\n3. Date with binary operator:\n{ operator: \"greater_than\", operand: { absolute: \"2023-01-01T00:00:00Z\" } }\n\n4. Logical combination of dates:\n{\noperator: \"and\",\nexpressions: [\n{ absolute: \"2023-01-01T00:00:00Z\" },\n{ operator: \"less_than\", operand: { relative: { offset: 0, unit: \"month\", boundary: \"end\" } } }\n]\n}", + "title": "BooleanExpression" + }, + "DateLiteral": { + "anyOf": [ + { + "$ref": "#/definitions/AbsoluteDate" + }, + { + "$ref": "#/definitions/RelativeDate" } ], - "description": "Represents a date value that can be either absolute or relative. Examples: 1. Absolute date: { date: { absolute: \"2023-01-01T00:00:00Z\" } }\n\n2. Relative date (30 days ago): { date: { relative: { offset: -30, unit: \"day\" } } }\n\n3. Relative date (start of current month): { date: { relative: { offset: 0, unit: \"month\", boundary: \"start\" } } }" + "title": "DateLiteral" }, "DateUnit": { - "description": "Represents units of time that can be used in relative date calculations. Examples:\n- 'second': 1 second\n- 'minute': 60 seconds\n- 'hour': 60 minutes\n- 'day': 24 hours\n- 'week': 7 days\n- 'month': ~30 days\n- 'quarter': 3 months\n- 'year': 12 months", + "description": "Represents units of time that can be used in relative date calculations.\nExamples:\n- 'second': 1 second\n- 'minute': 60 seconds\n- 'hour': 60 minutes\n- 'day': 24 hours\n- 'week': 7 days\n- 'month': ~30 days\n- 'quarter': 3 months\n- 'year': 12 months", "enum": [ "second", "minute", @@ -214,6 +248,7 @@ "quarter", "year" ], + "title": "DateUnit", "type": "string" }, "DistanceUnit": { @@ -222,72 +257,31 @@ "miles", "kilometers" ], + "title": "DistanceUnit", "type": "string" }, "Expression": { "anyOf": [ { - "additionalProperties": false, - "properties": { - "operand": { - "$ref": "#/definitions/Operand" - }, - "operator": { - "$ref": "#/definitions/UnaryOperator" - } - }, - "required": [ - "operator", - "operand" - ], - "type": "object", - "title": "UnaryExpression" + "$ref": "#/definitions/BooleanExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/Operand" - }, - "operator": { - "$ref": "#/definitions/BinaryOperator" - }, - "right": { - "$ref": "#/definitions/Operand" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "type": "object", - "title": "BinaryExpression" + "$ref": "#/definitions/DateExpression" }, { - "additionalProperties": false, - "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/Expression" - }, - "type": "array" - }, - "operator": { - "$ref": "#/definitions/LogicalOperator" - } - }, - "required": [ - "operator", - "expressions" - ], - "type": "object", - "title": "LogicalExpression" + "$ref": "#/definitions/NumberExpression" + }, + { + "$ref": "#/definitions/LocationExpression" + }, + { + "$ref": "#/definitions/ModelPath" } ], - "description": "Represents a complex expression that can evaluate to true, false, or noop. Examples: 1. Join expression (combining expressions from different models): { \"model\": \"user\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"age\" }, \"right\": 18 } }\n\n2. Logical expression (AND): { \"operator\": \"and\", \"expressions\": [ { \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" }, { \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 } ] }\n\n3. Location expression: { \"operator\": \"within\", \"left\": { \"location\": { \"latitude\": 37.7749, \"longitude\": -122.4194, \"distance\": { \"value\": 10, \"unit\": \"miles\" } } }, \"right\": { \"model\": \"user\", \"path\": \"location\" } }" + "description": "Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n\"model\": \"user\",\n\"expression\": {\n\"operator\": \"equals\",\n\"left\": { \"path\": \"age\" },\n\"right\": 18\n}\n}\n\n2. Logical expression (AND):\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" },\n{ \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 }\n]\n}\n\n3. Location expression:\n{\n\"operator\": \"within\",\n\"left\": { \"location\": { \"latitude\": 37.7749, \"longitude\": -122.4194, \"distance\": { \"value\": 10, \"unit\": \"miles\" } } },\n\"right\": { \"model\": \"user\", \"path\": \"location\" }\n}", + "title": "Expression" }, - "ListOperator": { + "ListBoolOperator": { "description": "Represents operators that work with lists of values. Examples:\n- \"contains\": { list: [1, 2, 3], value: 2 }\n- \"between\": { list: [1, 10], value: 5 }\n- \"match_any\": { list: [\"a\", \"b\"], value: \"a\" }\n- \"in\": { list: [1, 2, 3], value: 2 }", "enum": [ "contains", @@ -298,9 +292,33 @@ ], "type": "string" }, + "Literal": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/DateLiteral" + }, + { + "$ref": "#/definitions/ModelPath" + }, + { + "$ref": "#/definitions/Location" + } + ], + "description": "Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n\"hello\"\n\n2. Path reference:\n{ path: \"user.age\" }\n\n3. Arithmetic operation:\n{\noperator: \"plus\",\nleft: { path: \"price\" },\nright: { path: \"tax\" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: \"multiply\",\nleft: { operator: \"plus\", left: { path: \"base_price\" }, right: { path: \"shipping\" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: \"2023-01-01T00:00:00Z\" } }", + "title": "Literal" + }, "Location": { "additionalProperties": false, - "description": "Represents a geographic location, optionally with a distance constraint. Examples: 1. Simple location: { \"latitude\": 37.7749, \"longitude\": -122.4194 }\n\n2. Location with distance in miles: { \"latitude\": 40.7128, \"longitude\": -74.0060, \"distance\": { \"value\": 10, \"unit\": \"miles\" } }\n\n3. Location with distance in kilometers: { \"latitude\": 51.5074, \"longitude\": -0.1278, \"distance\": { \"value\": 5, \"unit\": \"kilometers\" } }", + "description": "Represents a geographic location, optionally with a distance constraint.\nExamples:\n1. Simple location:\n{ \"latitude\": 37.7749, \"longitude\": -122.4194 }\n\n2. Location with distance in miles:\n{ \"latitude\": 40.7128, \"longitude\": -74.0060, \"distance\": { \"value\": 10, \"unit\": \"miles\" } }\n\n3. Location with distance in kilometers:\n{ \"latitude\": 51.5074, \"longitude\": -0.1278, \"distance\": { \"value\": 5, \"unit\": \"kilometers\" } }", "properties": { "distance": { "additionalProperties": false, @@ -329,73 +347,30 @@ "latitude", "longitude" ], + "title": "Location", "type": "object" }, + "LocationBoolOperator": { + "description": "Represents operators for location-based comparisons. Examples:\n- \"within\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 }\n- \"equals\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } }", + "enum": [ + "within", + "equals" + ], + "type": "string" + }, "LocationExpression": { "anyOf": [ { "$ref": "#/definitions/Location" }, { - "additionalProperties": false, - "properties": { - "operand": { - "$ref": "#/definitions/Location" - }, - "operator": { - "$ref": "#/definitions/LocationOperator" - } - }, - "required": [ - "operator", - "operand" - ], - "type": "object" - }, - { - "additionalProperties": false, - "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/LocationExpression" - }, - "type": "array" - }, - "operator": { - "$ref": "#/definitions/LogicalOperator" - } - }, - "required": [ - "operator", - "expressions" - ], - "type": "object" - } - ], - "description": "Represents an expression that evaluates to a location or location-based condition. Examples: 1. Simple location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }\n\n2. Location with operator: { operator: \"within\", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Logical combination of locations: { operator: \"or\", expressions: [ { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }, { operator: \"within\", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: \"miles\" } } } ] }" - }, - "LocationOperand": { - "additionalProperties": false, - "description": "Represents a location value that can be used in location-based expressions. Examples: 1. Simple location (latitude/longitude only): { location: { latitude: 40.7128, longitude: -74.0060 } }\n\n2. Location with distance in miles: { location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Location with distance in meters: { location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 1000, unit: \"meters\" } } }", - "properties": { - "location": { - "$ref": "#/definitions/Location" + "$ref": "#/definitions/ModelPath" } - }, - "required": [ - "location" - ], - "type": "object" - }, - "LocationOperator": { - "description": "Represents operators for location-based comparisons. Examples:\n- \"within\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 }\n- \"equals\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } }", - "enum": [ - "within", - "equals" ], - "type": "string" + "description": "Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }\n\n2. Location with operator:\n{ operator: \"within\", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Logical combination of locations:\n{\noperator: \"or\",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } },\n{ operator: \"within\", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: \"miles\" } } }\n]\n}", + "title": "LocationExpression" }, - "LogicalOperator": { + "LogicalBoolOperator": { "description": "Represents logical operators for combining multiple conditions. Examples:\n- \"and\": { condition1: true, condition2: true } // result: true\n- \"or\": { condition1: true, condition2: false } // result: true", "enum": [ "and", @@ -405,7 +380,7 @@ }, "ModelPath": { "additionalProperties": false, - "description": "Represents a model path reference within a data model. Examples: 1. Simple model path: { \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path: { \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path: { \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", + "description": "Represents a model path reference within a data model.\nExamples:\n1. Simple model path:\n{ \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path:\n{ \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path:\n{ \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", "properties": { "model": { "type": "string" @@ -418,106 +393,81 @@ "model", "path" ], + "title": "ModelPath", "type": "object" }, - "Operand": { + "NumberBoolOperator": { + "description": "Represents binary operators that compare two values. Examples:\n- \"equals\": { value1: 5, value2: 5 }\n- \"less_than\": { value1: 3, value2: 5 }\n- \"matches\": { value1: \"pattern\", value2: \"text\" }\n- \"contains\": { value1: \"string\", value2: \"substring\" }", + "enum": [ + "equals", + "not_equals", + "less_than", + "less_than_equal", + "greater_than", + "greater_than_equal" + ], + "type": "string" + }, + "NumberExpression": { "anyOf": [ - { - "type": "boolean" - }, { "type": "number" }, - { - "type": "string" - }, - { - "$ref": "#/definitions/DateOperand" - }, { "$ref": "#/definitions/ModelPath" }, { "additionalProperties": false, "properties": { - "condition": { - "$ref": "#/definitions/Expression" - }, - "group_by_model": { - "type": "string" - }, - "operand": { - "$ref": "#/definitions/Operand" + "left": { + "$ref": "#/definitions/NumberExpression" }, "operator": { - "$ref": "#/definitions/AggregationOperator" - } - }, - "required": [ - "operator", - "group_by_model", - "operand" - ], - "type": "object", - "title": "ModelAggregationOperand" - } - ], - "description": "Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations. Examples: 1. Primitive values: true 42 \"hello\"\n\n2. Path reference: { path: \"user.age\" }\n\n3. Arithmetic operation: { operator: \"plus\", left: { path: \"price\" }, right: { path: \"tax\" } }\n\n4. Nested arithmetic operation: { operator: \"multiply\", left: { operator: \"plus\", left: { path: \"base_price\" }, right: { path: \"shipping\" } }, right: 1.1 }\n\n5. Date operand: { date: { absolute: \"2023-01-01T00:00:00Z\" } }" - }, - "PathExpression": { - "anyOf": [ - { - "type": "boolean", - "title": "BooleanPathExpression" - }, - { - "type": "number", - "title": "NumberPathExpression" - }, - { - "type": "string", - "title": "StringPathExpression" - }, - { - "additionalProperties": false, - "properties": { - "expression": { - "$ref": "#/definitions/PathExpression" + "$ref": "#/definitions/BinaryNumberOperator" }, - "operator": { - "$ref": "#/definitions/UnaryOperator" + "right": { + "$ref": "#/definitions/NumberExpression" } }, "required": [ "operator", - "expression" + "left", + "right" ], - "type": "object", - "title": "UnaryPathExpression" + "title": "BinaryNumberExpression", + "type": "object" }, { "additionalProperties": false, "properties": { + "condition": { + "$ref": "#/definitions/BooleanExpression" + }, + "group_by_model": { + "type": "string" + }, "operand": { - "$ref": "#/definitions/Operand" + "$ref": "#/definitions/NumberExpression" }, "operator": { - "$ref": "#/definitions/BinaryOperator" + "$ref": "#/definitions/AggregationNumberOperator" } }, "required": [ "operator", + "group_by_model", "operand" ], - "type": "object", - "title": "BinaryPathExpression" + "title": "AggregateNumberExpression", + "type": "object" } ], - "description": "Represents an expression that evaluates to a path or value. Examples: 1. Primitive values: true 42 \"hello\"\n\n2. Unary expression (NOT): { operator: \"not\", expression: { operator: \"equals\", operand: { path: \"status\" } } }\n\n3. Binary expression (comparing a path to a value): { operator: \"equals\", operand: { path: \"user.age\" } }" + "description": "Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n\n3. Logical group of count expressions:\n{\noperator: \"and\",\nexpressions: [\n1,\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n]\n}", + "title": "NumberExpression" }, "RelativeDate": { "additionalProperties": false, - "description": "Represents a date/time relative to the current time. Examples: 1. 7 days ago: { relative: { offset: -7, unit: \"day\" } }\n\n2. Start of current month: { relative: { offset: 0, unit: \"month\", boundary: \"start\" } }\n\n3. End of previous quarter: { relative: { offset: -1, unit: \"quarter\", boundary: \"end\" } }", + "description": "Represents a date/time relative to the current time.\nExamples:\n1. 7 days ago:\n{ relative: { offset: -7, unit: \"day\" } }\n\n2. Start of current month:\n{ relative: { offset: 0, unit: \"month\", boundary: \"start\" } }\n\n3. End of previous quarter:\n{ relative: { offset: -1, unit: \"quarter\", boundary: \"end\" } }", "properties": { "relative": { "additionalProperties": false, @@ -546,9 +496,35 @@ "required": [ "relative" ], + "title": "RelativeDate", "type": "object" }, - "UnaryOperator": { + "StringBoolOperator": { + "enum": [ + "equals", + "not_equals", + "matches", + "contains", + "not_contains", + "starts_with", + "not_starts_with", + "ends_with", + "not_ends_with" + ], + "type": "string" + }, + "StringExpression": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "StringExpression" + }, + "UnaryBoolOperator": { "description": "Represents unary operators that operate on a single value. Examples:\n- \"not\": Negates a boolean expression\n- \"exist\": Checks if a value exists", "enum": [ "null", @@ -582,4 +558,4 @@ "type": "object" } } -} +} \ No newline at end of file diff --git a/sdk/typescript-schema/scripts/add_titles_to_schema.sh b/sdk/typescript-schema/scripts/add_titles_to_schema.sh deleted file mode 100755 index 050451e..0000000 --- a/sdk/typescript-schema/scripts/add_titles_to_schema.sh +++ /dev/null @@ -1,67 +0,0 @@ -#!/bin/bash - -# Usage: -# ./add_titles_to_schema.sh [input.json] > output.json - -INPUT_FILE="${1:-schema/audience-schema.json}" - -if [[ ! -f "$INPUT_FILE" ]]; then - echo "Error: File '$INPUT_FILE' not found." >&2 - exit 1 -fi - -# Use global jq -JQ="jq" - -# Define mappings: JSONPath-like path | title -read -r -d '' MAPPINGS < tmp.tsconfig.json && mv tmp.tsconfig.json "$TSCONFIG" echo "Generating JSON schema..." -./node_modules/.bin/ts-json-schema-generator --path index.ts --out schema/audience-schema.tmp.json - -echo "Adding titles to schema..." -./scripts/add_titles_to_schema.sh schema/audience-schema.tmp.json > schema/audience-schema.json +./node_modules/.bin/ts-json-schema-generator --path index.ts --out schema/audience-schema.json cp -f schema/audience-schema.json ../../schema/audience-definition-schema.json -rm -f schema/audience-schema.tmp.json echo "Schema generation complete." From d4f8c34fca2b4ab7358f7532b2bdde928bf056d8 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Thu, 19 Jun 2025 12:37:38 -0700 Subject: [PATCH 06/16] Update models and fix tests --- schema/audience-definition-schema.json | 25 +- .../mp_audience_sdk/models/audience_models.py | 297 +++++++++--------- sdk/python/tests/test_audience_models.py | 97 +++--- .../expression/boolean-expression.ts | 14 +- .../expression/date-expression.ts | 8 +- .../expression/number-expression.ts | 4 +- .../schema/audience-schema.json | 25 +- 7 files changed, 265 insertions(+), 205 deletions(-) diff --git a/schema/audience-definition-schema.json b/schema/audience-definition-schema.json index 363ed22..adff72d 100644 --- a/schema/audience-definition-schema.json +++ b/schema/audience-definition-schema.json @@ -213,10 +213,7 @@ "DateExpression": { "anyOf": [ { - "$ref": "#/definitions/AbsoluteDate" - }, - { - "$ref": "#/definitions/RelativeDate" + "$ref": "#/definitions/DateLiteralExpression" }, { "$ref": "#/definitions/ModelPath" @@ -236,6 +233,26 @@ ], "title": "DateLiteral" }, + "DateLiteralExpression": { + "additionalProperties": false, + "properties": { + "date": { + "anyOf": [ + { + "$ref": "#/definitions/AbsoluteDate" + }, + { + "$ref": "#/definitions/RelativeDate" + } + ] + } + }, + "required": [ + "date" + ], + "title": "DateLiteralExpression", + "type": "object" + }, "DateUnit": { "description": "Represents units of time that can be used in relative date calculations.\nExamples:\n- 'second': 1 second\n- 'minute': 60 seconds\n- 'hour': 60 minutes\n- 'day': 24 hours\n- 'week': 7 days\n- 'month': ~30 days\n- 'quarter': 3 months\n- 'year': 12 months", "enum": [ diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index e12e017..45c850e 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-06-06T18:15:16+00:00 +# timestamp: 2025-06-19T19:18:47+00:00 from __future__ import annotations @@ -21,7 +21,7 @@ class AbsoluteDate(BaseModel): absolute: str -class AggregationOperator(Enum): +class AggregationNumberOperator(Enum): min = "min" max = "max" sum = "sum" @@ -30,7 +30,7 @@ class AggregationOperator(Enum): count = "count" -class ArithmeticOperator(Enum): +class BinaryNumberOperator(Enum): plus = "plus" minus = "minus" multiply = "multiply" @@ -38,29 +38,6 @@ class ArithmeticOperator(Enum): mod = "mod" -class BinaryOperator(Enum): - equals = "equals" - not_equals = "not_equals" - less_than = "less_than" - less_than_equal = "less_than_equal" - greater_than = "greater_than" - greater_than_equal = "greater_than_equal" - matches = "matches" - contains = "contains" - not_contains = "not_contains" - starts_with = "starts_with" - not_starts_with = "not_starts_with" - ends_with = "ends_with" - not_ends_with = "not_ends_with" - - -class AbsoluteDateOperand(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - date: AbsoluteDate - - class DateUnit(Enum): second = "second" minute = "minute" @@ -78,7 +55,7 @@ class DistanceUnit(Enum): kilometers = "kilometers" -class ListOperator(Enum): +class ListBoolOperator(Enum): contains = "contains" between = "between" match_any = "match_any" @@ -103,19 +80,12 @@ class Location(BaseModel): longitude: float -class LocationOperand(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - location: Location - - -class LocationOperator(Enum): +class LocationBoolOperator(Enum): within = "within" equals = "equals" -class LogicalOperator(Enum): +class LogicalBoolOperator(Enum): and_ = "and" or_ = "or" @@ -128,6 +98,15 @@ class ModelPath(BaseModel): path: str +class NumberBoolOperator(Enum): + equals = "equals" + not_equals = "not_equals" + less_than = "less_than" + less_than_equal = "less_than_equal" + greater_than = "greater_than" + greater_than_equal = "greater_than_equal" + + class Boundary(Enum): start = "start" end = "end" @@ -149,7 +128,23 @@ class RelativeDate(BaseModel): relative: Relative -class UnaryOperator(Enum): +class StringBoolOperator(Enum): + equals = "equals" + not_equals = "not_equals" + matches = "matches" + contains = "contains" + not_contains = "not_contains" + starts_with = "starts_with" + not_starts_with = "not_starts_with" + ends_with = "ends_with" + not_ends_with = "not_ends_with" + + +class StringExpression(RootModel[Union[str, ModelPath]]): + root: Union[str, ModelPath] = Field(..., title="StringExpression") + + +class UnaryBoolOperator(Enum): null = "null" not_null = "not_null" exists = "exists" @@ -171,188 +166,202 @@ class IsValidAudienceObject(BaseModel): named_args: Optional[NamedArgs] = Field(None, alias="namedArgs") -class DateExpression1(BaseModel): +class StringBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - operand: Union[AbsoluteDate, RelativeDate] - operator: BinaryOperator + left: StringExpression + operator: StringBoolOperator + right: StringExpression + + +class DateLiteral(RootModel[Union[AbsoluteDate, RelativeDate]]): + root: Union[AbsoluteDate, RelativeDate] = Field(..., title="DateLiteral") -class RelativeDateOperand(BaseModel): +class DateLiteralExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - date: RelativeDate + date: Union[AbsoluteDate, RelativeDate] -class DateOperand(RootModel[Union[AbsoluteDateOperand, RelativeDateOperand]]): - root: Union[AbsoluteDateOperand, RelativeDateOperand] = Field( +class Literal(RootModel[Union[bool, float, str, DateLiteral, ModelPath, Location]]): + root: Union[bool, float, str, DateLiteral, ModelPath, Location] = Field( ..., - description='Represents a date value that can be either absolute or relative. Examples: 1. Absolute date: { date: { absolute: "2023-01-01T00:00:00Z" } }\n\n2. Relative date (30 days ago): { date: { relative: { offset: -30, unit: "day" } } }\n\n3. Relative date (start of current month): { date: { relative: { offset: 0, unit: "month", boundary: "start" } } }', + description='Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n"hello"\n\n2. Path reference:\n{ path: "user.age" }\n\n3. Arithmetic operation:\n{\noperator: "plus",\nleft: { path: "price" },\nright: { path: "tax" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: "multiply",\nleft: { operator: "plus", left: { path: "base_price" }, right: { path: "shipping" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: "2023-01-01T00:00:00Z" } }', + title="Literal", ) -class LocationExpression1(BaseModel): - model_config = ConfigDict( - extra="forbid", +class LocationExpression(RootModel[Union[Location, ModelPath]]): + root: Union[Location, ModelPath] = Field( + ..., + description='Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator:\n{ operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations:\n{\noperator: "or",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } },\n{ operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } }\n]\n}', + title="LocationExpression", ) - operand: Location - operator: LocationOperator -class AudienceDefinition(BaseModel): +class LocationBooleanExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - audience: Expression = Field(..., title="Audience") - schema_version: Version + left: LocationExpression + operator: LocationBoolOperator + right: LocationExpression -class CountExpression1(BaseModel): - model_config = ConfigDict( - extra="forbid", +class DateExpression(RootModel[Union[DateLiteralExpression, ModelPath]]): + root: Union[DateLiteralExpression, ModelPath] = Field( + ..., + description='Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator:\n{ operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates:\n{\noperator: "and",\nexpressions: [\n{ absolute: "2023-01-01T00:00:00Z" },\n{ operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } }\n]\n}', + title="BooleanExpression", ) - operand: Operand - operator: BinaryOperator -class CountExpression2(BaseModel): +class DateBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - expressions: List[CountExpression] - operator: LogicalOperator + left: DateExpression + operator: NumberBoolOperator + right: DateExpression -class CountExpression(RootModel[Union[float, CountExpression1, CountExpression2]]): - root: Union[float, CountExpression1, CountExpression2] = Field( - ..., - description='Represents a count expression, which can be a number, a binary operation, or a logical group. Examples: 1. Simple count: 5\n\n2. Binary count expression: { operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions: { operator: "and", expressions: [ 1, { operator: "greater_than", operand: { path: "event.count" } } ] }', - ) - - -class DateExpression2(BaseModel): +class AudienceDefinition(BaseModel): model_config = ConfigDict( extra="forbid", ) - expressions: List[DateExpression] - operator: LogicalOperator + audience: BooleanExpression = Field(..., title="Audience") + schema_version: Version -class DateExpression( - RootModel[Union[AbsoluteDate, RelativeDate, DateExpression1, DateExpression2]] -): - root: Union[AbsoluteDate, RelativeDate, DateExpression1, DateExpression2] = Field( - ..., - description='Represents an expression that evaluates to a date or date-based condition. Examples: 1. Absolute date: { absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date: { relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator: { operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates: { operator: "and", expressions: [ { absolute: "2023-01-01T00:00:00Z" }, { operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } } ] }', +class UnaryBoolExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", ) + operand: Expression + operator: UnaryBoolOperator -class UnaryExpression(BaseModel): +class NumberBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - operand: Operand - operator: UnaryOperator + left: NumberExpression + operator: NumberBoolOperator + right: NumberExpression -class BinaryExpression(BaseModel): +class LogicalBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: Operand - operator: BinaryOperator - right: Operand + left: BooleanExpression + operator: LogicalBoolOperator + right: BooleanExpression -class LogicalExpression(BaseModel): +class LogicalManyBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - expressions: List[Expression] - operator: LogicalOperator + expressions: List[BooleanExpression] + operator: LogicalBoolOperator + + +class BooleanExpression( + RootModel[ + Union[ + bool, + ModelPath, + UnaryBoolExpression, + NumberBoolExpression, + StringBoolExpression, + DateBoolExpression, + LogicalBoolExpression, + LogicalManyBoolExpression, + LocationBooleanExpression, + ] + ] +): + root: Union[ + bool, + ModelPath, + UnaryBoolExpression, + NumberBoolExpression, + StringBoolExpression, + DateBoolExpression, + LogicalBoolExpression, + LogicalManyBoolExpression, + LocationBooleanExpression, + ] = Field(..., title="BooleanExpression") + -class Expression( - RootModel[Union[UnaryExpression, BinaryExpression, LogicalExpression]] -): - root: Union[UnaryExpression, BinaryExpression, LogicalExpression] = Field( - ..., - description='Represents a complex expression that can evaluate to true, false, or noop. Examples: 1. Join expression (combining expressions from different models): { "model": "user", "expression": { "operator": "equals", "left": { "path": "age" }, "right": 18 } }\n\n2. Logical expression (AND): { "operator": "and", "expressions": [ { "operator": "equals", "left": { "path": "country" }, "right": "US" }, { "operator": "greater_than", "left": { "path": "age" }, "right": 18 } ] }\n\n3. Location expression: { "operator": "within", "left": { "location": { "latitude": 37.7749, "longitude": -122.4194, "distance": { "value": 10, "unit": "miles" } } }, "right": { "model": "user", "path": "location" } }', - ) -class LocationExpression2(BaseModel): +class BinaryNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - expressions: List[LocationExpression] - operator: LogicalOperator + left: NumberExpression + operator: BinaryNumberOperator + right: NumberExpression -class LocationExpression( - RootModel[Union[Location, LocationExpression1, LocationExpression2]] -): - root: Union[Location, LocationExpression1, LocationExpression2] = Field( - ..., - description='Represents an expression that evaluates to a location or location-based condition. Examples: 1. Simple location: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator: { operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations: { operator: "or", expressions: [ { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }, { operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } } ] }', - ) - - -class ModelAggregationOperand(BaseModel): +class AggregateNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - condition: Optional[Expression] = None + condition: Optional[BooleanExpression] = None group_by_model: str - operand: Operand - operator: AggregationOperator + operand: NumberExpression + operator: AggregationNumberOperator -class Operand( - RootModel[Union[bool, float, str, DateOperand, ModelPath, ModelAggregationOperand]] +class NumberExpression( + RootModel[ + Union[float, ModelPath, BinaryNumberExpression, AggregateNumberExpression] + ] ): - root: Union[bool, float, str, DateOperand, ModelPath, ModelAggregationOperand] = ( + root: Union[float, ModelPath, BinaryNumberExpression, AggregateNumberExpression] = ( Field( ..., - description='Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations. Examples: 1. Primitive values: true 42 "hello"\n\n2. Path reference: { path: "user.age" }\n\n3. Arithmetic operation: { operator: "plus", left: { path: "price" }, right: { path: "tax" } }\n\n4. Nested arithmetic operation: { operator: "multiply", left: { operator: "plus", left: { path: "base_price" }, right: { path: "shipping" } }, right: 1.1 }\n\n5. Date operand: { date: { absolute: "2023-01-01T00:00:00Z" } }', + description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', + title="NumberExpression", ) ) - -class UnaryPathExpression(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - expression: PathExpression - operator: UnaryOperator - - -class BinaryPathExpression(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - operand: Operand - operator: BinaryOperator - - -class PathExpression( - RootModel[Union[bool, float, str, UnaryPathExpression, BinaryPathExpression]] +class Expression( + RootModel[ + Union[ + BooleanExpression, + DateExpression, + NumberExpression, + LocationExpression, + ModelPath, + ] + ] ): - root: Union[bool, float, str, UnaryPathExpression, BinaryPathExpression] = Field( + root: Union[ + BooleanExpression, + DateExpression, + NumberExpression, + LocationExpression, + ModelPath, + ] = Field( ..., - description='Represents an expression that evaluates to a path or value. Examples: 1. Primitive values: true 42 "hello"\n\n2. Unary expression (NOT): { operator: "not", expression: { operator: "equals", operand: { path: "status" } } }\n\n3. Binary expression (comparing a path to a value): { operator: "equals", operand: { path: "user.age" } }', + description='Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n"model": "user",\n"expression": {\n"operator": "equals",\n"left": { "path": "age" },\n"right": 18\n}\n}\n\n2. Logical expression (AND):\n{\n"operator": "and",\n"expressions": [\n{ "operator": "equals", "left": { "path": "country" }, "right": "US" },\n{ "operator": "greater_than", "left": { "path": "age" }, "right": 18 }\n]\n}\n\n3. Location expression:\n{\n"operator": "within",\n"left": { "location": { "latitude": 37.7749, "longitude": -122.4194, "distance": { "value": 10, "unit": "miles" } } },\n"right": { "model": "user", "path": "location" }\n}', + title="Expression", ) AudienceDefinition.model_rebuild() -CountExpression1.model_rebuild() -CountExpression2.model_rebuild() -DateExpression2.model_rebuild() -UnaryExpression.model_rebuild() -BinaryExpression.model_rebuild() -LogicalExpression.model_rebuild() -LocationExpression2.model_rebuild() -ModelAggregationOperand.model_rebuild() -UnaryPathExpression.model_rebuild() +UnaryBoolExpression.model_rebuild() +NumberBoolExpression.model_rebuild() +LogicalBoolExpression.model_rebuild() +LogicalManyBoolExpression.model_rebuild() +Expression.model_rebuild() +BinaryNumberExpression.model_rebuild() +AggregateNumberExpression.model_rebuild() diff --git a/sdk/python/tests/test_audience_models.py b/sdk/python/tests/test_audience_models.py index a16e377..6a0ee70 100644 --- a/sdk/python/tests/test_audience_models.py +++ b/sdk/python/tests/test_audience_models.py @@ -1,21 +1,22 @@ -# type: ignore import json from mp_audience_sdk.models.audience_models import ( AbsoluteDate, - AbsoluteDateOperand, - AggregationOperator, + AggregateNumberExpression, + AggregationNumberOperator, AudienceDefinition, - BinaryExpression, - BinaryOperator, + DateBoolExpression, DateUnit, - LogicalExpression, - LogicalOperator, - ModelAggregationOperand, + LogicalBoolOperator, + LogicalManyBoolExpression, ModelPath, + NumberBoolExpression, + NumberBoolOperator, Relative, RelativeDate, - RelativeDateOperand, + DateLiteralExpression, + StringBoolExpression, + StringBoolOperator, Version, ) @@ -39,8 +40,8 @@ def test_user_query(): deserialized_obj = AudienceDefinition.model_validate(json_dict) audience_defintion = AudienceDefinition( - audience=BinaryExpression( - operator=BinaryOperator.greater_than_equal, + audience=NumberBoolExpression( + operator=NumberBoolOperator.greater_than_equal, left=ModelPath(model="user", path="product_id"), right=3, ), @@ -143,57 +144,63 @@ def test_user_query_with_single_model(): "schema_version": "1.0" } """ - deserialized_obj = AudienceDefinition.model_validate(json.loads(audience_definition_json)) + deserialized_obj = AudienceDefinition.model_validate( + json.loads(audience_definition_json) + ) - color_or_expr = LogicalExpression( - operator=LogicalOperator.or_, + color_or_expr = LogicalManyBoolExpression( + operator=LogicalBoolOperator.or_, expressions=[ - BinaryExpression( - operator=BinaryOperator.equals, + StringBoolExpression( + operator=StringBoolOperator.equals, left=ModelPath(model="user", path="color"), right="blue", ), - BinaryExpression( - operator=BinaryOperator.equals, + StringBoolExpression( + operator=StringBoolOperator.equals, left=ModelPath(model="user", path="color"), right="yellow", ), - BinaryExpression( - operator=BinaryOperator.equals, left=ModelPath(model="user", path="color"), right="green" + StringBoolExpression( + operator=StringBoolOperator.equals, + left=ModelPath(model="user", path="color"), + right="green", ), ], ) - age_between_expr = LogicalExpression( - operator=LogicalOperator.and_, + age_between_expr = LogicalManyBoolExpression( + operator=LogicalBoolOperator.and_, expressions=[ - BinaryExpression( - operator=BinaryOperator.greater_than_equal, + NumberBoolExpression( + operator=NumberBoolOperator.greater_than_equal, left=ModelPath(model="user", path="age"), right=20.0, ), - BinaryExpression( - operator=BinaryOperator.less_than_equal, + NumberBoolExpression( + operator=NumberBoolOperator.less_than_equal, left=ModelPath(model="user", path="age"), right=40.0, ), ], ) - absolute_date_expr = BinaryExpression( - operator=BinaryOperator.equals, + absolute_date_expr = DateBoolExpression( + operator=NumberBoolOperator.equals, left=ModelPath(model="user", path="registration_date"), - right=AbsoluteDateOperand(date=AbsoluteDate(absolute="2024-01-15T00:00:00Z")), + right=DateLiteralExpression(date=AbsoluteDate(absolute="2024-01-15T00:00:00Z")), ) - relative_date_expr = BinaryExpression( - operator=BinaryOperator.greater_than_equal, + relative_date_expr = DateBoolExpression( + operator=NumberBoolOperator.greater_than_equal, left=ModelPath(model="user", path="last_seen_date"), - right=RelativeDateOperand(date=RelativeDate(relative=Relative(offset=-30, unit=DateUnit.day))), + right=DateLiteralExpression( + date=RelativeDate(relative=Relative(offset=-30, unit=DateUnit.day)) + ), ) - user_query = LogicalExpression( - operator=LogicalOperator.and_, + user_query = LogicalManyBoolExpression( + operator=LogicalBoolOperator.and_, expressions=[ color_or_expr, age_between_expr, @@ -203,8 +210,8 @@ def test_user_query_with_single_model(): ) audience_defintion = AudienceDefinition( - audience=LogicalExpression( - operator=LogicalOperator.and_, + audience=LogicalManyBoolExpression( + operator=LogicalBoolOperator.and_, expressions=[user_query], ), schema_version=Version("1.0"), @@ -240,19 +247,25 @@ def test_user_query_with_aggregate(): } """ - deserialized_obj = AudienceDefinition.model_validate(json.loads(audience_definition_json)) + deserialized_obj = AudienceDefinition.model_validate( + json.loads(audience_definition_json) + ) - aggregate_expr = ModelAggregationOperand( - operator=AggregationOperator.min, + aggregate_expr = AggregateNumberExpression( + operator=AggregationNumberOperator.min, group_by_model="user", operand=ModelPath(model="order", path="total"), - condition=BinaryExpression( - left=ModelPath(model="order", path="item_count"), operator=BinaryOperator.greater_than, right=2 + condition=NumberBoolExpression( + left=ModelPath(model="order", path="item_count"), + operator=NumberBoolOperator.greater_than, + right=2, ), ) audience_defintion = AudienceDefinition( - audience=BinaryExpression(operator=BinaryOperator.greater_than_equal, left=aggregate_expr, right=100), + audience=NumberBoolExpression( + operator=NumberBoolOperator.greater_than_equal, left=aggregate_expr, right=100 + ), schema_version=Version("1.0"), ) diff --git a/sdk/typescript-schema/expression/boolean-expression.ts b/sdk/typescript-schema/expression/boolean-expression.ts index e8d2353..6618e15 100644 --- a/sdk/typescript-schema/expression/boolean-expression.ts +++ b/sdk/typescript-schema/expression/boolean-expression.ts @@ -9,37 +9,37 @@ import { StringExpression } from "./string-expression"; /** * @title UnaryBoolExpression */ -type UnaryBoolExpression = { operator: UnaryBoolOperator, operand: Expression } +export type UnaryBoolExpression = { operator: UnaryBoolOperator, operand: Expression } /** * @title NumberBoolExpression */ -type NumberBoolExpression = { operator: NumberBoolOperator, left: NumberExpression, right: NumberExpression } +export type NumberBoolExpression = { operator: NumberBoolOperator, left: NumberExpression, right: NumberExpression } /** * @title StringBoolExpression */ -type StringBoolExpression = { operator: StringBoolOperator, left: StringExpression, right: StringExpression } +export type StringBoolExpression = { operator: StringBoolOperator, left: StringExpression, right: StringExpression } /** * @title DateBoolExpression */ -type DateBoolExpression = { operator: NumberBoolOperator, left: DateExpression, right: DateExpression } +export type DateBoolExpression = { operator: NumberBoolOperator, left: DateExpression, right: DateExpression } /** * @title LogicalBoolExpression */ -type LogicalBoolExpression = { operator: LogicalBoolOperator, left: BooleanExpression, right: BooleanExpression } +export type LogicalBoolExpression = { operator: LogicalBoolOperator, left: BooleanExpression, right: BooleanExpression } /** * @title LogicalManyBoolExpression */ -type LogicalManyBoolExpression = { operator: LogicalBoolOperator, expressions: BooleanExpression[] } +export type LogicalManyBoolExpression = { operator: LogicalBoolOperator, expressions: BooleanExpression[] } /** * @title LocationBooleanExpression */ -type LocationBooleanExpression = { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } +export type LocationBooleanExpression = { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } /** * @title BooleanExpression diff --git a/sdk/typescript-schema/expression/date-expression.ts b/sdk/typescript-schema/expression/date-expression.ts index 06aaa06..575ea9e 100644 --- a/sdk/typescript-schema/expression/date-expression.ts +++ b/sdk/typescript-schema/expression/date-expression.ts @@ -1,6 +1,11 @@ import { AbsoluteDate, RelativeDate } from "../literal/date"; import { ModelPath } from "../literal/model-path"; +/** + * @title DateLiteralExpression + */ +export type DateLiteralExpression = { date: AbsoluteDate | RelativeDate } + /** * @title BooleanExpression * @description Represents an expression that evaluates to a date or date-based condition. @@ -24,6 +29,5 @@ import { ModelPath } from "../literal/model-path"; * } */ export type DateExpression = - AbsoluteDate - | RelativeDate + DateLiteralExpression | ModelPath diff --git a/sdk/typescript-schema/expression/number-expression.ts b/sdk/typescript-schema/expression/number-expression.ts index eb2787d..a082907 100644 --- a/sdk/typescript-schema/expression/number-expression.ts +++ b/sdk/typescript-schema/expression/number-expression.ts @@ -5,12 +5,12 @@ import { ModelPath } from "../literal/model-path"; /** * @title BinaryNumberExpression */ -type BinaryNumberExpression = { operator: BinaryNumberOperator, left: NumberExpression, right: NumberExpression } +export type BinaryNumberExpression = { operator: BinaryNumberOperator, left: NumberExpression, right: NumberExpression } /** * @title AggregateNumberExpression */ -type AggregateNumberExpression = { operator: AggregationNumberOperator, group_by_model: string, operand: NumberExpression, condition?: BooleanExpression } +export type AggregateNumberExpression = { operator: AggregationNumberOperator, group_by_model: string, operand: NumberExpression, condition?: BooleanExpression } /** * @title NumberExpression diff --git a/sdk/typescript-schema/schema/audience-schema.json b/sdk/typescript-schema/schema/audience-schema.json index 363ed22..adff72d 100644 --- a/sdk/typescript-schema/schema/audience-schema.json +++ b/sdk/typescript-schema/schema/audience-schema.json @@ -213,10 +213,7 @@ "DateExpression": { "anyOf": [ { - "$ref": "#/definitions/AbsoluteDate" - }, - { - "$ref": "#/definitions/RelativeDate" + "$ref": "#/definitions/DateLiteralExpression" }, { "$ref": "#/definitions/ModelPath" @@ -236,6 +233,26 @@ ], "title": "DateLiteral" }, + "DateLiteralExpression": { + "additionalProperties": false, + "properties": { + "date": { + "anyOf": [ + { + "$ref": "#/definitions/AbsoluteDate" + }, + { + "$ref": "#/definitions/RelativeDate" + } + ] + } + }, + "required": [ + "date" + ], + "title": "DateLiteralExpression", + "type": "object" + }, "DateUnit": { "description": "Represents units of time that can be used in relative date calculations.\nExamples:\n- 'second': 1 second\n- 'minute': 60 seconds\n- 'hour': 60 minutes\n- 'day': 24 hours\n- 'week': 7 days\n- 'month': ~30 days\n- 'quarter': 3 months\n- 'year': 12 months", "enum": [ From 1b6ad5a6413b28e115979ef1338043e8c64d2e17 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Thu, 19 Jun 2025 14:07:18 -0700 Subject: [PATCH 07/16] Fix python SDK gen --- Makefile | 4 +- schema/audience-definition-schema.json | 365 ++++++++++-------- .../mp_audience_sdk/models/audience_models.py | 290 +++++++------- sdk/python/tests/test_audience_models.py | 7 +- .../schema/audience-schema.json | 365 ++++++++++-------- 5 files changed, 555 insertions(+), 476 deletions(-) diff --git a/Makefile b/Makefile index d1b2e39..95ea77e 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,9 @@ generate-python-models: --output-model-type pydantic_v2.BaseModel \ --field-constraints \ --snake-case-field \ - --encoding utf-8 + --encoding utf-8 \ + --collapse-root-models \ + --use-union-operator black $(PYTHON_OUTPUT_DIR) test: diff --git a/schema/audience-definition-schema.json b/schema/audience-definition-schema.json index adff72d..ab31cbf 100644 --- a/schema/audience-definition-schema.json +++ b/schema/audience-definition-schema.json @@ -15,6 +15,30 @@ "title": "AbsoluteDate", "type": "object" }, + "AggregateNumberExpression": { + "additionalProperties": false, + "properties": { + "condition": { + "$ref": "#/definitions/BooleanExpression" + }, + "group_by_model": { + "type": "string" + }, + "operand": { + "$ref": "#/definitions/NumberExpression" + }, + "operator": { + "$ref": "#/definitions/AggregationNumberOperator" + } + }, + "required": [ + "operator", + "group_by_model", + "operand" + ], + "title": "AggregateNumberExpression", + "type": "object" + }, "AggregationNumberOperator": { "description": "Represents operators for aggregating multiple values. Examples:\n- \"min\": [1, 2, 3] // result: 1\n- \"max\": [1, 2, 3] // result: 3\n- \"avg\": [1, 2, 3] // result: 2\n- \"count\": [1, 2, 3] // result: 3", "enum": [ @@ -46,6 +70,27 @@ "title": "AudienceDefinition", "type": "object" }, + "BinaryNumberExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/NumberExpression" + }, + "operator": { + "$ref": "#/definitions/BinaryNumberOperator" + }, + "right": { + "$ref": "#/definitions/NumberExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "BinaryNumberExpression", + "type": "object" + }, "BinaryNumberOperator": { "description": "Represents mathematical operators for numeric calculations. Examples:\n- \"plus\": { value1: 5, value2: 3 } // result: 8\n- \"multiply\": { value1: 4, value2: 2 } // result: 8\n- \"mod\": { value1: 10, value2: 3 } // result: 1", "enum": [ @@ -66,150 +111,50 @@ "$ref": "#/definitions/ModelPath" }, { - "additionalProperties": false, - "properties": { - "operand": { - "$ref": "#/definitions/Expression" - }, - "operator": { - "$ref": "#/definitions/UnaryBoolOperator" - } - }, - "required": [ - "operator", - "operand" - ], - "title": "UnaryBoolExpression", - "type": "object" + "$ref": "#/definitions/UnaryBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/NumberExpression" - }, - "operator": { - "$ref": "#/definitions/NumberBoolOperator" - }, - "right": { - "$ref": "#/definitions/NumberExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "NumberBoolExpression", - "type": "object" + "$ref": "#/definitions/NumberBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/StringExpression" - }, - "operator": { - "$ref": "#/definitions/StringBoolOperator" - }, - "right": { - "$ref": "#/definitions/StringExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "StringBoolExpression", - "type": "object" + "$ref": "#/definitions/StringBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/DateExpression" - }, - "operator": { - "$ref": "#/definitions/NumberBoolOperator" - }, - "right": { - "$ref": "#/definitions/DateExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "DateBoolExpression", - "type": "object" + "$ref": "#/definitions/DateBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/BooleanExpression" - }, - "operator": { - "$ref": "#/definitions/LogicalBoolOperator" - }, - "right": { - "$ref": "#/definitions/BooleanExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "LogicalBoolExpression", - "type": "object" + "$ref": "#/definitions/LogicalBoolExpression" }, { - "additionalProperties": false, - "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/BooleanExpression" - }, - "type": "array" - }, - "operator": { - "$ref": "#/definitions/LogicalBoolOperator" - } - }, - "required": [ - "operator", - "expressions" - ], - "title": "LogicalManyBoolExpression", - "type": "object" + "$ref": "#/definitions/LogicalManyBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/LocationExpression" - }, - "operator": { - "$ref": "#/definitions/LocationBoolOperator" - }, - "right": { - "$ref": "#/definitions/LocationExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "LocationBooleanExpression", - "type": "object" + "$ref": "#/definitions/LocationBooleanExpression" } ], "title": "BooleanExpression" }, + "DateBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/DateExpression" + }, + "operator": { + "$ref": "#/definitions/NumberBoolOperator" + }, + "right": { + "$ref": "#/definitions/DateExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "DateBoolExpression", + "type": "object" + }, "DateExpression": { "anyOf": [ { @@ -375,6 +320,27 @@ ], "type": "string" }, + "LocationBooleanExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/LocationExpression" + }, + "operator": { + "$ref": "#/definitions/LocationBoolOperator" + }, + "right": { + "$ref": "#/definitions/LocationExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "LocationBooleanExpression", + "type": "object" + }, "LocationExpression": { "anyOf": [ { @@ -387,6 +353,27 @@ "description": "Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }\n\n2. Location with operator:\n{ operator: \"within\", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Logical combination of locations:\n{\noperator: \"or\",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } },\n{ operator: \"within\", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: \"miles\" } } }\n]\n}", "title": "LocationExpression" }, + "LogicalBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/BooleanExpression" + }, + "operator": { + "$ref": "#/definitions/LogicalBoolOperator" + }, + "right": { + "$ref": "#/definitions/BooleanExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "LogicalBoolExpression", + "type": "object" + }, "LogicalBoolOperator": { "description": "Represents logical operators for combining multiple conditions. Examples:\n- \"and\": { condition1: true, condition2: true } // result: true\n- \"or\": { condition1: true, condition2: false } // result: true", "enum": [ @@ -395,6 +382,26 @@ ], "type": "string" }, + "LogicalManyBoolExpression": { + "additionalProperties": false, + "properties": { + "expressions": { + "items": { + "$ref": "#/definitions/BooleanExpression" + }, + "type": "array" + }, + "operator": { + "$ref": "#/definitions/LogicalBoolOperator" + } + }, + "required": [ + "operator", + "expressions" + ], + "title": "LogicalManyBoolExpression", + "type": "object" + }, "ModelPath": { "additionalProperties": false, "description": "Represents a model path reference within a data model.\nExamples:\n1. Simple model path:\n{ \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path:\n{ \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path:\n{ \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", @@ -413,6 +420,27 @@ "title": "ModelPath", "type": "object" }, + "NumberBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/NumberExpression" + }, + "operator": { + "$ref": "#/definitions/NumberBoolOperator" + }, + "right": { + "$ref": "#/definitions/NumberExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "NumberBoolExpression", + "type": "object" + }, "NumberBoolOperator": { "description": "Represents binary operators that compare two values. Examples:\n- \"equals\": { value1: 5, value2: 5 }\n- \"less_than\": { value1: 3, value2: 5 }\n- \"matches\": { value1: \"pattern\", value2: \"text\" }\n- \"contains\": { value1: \"string\", value2: \"substring\" }", "enum": [ @@ -434,49 +462,10 @@ "$ref": "#/definitions/ModelPath" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/NumberExpression" - }, - "operator": { - "$ref": "#/definitions/BinaryNumberOperator" - }, - "right": { - "$ref": "#/definitions/NumberExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "BinaryNumberExpression", - "type": "object" + "$ref": "#/definitions/BinaryNumberExpression" }, { - "additionalProperties": false, - "properties": { - "condition": { - "$ref": "#/definitions/BooleanExpression" - }, - "group_by_model": { - "type": "string" - }, - "operand": { - "$ref": "#/definitions/NumberExpression" - }, - "operator": { - "$ref": "#/definitions/AggregationNumberOperator" - } - }, - "required": [ - "operator", - "group_by_model", - "operand" - ], - "title": "AggregateNumberExpression", - "type": "object" + "$ref": "#/definitions/AggregateNumberExpression" } ], "description": "Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n\n3. Logical group of count expressions:\n{\noperator: \"and\",\nexpressions: [\n1,\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n]\n}", @@ -516,6 +505,27 @@ "title": "RelativeDate", "type": "object" }, + "StringBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/StringExpression" + }, + "operator": { + "$ref": "#/definitions/StringBoolOperator" + }, + "right": { + "$ref": "#/definitions/StringExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "StringBoolExpression", + "type": "object" + }, "StringBoolOperator": { "enum": [ "equals", @@ -541,6 +551,23 @@ ], "title": "StringExpression" }, + "UnaryBoolExpression": { + "additionalProperties": false, + "properties": { + "operand": { + "$ref": "#/definitions/Expression" + }, + "operator": { + "$ref": "#/definitions/UnaryBoolOperator" + } + }, + "required": [ + "operator", + "operand" + ], + "title": "UnaryBoolExpression", + "type": "object" + }, "UnaryBoolOperator": { "description": "Represents unary operators that operate on a single value. Examples:\n- \"not\": Negates a boolean expression\n- \"exist\": Checks if a value exists", "enum": [ diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index 45c850e..217d222 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,11 +1,11 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-06-19T19:18:47+00:00 +# timestamp: 2025-06-19T21:03:31+00:00 from __future__ import annotations from enum import Enum -from typing import Any, List, Optional, Union +from typing import Any, List from pydantic import BaseModel, ConfigDict, Field, RootModel @@ -75,7 +75,7 @@ class Location(BaseModel): model_config = ConfigDict( extra="forbid", ) - distance: Optional[Distance] = None + distance: Distance | None = None latitude: float longitude: float @@ -116,7 +116,7 @@ class Relative(BaseModel): model_config = ConfigDict( extra="forbid", ) - boundary: Optional[Boundary] = None + boundary: Boundary | None = None offset: float unit: DateUnit @@ -140,10 +140,6 @@ class StringBoolOperator(Enum): not_ends_with = "not_ends_with" -class StringExpression(RootModel[Union[str, ModelPath]]): - root: Union[str, ModelPath] = Field(..., title="StringExpression") - - class UnaryBoolOperator(Enum): null = "null" not_null = "not_null" @@ -151,10 +147,6 @@ class UnaryBoolOperator(Enum): not_exists = "not_exists" -class Version(RootModel[str]): - root: str - - class NamedArgs(BaseModel): model_config = ConfigDict( extra="forbid", @@ -163,169 +155,197 @@ class NamedArgs(BaseModel): class IsValidAudienceObject(BaseModel): - named_args: Optional[NamedArgs] = Field(None, alias="namedArgs") + named_args: NamedArgs | None = Field(None, alias="namedArgs") -class StringBoolExpression(BaseModel): +class DateLiteralExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: StringExpression - operator: StringBoolOperator - right: StringExpression + date: AbsoluteDate | RelativeDate -class DateLiteral(RootModel[Union[AbsoluteDate, RelativeDate]]): - root: Union[AbsoluteDate, RelativeDate] = Field(..., title="DateLiteral") +class Literal( + RootModel[bool | float | str | ModelPath | Location | AbsoluteDate | RelativeDate] +): + root: bool | float | str | ModelPath | Location | AbsoluteDate | RelativeDate = ( + Field( + ..., + description='Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n"hello"\n\n2. Path reference:\n{ path: "user.age" }\n\n3. Arithmetic operation:\n{\noperator: "plus",\nleft: { path: "price" },\nright: { path: "tax" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: "multiply",\nleft: { operator: "plus", left: { path: "base_price" }, right: { path: "shipping" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: "2023-01-01T00:00:00Z" } }', + title="Literal", + ) + ) -class DateLiteralExpression(BaseModel): +class StringBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - date: Union[AbsoluteDate, RelativeDate] + left: str | ModelPath = Field(..., title="StringExpression") + operator: StringBoolOperator + right: str | ModelPath = Field(..., title="StringExpression") -class Literal(RootModel[Union[bool, float, str, DateLiteral, ModelPath, Location]]): - root: Union[bool, float, str, DateLiteral, ModelPath, Location] = Field( +class LocationBooleanExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + left: Location | ModelPath = Field( ..., - description='Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n"hello"\n\n2. Path reference:\n{ path: "user.age" }\n\n3. Arithmetic operation:\n{\noperator: "plus",\nleft: { path: "price" },\nright: { path: "tax" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: "multiply",\nleft: { operator: "plus", left: { path: "base_price" }, right: { path: "shipping" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: "2023-01-01T00:00:00Z" } }', - title="Literal", + description='Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator:\n{ operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations:\n{\noperator: "or",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } },\n{ operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } }\n]\n}', + title="LocationExpression", ) - - -class LocationExpression(RootModel[Union[Location, ModelPath]]): - root: Union[Location, ModelPath] = Field( + operator: LocationBoolOperator + right: Location | ModelPath = Field( ..., description='Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator:\n{ operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations:\n{\noperator: "or",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } },\n{ operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } }\n]\n}', title="LocationExpression", ) -class LocationBooleanExpression(BaseModel): +class DateBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: LocationExpression - operator: LocationBoolOperator - right: LocationExpression - - -class DateExpression(RootModel[Union[DateLiteralExpression, ModelPath]]): - root: Union[DateLiteralExpression, ModelPath] = Field( + left: DateLiteralExpression | ModelPath = Field( + ..., + description='Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator:\n{ operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates:\n{\noperator: "and",\nexpressions: [\n{ absolute: "2023-01-01T00:00:00Z" },\n{ operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } }\n]\n}', + title="BooleanExpression", + ) + operator: NumberBoolOperator + right: DateLiteralExpression | ModelPath = Field( ..., description='Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator:\n{ operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates:\n{\noperator: "and",\nexpressions: [\n{ absolute: "2023-01-01T00:00:00Z" },\n{ operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } }\n]\n}', title="BooleanExpression", ) -class DateBoolExpression(BaseModel): +class AggregateNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: DateExpression - operator: NumberBoolOperator - right: DateExpression + condition: ( + bool + | ModelPath + | UnaryBoolExpression + | NumberBoolExpression + | StringBoolExpression + | DateBoolExpression + | LogicalBoolExpression + | LogicalManyBoolExpression + | LocationBooleanExpression + | None + ) = Field(None, title="BooleanExpression") + group_by_model: str + operand: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( + Field( + ..., + description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', + title="NumberExpression", + ) + ) + operator: AggregationNumberOperator class AudienceDefinition(BaseModel): model_config = ConfigDict( extra="forbid", ) - audience: BooleanExpression = Field(..., title="Audience") - schema_version: Version + audience: ( + bool + | ModelPath + | UnaryBoolExpression + | NumberBoolExpression + | StringBoolExpression + | DateBoolExpression + | LogicalBoolExpression + | LogicalManyBoolExpression + | LocationBooleanExpression + ) = Field(..., title="Audience") + schema_version: str -class UnaryBoolExpression(BaseModel): +class BinaryNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - operand: Expression - operator: UnaryBoolOperator - - -class NumberBoolExpression(BaseModel): - model_config = ConfigDict( - extra="forbid", + left: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( + Field( + ..., + description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', + title="NumberExpression", + ) + ) + operator: BinaryNumberOperator + right: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( + Field( + ..., + description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', + title="NumberExpression", + ) ) - left: NumberExpression - operator: NumberBoolOperator - right: NumberExpression class LogicalBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: BooleanExpression + left: ( + bool + | ModelPath + | UnaryBoolExpression + | NumberBoolExpression + | StringBoolExpression + | DateBoolExpression + | LogicalBoolExpression + | LogicalManyBoolExpression + | LocationBooleanExpression + ) = Field(..., title="BooleanExpression") operator: LogicalBoolOperator - right: BooleanExpression + right: ( + bool + | ModelPath + | UnaryBoolExpression + | NumberBoolExpression + | StringBoolExpression + | DateBoolExpression + | LogicalBoolExpression + | LogicalManyBoolExpression + | LocationBooleanExpression + ) = Field(..., title="BooleanExpression") class LogicalManyBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - expressions: List[BooleanExpression] - operator: LogicalBoolOperator - - -class BooleanExpression( - RootModel[ - Union[ - bool, - ModelPath, - UnaryBoolExpression, - NumberBoolExpression, - StringBoolExpression, - DateBoolExpression, - LogicalBoolExpression, - LogicalManyBoolExpression, - LocationBooleanExpression, - ] + expressions: List[ + bool + | ModelPath + | UnaryBoolExpression + | NumberBoolExpression + | StringBoolExpression + | DateBoolExpression + | LogicalBoolExpression + | LogicalManyBoolExpression + | LocationBooleanExpression ] -): - root: Union[ - bool, - ModelPath, - UnaryBoolExpression, - NumberBoolExpression, - StringBoolExpression, - DateBoolExpression, - LogicalBoolExpression, - LogicalManyBoolExpression, - LocationBooleanExpression, - ] = Field(..., title="BooleanExpression") - - - + operator: LogicalBoolOperator -class BinaryNumberExpression(BaseModel): +class NumberBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: NumberExpression - operator: BinaryNumberOperator - right: NumberExpression - - -class AggregateNumberExpression(BaseModel): - model_config = ConfigDict( - extra="forbid", + left: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( + Field( + ..., + description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', + title="NumberExpression", + ) ) - condition: Optional[BooleanExpression] = None - group_by_model: str - operand: NumberExpression - operator: AggregationNumberOperator - - -class NumberExpression( - RootModel[ - Union[float, ModelPath, BinaryNumberExpression, AggregateNumberExpression] - ] -): - root: Union[float, ModelPath, BinaryNumberExpression, AggregateNumberExpression] = ( + operator: NumberBoolOperator + right: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( Field( ..., description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', @@ -333,35 +353,39 @@ class NumberExpression( ) ) -class Expression( - RootModel[ - Union[ - BooleanExpression, - DateExpression, - NumberExpression, - LocationExpression, - ModelPath, - ] - ] -): - root: Union[ - BooleanExpression, - DateExpression, - NumberExpression, - LocationExpression, - ModelPath, - ] = Field( + +class UnaryBoolExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + operand: ( + ModelPath + | bool + | ModelPath + | UnaryBoolExpression + | NumberBoolExpression + | StringBoolExpression + | DateBoolExpression + | LogicalBoolExpression + | LogicalManyBoolExpression + | LocationBooleanExpression + | DateLiteralExpression + | ModelPath + | float + | ModelPath + | BinaryNumberExpression + | AggregateNumberExpression + | Location + | ModelPath + ) = Field( ..., description='Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n"model": "user",\n"expression": {\n"operator": "equals",\n"left": { "path": "age" },\n"right": 18\n}\n}\n\n2. Logical expression (AND):\n{\n"operator": "and",\n"expressions": [\n{ "operator": "equals", "left": { "path": "country" }, "right": "US" },\n{ "operator": "greater_than", "left": { "path": "age" }, "right": 18 }\n]\n}\n\n3. Location expression:\n{\n"operator": "within",\n"left": { "location": { "latitude": 37.7749, "longitude": -122.4194, "distance": { "value": 10, "unit": "miles" } } },\n"right": { "model": "user", "path": "location" }\n}', title="Expression", ) + operator: UnaryBoolOperator +AggregateNumberExpression.model_rebuild() AudienceDefinition.model_rebuild() -UnaryBoolExpression.model_rebuild() -NumberBoolExpression.model_rebuild() -LogicalBoolExpression.model_rebuild() -LogicalManyBoolExpression.model_rebuild() -Expression.model_rebuild() BinaryNumberExpression.model_rebuild() -AggregateNumberExpression.model_rebuild() +NumberBoolExpression.model_rebuild() diff --git a/sdk/python/tests/test_audience_models.py b/sdk/python/tests/test_audience_models.py index 6a0ee70..7826666 100644 --- a/sdk/python/tests/test_audience_models.py +++ b/sdk/python/tests/test_audience_models.py @@ -17,7 +17,6 @@ DateLiteralExpression, StringBoolExpression, StringBoolOperator, - Version, ) @@ -45,7 +44,7 @@ def test_user_query(): left=ModelPath(model="user", path="product_id"), right=3, ), - schema_version=Version("1.0"), + schema_version="1.0", ) assert audience_defintion == deserialized_obj @@ -214,7 +213,7 @@ def test_user_query_with_single_model(): operator=LogicalBoolOperator.and_, expressions=[user_query], ), - schema_version=Version("1.0"), + schema_version="1.0", ) assert deserialized_obj == audience_defintion @@ -266,7 +265,7 @@ def test_user_query_with_aggregate(): audience=NumberBoolExpression( operator=NumberBoolOperator.greater_than_equal, left=aggregate_expr, right=100 ), - schema_version=Version("1.0"), + schema_version="1.0", ) assert deserialized_obj == audience_defintion diff --git a/sdk/typescript-schema/schema/audience-schema.json b/sdk/typescript-schema/schema/audience-schema.json index adff72d..ab31cbf 100644 --- a/sdk/typescript-schema/schema/audience-schema.json +++ b/sdk/typescript-schema/schema/audience-schema.json @@ -15,6 +15,30 @@ "title": "AbsoluteDate", "type": "object" }, + "AggregateNumberExpression": { + "additionalProperties": false, + "properties": { + "condition": { + "$ref": "#/definitions/BooleanExpression" + }, + "group_by_model": { + "type": "string" + }, + "operand": { + "$ref": "#/definitions/NumberExpression" + }, + "operator": { + "$ref": "#/definitions/AggregationNumberOperator" + } + }, + "required": [ + "operator", + "group_by_model", + "operand" + ], + "title": "AggregateNumberExpression", + "type": "object" + }, "AggregationNumberOperator": { "description": "Represents operators for aggregating multiple values. Examples:\n- \"min\": [1, 2, 3] // result: 1\n- \"max\": [1, 2, 3] // result: 3\n- \"avg\": [1, 2, 3] // result: 2\n- \"count\": [1, 2, 3] // result: 3", "enum": [ @@ -46,6 +70,27 @@ "title": "AudienceDefinition", "type": "object" }, + "BinaryNumberExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/NumberExpression" + }, + "operator": { + "$ref": "#/definitions/BinaryNumberOperator" + }, + "right": { + "$ref": "#/definitions/NumberExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "BinaryNumberExpression", + "type": "object" + }, "BinaryNumberOperator": { "description": "Represents mathematical operators for numeric calculations. Examples:\n- \"plus\": { value1: 5, value2: 3 } // result: 8\n- \"multiply\": { value1: 4, value2: 2 } // result: 8\n- \"mod\": { value1: 10, value2: 3 } // result: 1", "enum": [ @@ -66,150 +111,50 @@ "$ref": "#/definitions/ModelPath" }, { - "additionalProperties": false, - "properties": { - "operand": { - "$ref": "#/definitions/Expression" - }, - "operator": { - "$ref": "#/definitions/UnaryBoolOperator" - } - }, - "required": [ - "operator", - "operand" - ], - "title": "UnaryBoolExpression", - "type": "object" + "$ref": "#/definitions/UnaryBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/NumberExpression" - }, - "operator": { - "$ref": "#/definitions/NumberBoolOperator" - }, - "right": { - "$ref": "#/definitions/NumberExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "NumberBoolExpression", - "type": "object" + "$ref": "#/definitions/NumberBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/StringExpression" - }, - "operator": { - "$ref": "#/definitions/StringBoolOperator" - }, - "right": { - "$ref": "#/definitions/StringExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "StringBoolExpression", - "type": "object" + "$ref": "#/definitions/StringBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/DateExpression" - }, - "operator": { - "$ref": "#/definitions/NumberBoolOperator" - }, - "right": { - "$ref": "#/definitions/DateExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "DateBoolExpression", - "type": "object" + "$ref": "#/definitions/DateBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/BooleanExpression" - }, - "operator": { - "$ref": "#/definitions/LogicalBoolOperator" - }, - "right": { - "$ref": "#/definitions/BooleanExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "LogicalBoolExpression", - "type": "object" + "$ref": "#/definitions/LogicalBoolExpression" }, { - "additionalProperties": false, - "properties": { - "expressions": { - "items": { - "$ref": "#/definitions/BooleanExpression" - }, - "type": "array" - }, - "operator": { - "$ref": "#/definitions/LogicalBoolOperator" - } - }, - "required": [ - "operator", - "expressions" - ], - "title": "LogicalManyBoolExpression", - "type": "object" + "$ref": "#/definitions/LogicalManyBoolExpression" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/LocationExpression" - }, - "operator": { - "$ref": "#/definitions/LocationBoolOperator" - }, - "right": { - "$ref": "#/definitions/LocationExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "LocationBooleanExpression", - "type": "object" + "$ref": "#/definitions/LocationBooleanExpression" } ], "title": "BooleanExpression" }, + "DateBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/DateExpression" + }, + "operator": { + "$ref": "#/definitions/NumberBoolOperator" + }, + "right": { + "$ref": "#/definitions/DateExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "DateBoolExpression", + "type": "object" + }, "DateExpression": { "anyOf": [ { @@ -375,6 +320,27 @@ ], "type": "string" }, + "LocationBooleanExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/LocationExpression" + }, + "operator": { + "$ref": "#/definitions/LocationBoolOperator" + }, + "right": { + "$ref": "#/definitions/LocationExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "LocationBooleanExpression", + "type": "object" + }, "LocationExpression": { "anyOf": [ { @@ -387,6 +353,27 @@ "description": "Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }\n\n2. Location with operator:\n{ operator: \"within\", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Logical combination of locations:\n{\noperator: \"or\",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } },\n{ operator: \"within\", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: \"miles\" } } }\n]\n}", "title": "LocationExpression" }, + "LogicalBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/BooleanExpression" + }, + "operator": { + "$ref": "#/definitions/LogicalBoolOperator" + }, + "right": { + "$ref": "#/definitions/BooleanExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "LogicalBoolExpression", + "type": "object" + }, "LogicalBoolOperator": { "description": "Represents logical operators for combining multiple conditions. Examples:\n- \"and\": { condition1: true, condition2: true } // result: true\n- \"or\": { condition1: true, condition2: false } // result: true", "enum": [ @@ -395,6 +382,26 @@ ], "type": "string" }, + "LogicalManyBoolExpression": { + "additionalProperties": false, + "properties": { + "expressions": { + "items": { + "$ref": "#/definitions/BooleanExpression" + }, + "type": "array" + }, + "operator": { + "$ref": "#/definitions/LogicalBoolOperator" + } + }, + "required": [ + "operator", + "expressions" + ], + "title": "LogicalManyBoolExpression", + "type": "object" + }, "ModelPath": { "additionalProperties": false, "description": "Represents a model path reference within a data model.\nExamples:\n1. Simple model path:\n{ \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path:\n{ \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path:\n{ \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", @@ -413,6 +420,27 @@ "title": "ModelPath", "type": "object" }, + "NumberBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/NumberExpression" + }, + "operator": { + "$ref": "#/definitions/NumberBoolOperator" + }, + "right": { + "$ref": "#/definitions/NumberExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "NumberBoolExpression", + "type": "object" + }, "NumberBoolOperator": { "description": "Represents binary operators that compare two values. Examples:\n- \"equals\": { value1: 5, value2: 5 }\n- \"less_than\": { value1: 3, value2: 5 }\n- \"matches\": { value1: \"pattern\", value2: \"text\" }\n- \"contains\": { value1: \"string\", value2: \"substring\" }", "enum": [ @@ -434,49 +462,10 @@ "$ref": "#/definitions/ModelPath" }, { - "additionalProperties": false, - "properties": { - "left": { - "$ref": "#/definitions/NumberExpression" - }, - "operator": { - "$ref": "#/definitions/BinaryNumberOperator" - }, - "right": { - "$ref": "#/definitions/NumberExpression" - } - }, - "required": [ - "operator", - "left", - "right" - ], - "title": "BinaryNumberExpression", - "type": "object" + "$ref": "#/definitions/BinaryNumberExpression" }, { - "additionalProperties": false, - "properties": { - "condition": { - "$ref": "#/definitions/BooleanExpression" - }, - "group_by_model": { - "type": "string" - }, - "operand": { - "$ref": "#/definitions/NumberExpression" - }, - "operator": { - "$ref": "#/definitions/AggregationNumberOperator" - } - }, - "required": [ - "operator", - "group_by_model", - "operand" - ], - "title": "AggregateNumberExpression", - "type": "object" + "$ref": "#/definitions/AggregateNumberExpression" } ], "description": "Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n\n3. Logical group of count expressions:\n{\noperator: \"and\",\nexpressions: [\n1,\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n]\n}", @@ -516,6 +505,27 @@ "title": "RelativeDate", "type": "object" }, + "StringBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/StringExpression" + }, + "operator": { + "$ref": "#/definitions/StringBoolOperator" + }, + "right": { + "$ref": "#/definitions/StringExpression" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "StringBoolExpression", + "type": "object" + }, "StringBoolOperator": { "enum": [ "equals", @@ -541,6 +551,23 @@ ], "title": "StringExpression" }, + "UnaryBoolExpression": { + "additionalProperties": false, + "properties": { + "operand": { + "$ref": "#/definitions/Expression" + }, + "operator": { + "$ref": "#/definitions/UnaryBoolOperator" + } + }, + "required": [ + "operator", + "operand" + ], + "title": "UnaryBoolExpression", + "type": "object" + }, "UnaryBoolOperator": { "description": "Represents unary operators that operate on a single value. Examples:\n- \"not\": Negates a boolean expression\n- \"exist\": Checks if a value exists", "enum": [ From 00bcb7f45c8f425a9b34a06697cc91b5414cfc40 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Fri, 20 Jun 2025 10:48:09 -0700 Subject: [PATCH 08/16] Delete unused SDK --- sdk/typescript/.nvmrc | 1 - sdk/typescript/README.md | 354 ---- sdk/typescript/package-lock.json | 1628 ----------------- sdk/typescript/package.json | 28 - sdk/typescript/src/audience-builder.ts | 110 -- .../count-expression-factory.ts | 77 - .../date-operand-factory.ts | 89 - .../expression-factory/expression-factory.ts | 114 -- .../location-operand-factory.ts | 83 - .../src/expression-factory/operand-factory.ts | 127 -- .../path-expression-factory.ts | 45 - sdk/typescript/src/index.ts | 73 - .../src/query-builders/query-builder.ts | 39 - sdk/typescript/tsconfig.json | 15 - 14 files changed, 2783 deletions(-) delete mode 100644 sdk/typescript/.nvmrc delete mode 100644 sdk/typescript/README.md delete mode 100644 sdk/typescript/package-lock.json delete mode 100644 sdk/typescript/package.json delete mode 100644 sdk/typescript/src/audience-builder.ts delete mode 100644 sdk/typescript/src/expression-factory/count-expression-factory.ts delete mode 100644 sdk/typescript/src/expression-factory/date-operand-factory.ts delete mode 100644 sdk/typescript/src/expression-factory/expression-factory.ts delete mode 100644 sdk/typescript/src/expression-factory/location-operand-factory.ts delete mode 100644 sdk/typescript/src/expression-factory/operand-factory.ts delete mode 100644 sdk/typescript/src/expression-factory/path-expression-factory.ts delete mode 100644 sdk/typescript/src/index.ts delete mode 100644 sdk/typescript/src/query-builders/query-builder.ts delete mode 100644 sdk/typescript/tsconfig.json diff --git a/sdk/typescript/.nvmrc b/sdk/typescript/.nvmrc deleted file mode 100644 index 0f394a5..0000000 --- a/sdk/typescript/.nvmrc +++ /dev/null @@ -1 +0,0 @@ -20.18.0 \ No newline at end of file diff --git a/sdk/typescript/README.md b/sdk/typescript/README.md deleted file mode 100644 index d7fe24c..0000000 --- a/sdk/typescript/README.md +++ /dev/null @@ -1,354 +0,0 @@ -# mParticle Audience SDK - -A TypeScript SDK for building and managing mParticle Audiences. - -## Installation - -```bash -npm install @mparticle/audience-sdk -``` - -## Usage - -### Creating a Simple Audience - -```typescript -import { createAudience, createEventQueryBuilder } from '@mparticle/audience-sdk'; - -// Create an event query -const eventQuery = createEventQueryBuilder() - .setModels(['event']) - .setEventName({ path: 'purchase' }) - .build(); - -// Create an audience with the event query -const audience = createAudience() - .addQuery({ event: eventQuery }) - .build(); - -// Convert to JSON -const json = JSON.stringify(audience, null, 2); -``` - -### Creating a Complex Audience with Logical Combinations - -```typescript -import { - createAudience, - createEventQueryBuilder, - createUserQueryBuilder, - createLogicalQuery -} from '@mparticle/audience-sdk'; - -// Create an event query for purchases -const purchaseQuery = createEventQueryBuilder() - .setModels(['event']) - .setEventName({ path: 'purchase' }) - .build(); - -// Create a user query for premium users -const premiumUserQuery = createUserQueryBuilder() - .setModels(['user']) - .addAttribute('subscription_tier', { path: 'premium' }) - .build(); - -// Create a logical query combining both conditions -const logicalQuery = createLogicalQuery() - .setOperator('and') - .addQuery({ event: purchaseQuery }) - .addQuery({ user: premiumUserQuery }) - .build(); - -// Create the final audience -const audience = createAudience() - .setOperator('or') - .addQuery({ event: purchaseQuery }) - .addLogicalQuery(logicalQuery) - .build(); -``` - -### Building Operands - -```typescript -import { - OperandFactory, - DateOperandFactory, - LocationOperandFactory -} from '@mparticle/audience-sdk'; - -// Create primitive operands -const stringOperand = OperandFactory.createPrimitive('value'); -const numberOperand = OperandFactory.createPrimitive(42); -const booleanOperand = OperandFactory.createPrimitive(true); - -// Create path operands -const pathOperand = OperandFactory.createPath('user.profile.age'); - -// Create date operands -const absoluteDate = OperandFactory.createAbsoluteDate('2023-01-01T00:00:00Z'); -const relativeDate = OperandFactory.createRelativeDate(-7, 'day', 'start'); - -// Create location operands -const locationPoint = OperandFactory.createLocationPoint(37.7749, -122.4194); -const locationWithRadius = OperandFactory.createLocationWithMiles(37.7749, -122.4194, 10); - -// Create arithmetic operands -const arithmeticOperand = OperandFactory.createArithmetic( - 'add', - OperandFactory.createPath('user.profile.age'), - OperandFactory.createPrimitive(5) -); -``` - -### Building Expressions - -```typescript -import { - ExpressionFactory, - OperandFactory -} from '@mparticle/audience-sdk'; - -// Create binary expressions -const equalsExpression = ExpressionFactory.createBinary( - 'eq', - OperandFactory.createPath('user.profile.age'), - OperandFactory.createPrimitive(18) -); - -const greaterThanExpression = ExpressionFactory.createBinary( - 'gt', - OperandFactory.createPath('user.profile.age'), - OperandFactory.createPrimitive(21) -); - -// Create logical expressions (AND/OR) -const andExpression = ExpressionFactory.createAnd([ - equalsExpression, - greaterThanExpression -]); - -const orExpression = ExpressionFactory.createOr([ - equalsExpression, - greaterThanExpression -]); - -// Create NOT expressions -const notExpression = ExpressionFactory.createNot(equalsExpression); - -// Create EXISTS expressions -const existsExpression = ExpressionFactory.createExists( - OperandFactory.createPath('user.profile.email') -); - -// Create location expressions -const locationExpression = ExpressionFactory.createLocation( - 'within', - OperandFactory.createLocationWithMiles(37.7749, -122.4194, 10), - { path: 'user.location' } -); -``` - -### Building Event Queries - -```typescript -import { - createEventQueryBuilder, - ExpressionFactory, - OperandFactory -} from '@mparticle/audience-sdk'; - -// Simple event query -const simpleEventQuery = createEventQueryBuilder() - .setModels(['event']) - .setEventName({ path: 'purchase' }) - .build(); - -// Event query with attributes -const eventQueryWithAttributes = createEventQueryBuilder() - .setModels(['event']) - .setEventName({ path: 'purchase' }) - .setAttributeOperator('and') - .addAttributesExpression( - ExpressionFactory.createBinary( - 'gt', - OperandFactory.createPath('event.properties.amount'), - OperandFactory.createPrimitive(100) - ) - ) - .build(); - -// Event query with count -const eventQueryWithCount = createEventQueryBuilder() - .setModels(['event']) - .setEventName({ path: 'purchase' }) - .setCountValue(5) - .build(); - -// Event query with date -const eventQueryWithDate = createEventQueryBuilder() - .setModels(['event']) - .setEventName({ path: 'purchase' }) - .setRelativeDate(-30, 'day', 'start') - .build(); - -// Event query with location -const eventQueryWithLocation = createEventQueryBuilder() - .setModels(['event']) - .setEventName({ path: 'purchase' }) - .setLocation( - ExpressionFactory.createLocation( - 'within', - OperandFactory.createLocationWithMiles(37.7749, -122.4194, 10), - { path: 'event.location' } - ) - ) - .build(); -``` - -### Building User Queries - -```typescript -import { - createUserQueryBuilder, - ExpressionFactory, - OperandFactory -} from '@mparticle/audience-sdk'; - -// Simple user query -const simpleUserQuery = createUserQueryBuilder() - .setModels(['user']) - .setAttributeOperator('and') - .addAttributesExpression( - ExpressionFactory.createBinary( - 'eq', - OperandFactory.createPath('user.profile.subscription_tier'), - OperandFactory.createPrimitive('premium') - ) - ) - .build(); - -// Complex user query with multiple conditions -const complexUserQuery = createUserQueryBuilder() - .setModels(['user']) - .setAttributeOperator('and') - .addAttributesExpression( - ExpressionFactory.createBinary( - 'eq', - OperandFactory.createPath('user.profile.subscription_tier'), - OperandFactory.createPrimitive('premium') - ) - ) - .addAttributesExpression( - ExpressionFactory.createBinary( - 'gt', - OperandFactory.createPath('user.profile.age'), - OperandFactory.createPrimitive(21) - ) - ) - .addAttributesExpression( - ExpressionFactory.createExists( - OperandFactory.createPath('user.profile.email') - ) - ) - .build(); -``` - -### Parsing and Validating Audiences - -```typescript -import { parseAudience, validateAudience, stringifyAudience } from '@mparticle/audience-sdk'; - -// Parse an audience from JSON -const jsonString = '{"audience":{"operator":"and","queries":[{"event":{"model":"event","event_name":{"path":"purchase"}}}]}}'; -const audience = parseAudience(jsonString); - -// Validate an audience -const isValid = validateAudience(audience); - -// Convert an audience to JSON -const json = stringifyAudience(audience); -``` - -## API Reference - -### AudienceBuilder - -The main builder for creating Audience objects. - -- `setOperator(operator: 'and' | 'or')`: Sets the logical operator for combining queries -- `addQuery(query: AudienceQuery)`: Adds a query to the audience -- `addLogicalQuery(logicalQuery: LogicalAudienceQueries)`: Adds a nested logical query -- `build()`: Builds and returns the final Audience object - -### QueryBuilders - -#### GeneralQueryBuilder - -- `setModels(models: Model[])`: Sets the models for the query -- `setExpression(expression: Expression)`: Sets the expression for the query -- `build()`: Builds and returns the query - -#### EventQueryBuilder - -- `setModels(models: Model[])`: Sets the models for the event query -- `setEventName(eventName: PathExpression)`: Sets the event name -- `setAttributeOperator(operator: LogicalOperator)`: Sets the operator for combining attribute expressions -- `addAttributesExpression(expression: SingleModelExpression)`: Adds an expression to the query -- `setCountValue(count: number)`: Sets a simple numeric count value -- `setCountBinary(operator: BinaryOperator, operand: Operand)`: Sets a binary operator count expression -- `setCountLogical(operator: LogicalOperator, expressions: CountExpression[])`: Sets a logical combination of count expressions -- `setAbsoluteDate(absoluteDate: string)`: Sets an absolute date -- `setRelativeDate(offset: number, unit: DateUnit, boundary?: 'start' | 'end')`: Sets a relative date -- `setDateBinary(operator: BinaryOperator, operand: AbsoluteDate | RelativeDate)`: Sets a binary operator date expression -- `setDateLogical(operator: LogicalOperator, expressions: DateExpression[])`: Sets a logical combination of date expressions -- `setLocation(location: LocationExpression)`: Sets the location -- `setEventType(eventType: PathExpression)`: Sets the event type -- `build()`: Builds and returns the event query - -#### UserQueryBuilder - -- `setModels(models: Model[])`: Sets the models for the user query -- `setAttributeOperator(operator: LogicalOperator)`: Sets the operator for combining attribute expressions -- `addAttributesExpression(expression: SingleModelExpression)`: Adds an expression to the query -- `build()`: Builds and returns the user query - -### Expression Factory - -- `createJoin(model: Model, expression: Expression)`: Creates a join expression -- `createNot(expression: Expression, model?: Model)`: Creates a unary expression (NOT) -- `createExists(operand: Operand, model?: Model)`: Creates an exists expression -- `createBinary(operator: BinaryOperator, left: Operand, right: Operand, model?: Model)`: Creates a binary expression -- `createModelAggregation(model: Model, operator: BinaryOperator, expression: Expression, aggregation: { operator: AggregationOperator, path: string }, right: Operand | { model: string, operator: AggregationOperator, path: string, expression: Expression })`: Creates a model aggregation expression -- `createLogical(operator: LogicalOperator, expressions: Expression[], model?: Model)`: Creates a logical expression (AND/OR) -- `createLocation(operator: LocationOperator, location: LocationOperand, path: { path: string }, model?: Model)`: Creates a location expression -- `createAnd(expressions: Expression[], model?: Model)`: Creates an AND expression -- `createOr(expressions: Expression[], model?: Model)`: Creates an OR expression - -### Operand Factory - -- `createPath(path: string)`: Creates a path operand -- `createDate(dateOperand: DateOperand)`: Creates a date operand -- `createArithmetic(operator: ArithmeticOperator, left: Operand, right: Operand)`: Creates an arithmetic operand -- `createAbsoluteDate(dateString: string)`: Creates an absolute date operand -- `createRelativeDate(offset: number, unit: string, boundary?: 'start' | 'end')`: Creates a relative date operand -- `createLocationPoint(latitude: number, longitude: number)`: Creates a location operand with latitude and longitude -- `createLocationWithMeters(latitude: number, longitude: number, meters: number)`: Creates a location operand with latitude, longitude, and distance in meters -- `createLocationWithMiles(latitude: number, longitude: number, miles: number)`: Creates a location operand with latitude, longitude, and distance in miles -- `createLocationWithKilometers(latitude: number, longitude: number, kilometers: number)`: Creates a location operand with latitude, longitude, and distance in kilometers - -### Model Factory - -- `createWithId(id: number, type: string)`: Creates a model with an ID and type -- `createWithName(name: string, type: string)`: Creates a model with a name and type -- `createModel(type: string, id: number, name?: string)`: Creates a model with type, ID, and optional name - -### Utility Functions - -- `createAudience()`: Creates a new AudienceBuilder instance -- `createLogicalQuery()`: Creates a new LogicalQueryBuilder instance -- `createGeneralQueryBuilder()`: Creates a new GeneralQueryBuilder instance -- `createEventQueryBuilder()`: Creates a new EventQueryBuilder instance -- `createUserQueryBuilder()`: Creates a new UserQueryBuilder instance -- `validateAudience(audience: Audience)`: Validates an Audience object -- `parseAudience(json: string)`: Parses a JSON string into an Audience object -- `stringifyAudience(audience: Audience)`: Converts an Audience object to a JSON string \ No newline at end of file diff --git a/sdk/typescript/package-lock.json b/sdk/typescript/package-lock.json deleted file mode 100644 index 5ecb05b..0000000 --- a/sdk/typescript/package-lock.json +++ /dev/null @@ -1,1628 +0,0 @@ -{ - "name": "@mparticle/audience-sdk-typescript", - "version": "1.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@mparticle/audience-sdk-typescript", - "version": "1.0.0", - "license": "Apache-2.0", - "dependencies": { - "@mparticle/audience-typescript-schema": "file:../typescript-schema" - }, - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.59.0", - "@typescript-eslint/parser": "^5.59.0", - "eslint": "^8.38.0", - "typescript": "^5.0.4" - } - }, - "../typescript-schema": { - "name": "@mparticle/audience-typescript-schema", - "version": "1.0.0", - "license": "Apache-2.0", - "devDependencies": { - "@semantic-release/changelog": "^6.0.3", - "@semantic-release/git": "^10.0.1", - "@semantic-release/github": "^9.2.6", - "@semantic-release/npm": "^11.0.2", - "semantic-release": "^23.0.2", - "typescript": "^5.0.4" - }, - "engines": { - "node": ">=20.8.1" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.6.1", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.6.1.tgz", - "integrity": "sha512-KTsJMmobmbrFLe3LDh0PC2FXpcSYJt/MLjlkh/9LEnmKYLSYmT/0EW9JWANjeoemiuZrmogti0tW5Ch+qNUYDw==", - "dev": true, - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", - "dev": true, - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/js": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", - "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.13.0", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", - "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "dependencies": { - "@humanwhocodes/object-schema": "^2.0.3", - "debug": "^4.3.1", - "minimatch": "^3.0.5" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", - "dev": true, - "engines": { - "node": ">=12.22" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", - "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true - }, - "node_modules/@mparticle/audience-typescript-schema": { - "resolved": "../typescript-schema", - "link": true - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@types/json-schema": { - "version": "7.0.15", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", - "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true - }, - "node_modules/@types/semver": { - "version": "7.7.0", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz", - "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==", - "dev": true - }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/scope-manager": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", - "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/type-utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", - "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", - "dev": true, - "dependencies": { - "@typescript-eslint/typescript-estree": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "*" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/types": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", - "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", - "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/visitor-keys": "5.62.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", - "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", - "dev": true, - "dependencies": { - "@typescript-eslint/types": "5.62.0", - "eslint-visitor-keys": "^3.3.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "dev": true - }, - "node_modules/acorn": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.1.tgz", - "integrity": "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg==", - "dev": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", - "dev": true, - "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", - "dev": true, - "dependencies": { - "esutils": "^2.0.2" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/eslint": { - "version": "8.57.1", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", - "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.1", - "@humanwhocodes/config-array": "^0.13.0", - "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", - "ajv": "^6.12.4", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "find-up": "^5.0.0", - "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.1.2", - "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" - }, - "bin": { - "eslint": "bin/eslint.js" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", - "dev": true, - "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", - "dev": true, - "dependencies": { - "estraverse": "^5.1.0" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "dependencies": { - "estraverse": "^5.2.0" - }, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true - }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", - "dev": true, - "dependencies": { - "flat-cache": "^3.0.4" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", - "dev": true, - "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" - }, - "engines": { - "node": "^10.12.0 || >=12.0.0" - } - }, - "node_modules/flatted": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", - "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", - "dev": true - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/graphemer": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", - "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "engines": { - "node": ">= 4" - } - }, - "node_modules/import-fresh": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", - "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", - "dev": true, - "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "dev": true, - "engines": { - "node": ">=0.8.19" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true - }, - "node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/json-stable-stringify-without-jsonify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", - "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true - }, - "node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", - "dev": true, - "dependencies": { - "json-buffer": "3.0.1" - } - }, - "node_modules/levn": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", - "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1", - "type-check": "~0.4.0" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.merge": { - "version": "4.6.2", - "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", - "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/natural-compare": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", - "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true - }, - "node_modules/natural-compare-lite": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", - "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", - "dev": true - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/optionator": { - "version": "0.9.4", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", - "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", - "dev": true, - "dependencies": { - "deep-is": "^0.1.3", - "fast-levenshtein": "^2.0.6", - "levn": "^0.4.1", - "prelude-ls": "^1.2.1", - "type-check": "^0.4.0", - "word-wrap": "^1.2.5" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parent-module": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", - "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", - "dev": true, - "dependencies": { - "callsites": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/prelude-ls": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", - "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", - "dev": true, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/punycode": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", - "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, - "node_modules/resolve-from": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", - "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", - "dev": true, - "engines": { - "node": ">=4" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "deprecated": "Rimraf versions prior to v4 are no longer supported", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/semver": { - "version": "7.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", - "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/type-check": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", - "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", - "dev": true, - "dependencies": { - "prelude-ls": "^1.2.1" - }, - "engines": { - "node": ">= 0.8.0" - } - }, - "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typescript": { - "version": "5.8.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.3.tgz", - "integrity": "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==", - "dev": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uri-js": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", - "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", - "dev": true, - "dependencies": { - "punycode": "^2.1.0" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/sdk/typescript/package.json b/sdk/typescript/package.json deleted file mode 100644 index 3c5c0af..0000000 --- a/sdk/typescript/package.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "name": "@mparticle/audience-sdk-typescript", - "version": "1.0.0", - "description": "TypeScript SDK for building and managing mParticle Audiences", - "main": "dist/index.js", - "types": "dist/index.d.ts", - "repository": { - "type": "git", - "url": "git+https://github.com/mParticle/audience-sdk.git" - }, - "keywords": [ - "audience" - ], - "license": "Apache-2.0", - "scripts": { - "build": "tsc", - "lint": "eslint src/**/*.ts" - }, - "dependencies": { - "@mparticle/audience-typescript-schema": "file:../typescript-schema" - }, - "devDependencies": { - "@typescript-eslint/eslint-plugin": "^5.59.0", - "@typescript-eslint/parser": "^5.59.0", - "eslint": "^8.38.0", - "typescript": "^5.0.4" - } - } \ No newline at end of file diff --git a/sdk/typescript/src/audience-builder.ts b/sdk/typescript/src/audience-builder.ts deleted file mode 100644 index 73d2923..0000000 --- a/sdk/typescript/src/audience-builder.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { Audience, LogicalAudienceExpression, Expression } from '@mparticle/audience-typescript-schema/audience'; -import { LogicalOperator } from '@mparticle/audience-typescript-schema/common/operator'; -import { VERSION } from '@mparticle/audience-typescript-schema/version'; - -export class AudienceBuilder { - private expressions: (LogicalAudienceExpression | Expression)[] = []; - private currentOperator: LogicalOperator = 'and'; - - /** - * Creates a new AudienceBuilder instance - */ - constructor() { } - - /** - * Sets the logical operator for combining queries - * @param operator The logical operator to use ('and' or 'or') - */ - setOperator(operator: LogicalOperator): this { - this.currentOperator = operator; - return this; - } - - /** - * Adds an expression to the audience - * @param expression The expression to add - */ - addExpression(expression: Expression): this { - this.expressions.push(expression); - return this; - } - - /** - * Adds a nested logical expression to the audience - * @param logicalExpression The logical expression to add - */ - addLogicalExpression(logicalExpression: LogicalAudienceExpression): this { - this.expressions.push(logicalExpression); - return this; - } - - /** - * Builds and returns the final Audience object - */ - build(): Audience { - if (this.expressions.length === 0) { - throw new Error('Cannot build an audience with no expressions'); - } - - return { - schema_version: VERSION, - audience: { - operator: this.currentOperator, - expressions: this.expressions - } - }; - } - - /** - * Creates a new logical query builder - */ - static createLogicalExpression(): LogicalExpressionBuilder { - return new LogicalExpressionBuilder(); - } -} - -export class LogicalExpressionBuilder { - private expressions: (LogicalAudienceExpression | Expression)[] = []; - private operator: LogicalOperator = 'and'; - - /** - * Sets the logical operator for the query - * @param operator The logical operator to use ('and' or 'or') - */ - setOperator(operator: LogicalOperator): this { - this.operator = operator; - return this; - } - - /** - * Adds an expression to the logical expression - * @param expression The expression to add - */ - addExpression(expression: Expression): this { - this.expressions.push(expression); - return this; - } - - /** - * Adds a nested logical expression - * @param logicalExpression The logical expression to add - */ - addLogicalExpression(logicalExpression: LogicalAudienceExpression): this { - this.expressions.push(logicalExpression); - return this; - } - - /** - * Builds and returns the logical query - */ - build(): LogicalAudienceExpression { - if (this.expressions.length === 0) { - throw new Error('Cannot build a logical expression with no expressions'); - } - - return { - operator: this.operator, - expressions: this.expressions - }; - } -} \ No newline at end of file diff --git a/sdk/typescript/src/expression-factory/count-expression-factory.ts b/sdk/typescript/src/expression-factory/count-expression-factory.ts deleted file mode 100644 index 0bc530e..0000000 --- a/sdk/typescript/src/expression-factory/count-expression-factory.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { CountExpression } from '@mparticle/audience-typescript-schema/expression/count-expression'; -import { Operand } from '@mparticle/audience-typescript-schema/operand/operand'; -import { BinaryOperator, LogicalOperator } from '@mparticle/audience-typescript-schema/common/operator'; - -/** - * Factory class for creating different types of count expressions - */ -export class CountExpressionFactory { - /** - * Creates a count expression with a binary operator - * @param operator The binary operator - * @param operand The operand to compare against - * @returns A count expression - */ - static createBinary( - operator: BinaryOperator, - operand: Operand - ): CountExpression { - return { operator, operand }; - } - - /** - * Creates a logical combination of count expressions - * @param operator The logical operator ('and' or 'or') - * @param expressions The count expressions to combine - * @returns A logical count expression - */ - static createLogical( - operator: LogicalOperator, - expressions: CountExpression[] - ): CountExpression { - return { operator, expressions }; - } - - /** - * Creates an AND logical combination of count expressions - * @param expressions The count expressions to combine - * @returns An AND logical count expression - */ - static createAnd(expressions: CountExpression[]): CountExpression { - return this.createLogical('and', expressions); - } - - /** - * Creates an OR logical combination of count expressions - * @param expressions The count expressions to combine - * @returns An OR logical count expression - */ - static createOr(expressions: CountExpression[]): CountExpression { - return this.createLogical('or', expressions); - } - - /** - * Creates a count expression with the specified operator and operand - * @param operator The operator to use - * @param operand The operand to compare against - * @returns A count expression - */ - static createWithOperator(operator: BinaryOperator, operand: Operand): CountExpression { - return this.createBinary(operator, operand); - } - - /** - * Creates a unary count expression - * @param operator The unary operator - * @param expression The expression to operate on - * @returns A unary count expression - */ - private static createUnary( - operator: 'not', - expression: CountExpression - ): CountExpression { - // This is a workaround since CountExpression doesn't directly support unary operators - // We'll create a logical expression with a single expression - return this.createAnd([expression]); - } -} \ No newline at end of file diff --git a/sdk/typescript/src/expression-factory/date-operand-factory.ts b/sdk/typescript/src/expression-factory/date-operand-factory.ts deleted file mode 100644 index b2df406..0000000 --- a/sdk/typescript/src/expression-factory/date-operand-factory.ts +++ /dev/null @@ -1,89 +0,0 @@ -import { DateOperand, AbsoluteDate, RelativeDate, DateUnit } from '@mparticle/audience-typescript-schema/operand/date-operand'; - -export class DateOperandFactory { - /** - * Creates an absolute date operand - * @param dateString The ISO 8601 date string - */ - static createAbsoluteDate(dateString: string): DateOperand { - const absoluteDate: AbsoluteDate = { - absolute: dateString - }; - return { date: absoluteDate }; - } - - /** - * Creates a relative date operand - * @param offset The number of units to offset - * @param unit The unit of time - * @param boundary Optional boundary specification - */ - static createRelativeDate( - offset: number, - unit: DateUnit, - boundary?: 'start' | 'end' - ): DateOperand { - const relativeDate: RelativeDate = { - relative: { - offset, - unit, - ...(boundary && { boundary }) - } - }; - return { date: relativeDate }; - } - - /** - * Creates a date operand for a specific number of days ago - * @param days The number of days ago - * @param boundary Optional boundary specification - */ - static daysAgo(days: number, boundary?: 'start' | 'end'): DateOperand { - return this.createRelativeDate(-days, 'day', boundary); - } - - /** - * Creates a date operand for a specific number of days in the future - * @param days The number of days in the future - * @param boundary Optional boundary specification - */ - static daysFromNow(days: number, boundary?: 'start' | 'end'): DateOperand { - return this.createRelativeDate(days, 'day', boundary); - } - - /** - * Creates a date operand for a specific number of months ago - * @param months The number of months ago - * @param boundary Optional boundary specification - */ - static monthsAgo(months: number, boundary?: 'start' | 'end'): DateOperand { - return this.createRelativeDate(-months, 'month', boundary); - } - - /** - * Creates a date operand for a specific number of months in the future - * @param months The number of months in the future - * @param boundary Optional boundary specification - */ - static monthsFromNow(months: number, boundary?: 'start' | 'end'): DateOperand { - return this.createRelativeDate(months, 'month', boundary); - } - - /** - * Creates a date operand for a specific number of years ago - * @param years The number of years ago - * @param boundary Optional boundary specification - */ - static yearsAgo(years: number, boundary?: 'start' | 'end'): DateOperand { - return this.createRelativeDate(-years, 'year', boundary); - } - - /** - * Creates a date operand for a specific number of years in the future - * @param years The number of years in the future - * @param boundary Optional boundary specification - */ - static yearsFromNow(years: number, boundary?: 'start' | 'end'): DateOperand { - return this.createRelativeDate(years, 'year', boundary); - } -} \ No newline at end of file diff --git a/sdk/typescript/src/expression-factory/expression-factory.ts b/sdk/typescript/src/expression-factory/expression-factory.ts deleted file mode 100644 index 10f4911..0000000 --- a/sdk/typescript/src/expression-factory/expression-factory.ts +++ /dev/null @@ -1,114 +0,0 @@ -import { Expression } from '@mparticle/audience-typescript-schema/expression/expression'; -import { Operand } from '@mparticle/audience-typescript-schema/operand/operand'; -import { BinaryOperator, LogicalOperator, LocationOperator, AggregationOperator } from '@mparticle/audience-typescript-schema/common/operator'; -import { LocationOperand } from '@mparticle/audience-typescript-schema/operand/location-operand'; -import { ModelPath } from '@mparticle/audience-typescript-schema/common/model-path'; - -/** - * Factory class for creating different types of expressions - */ -export class ExpressionFactory { - - /** - * Creates a unary expression (NOT) - * @param expression The expression to negate - * @param model Optional model - * @returns A unary expression - */ - static createNot(expression: Expression, model?: string): Expression { - return { model, operator: 'not', expression }; - } - - /** - * Creates an exists expression - * @param operand The operand to check for existence - * @param model Optional model - * @returns An exists expression - */ - static createExists(operand: Operand, model?: string): Expression { - return { model, operator: 'exists', operand }; - } - - /** - * Creates a binary expression - * @param operator The binary operator - * @param left The left operand - * @param right The right operand - * @param model Optional model - * @returns A binary expression - */ - static createBinary( - operator: BinaryOperator, - left: Operand, - right: Operand, - model?: string - ): Expression { - return { model, operator, left, right }; - } - - /** - * Creates a logical expression (AND/OR) - * @param operator The logical operator - * @param expressions The expressions to combine - * @param model Optional model - * @returns A logical expression - */ - static createLogical( - operator: LogicalOperator, - expressions: Expression[] - ): Expression { - return { operator, expressions }; - } - - /** - * Creates a location expression - * @param operator The location operator - * @param location The location operand - * @param model model - * @param path The path to compare against - * @returns A location expression - */ - static createLocation( - operator: LocationOperator, - location: LocationOperand, - model: string, - path: string, - ): Expression { - return { operator, left: location, right: { model, path } }; - } - - /** - * Creates an AND expression - * @param expressions The expressions to combine - * @returns An AND expression - */ - static createAnd(expressions: Expression[]): Expression { - return this.createLogical('and', expressions); - } - - /** - * Creates an OR expression - * @param expressions The expressions to combine - * @returns An OR expression - */ - static createOr(expressions: Expression[]): Expression { - return this.createLogical('or', expressions); - } - - /** - * Creates an aggregate expression - * @param operator The aggregation operator - * @param group_by The group by field - * @param expression The model path to aggregate - * @param condition The condition expression - * @returns An aggregate expression - */ - static createAggregate( - operator: AggregationOperator, - group_by: string, - expression: ModelPath, - condition: Expression - ): Expression { - return { operator, group_by, expression, condition }; - } -} \ No newline at end of file diff --git a/sdk/typescript/src/expression-factory/location-operand-factory.ts b/sdk/typescript/src/expression-factory/location-operand-factory.ts deleted file mode 100644 index 430df53..0000000 --- a/sdk/typescript/src/expression-factory/location-operand-factory.ts +++ /dev/null @@ -1,83 +0,0 @@ -import { LocationOperand } from '@mparticle/audience-typescript-schema/operand/location-operand'; -import { Location, DistanceUnit } from '@mparticle/audience-typescript-schema/common/location'; - -export class LocationOperandFactory { - /** - * Creates a location operand with latitude and longitude - * @param latitude The latitude - * @param longitude The longitude - */ - static createLocation(latitude: number, longitude: number): LocationOperand { - const location: Location = { - latitude, - longitude - }; - return { location }; - } - - /** - * Creates a location operand with latitude, longitude, and distance - * @param latitude The latitude - * @param longitude The longitude - * @param distanceValue The distance value - * @param distanceUnit The distance unit - */ - static createLocationWithDistance( - latitude: number, - longitude: number, - distanceValue: number, - distanceUnit: DistanceUnit - ): LocationOperand { - const location: Location = { - latitude, - longitude, - distance: { - value: distanceValue, - unit: distanceUnit - } - }; - return { location }; - } - - /** - * Creates a location operand with latitude, longitude, and distance in meters - * @param latitude The latitude - * @param longitude The longitude - * @param meters The distance in meters - */ - static createLocationWithMeters( - latitude: number, - longitude: number, - meters: number - ): LocationOperand { - return this.createLocationWithDistance(latitude, longitude, meters, 'meters'); - } - - /** - * Creates a location operand with latitude, longitude, and distance in miles - * @param latitude The latitude - * @param longitude The longitude - * @param miles The distance in miles - */ - static createLocationWithMiles( - latitude: number, - longitude: number, - miles: number - ): LocationOperand { - return this.createLocationWithDistance(latitude, longitude, miles, 'miles'); - } - - /** - * Creates a location operand with latitude, longitude, and distance in kilometers - * @param latitude The latitude - * @param longitude The longitude - * @param kilometers The distance in kilometers - */ - static createLocationWithKilometers( - latitude: number, - longitude: number, - kilometers: number - ): LocationOperand { - return this.createLocationWithDistance(latitude, longitude, kilometers, 'kilometers'); - } -} \ No newline at end of file diff --git a/sdk/typescript/src/expression-factory/operand-factory.ts b/sdk/typescript/src/expression-factory/operand-factory.ts deleted file mode 100644 index dbc43a3..0000000 --- a/sdk/typescript/src/expression-factory/operand-factory.ts +++ /dev/null @@ -1,127 +0,0 @@ -import { Operand } from '@mparticle/audience-typescript-schema/operand/operand'; -import { DateOperand } from '@mparticle/audience-typescript-schema/operand/date-operand'; -import { LocationOperand } from '@mparticle/audience-typescript-schema/operand/location-operand'; -import { ArithmeticOperator } from '@mparticle/audience-typescript-schema/common/operator'; -import { DateOperandFactory } from './date-operand-factory'; -import { LocationOperandFactory } from './location-operand-factory'; -/** - * Factory class for creating different types of operands - */ -export class OperandFactory { - - /** - * Creates a model and path operand - * @param path The path to reference - * @returns A path operand - */ - static createModelPath(model: string, path: string): Operand { - return { model, path }; - } - - /** - * Creates a date operand - * @param dateOperand The date operand - * @returns A date operand - */ - static createDate(dateOperand: DateOperand): Operand { - return dateOperand; - } - - /** - * Creates an arithmetic operand - * @param operator The arithmetic operator - * @param left The left operand - * @param right The right operand - * @returns An arithmetic operand - */ - static createArithmetic( - operator: ArithmeticOperator, - left: Operand, - right: Operand - ): Operand { - return { - operator, - left, - right - }; - } - - /** - * Creates an absolute date operand - * @param dateString The ISO 8601 date string - * @returns A date operand - */ - static createAbsoluteDate(dateString: string): DateOperand { - return DateOperandFactory.createAbsoluteDate(dateString); - } - - /** - * Creates a relative date operand - * @param offset The number of units to offset - * @param unit The unit of time - * @param boundary Optional boundary specification - * @returns A date operand - */ - static createRelativeDate( - offset: number, - unit: string, - boundary?: 'start' | 'end' - ): DateOperand { - return DateOperandFactory.createRelativeDate(offset, unit as any, boundary); - } - - /** - * Creates a location operand with latitude and longitude - * @param latitude The latitude - * @param longitude The longitude - * @returns A location operand - */ - static createLocationPoint(latitude: number, longitude: number): LocationOperand { - return LocationOperandFactory.createLocation(latitude, longitude); - } - - /** - * Creates a location operand with latitude, longitude, and distance in meters - * @param latitude The latitude - * @param longitude The longitude - * @param meters The distance in meters - * @returns A location operand - */ - static createLocationWithMeters( - latitude: number, - longitude: number, - meters: number - ): LocationOperand { - return LocationOperandFactory.createLocationWithMeters(latitude, longitude, meters); - } - - /** - * Creates a location operand with latitude, longitude, and distance in miles - * @param latitude The latitude - * @param longitude The longitude - * @param miles The distance in miles - * @returns A location operand - */ - static createLocationWithMiles( - latitude: number, - longitude: number, - miles: number - ): LocationOperand { - return LocationOperandFactory.createLocationWithMiles(latitude, longitude, miles); - } - - /** - * Creates a location operand with latitude, longitude, and distance in kilometers - * @param latitude The latitude - * @param longitude The longitude - * @param kilometers The distance in kilometers - * @returns A location operand - */ - static createLocationWithKilometers( - latitude: number, - longitude: number, - kilometers: number - ): LocationOperand { - return LocationOperandFactory.createLocationWithKilometers(latitude, longitude, kilometers); - } -} \ No newline at end of file diff --git a/sdk/typescript/src/expression-factory/path-expression-factory.ts b/sdk/typescript/src/expression-factory/path-expression-factory.ts deleted file mode 100644 index a337964..0000000 --- a/sdk/typescript/src/expression-factory/path-expression-factory.ts +++ /dev/null @@ -1,45 +0,0 @@ -import { PathExpression } from '@mparticle/audience-typescript-schema/expression/path-expression'; -import { Operand } from '@mparticle/audience-typescript-schema/operand/operand'; -import { UnaryOperator, BinaryOperator } from '@mparticle/audience-typescript-schema/common/operator'; -import { Expression } from '@mparticle/audience-typescript-schema/expression/expression'; - -/** - * Factory class for creating different types of path expressions - */ -export class PathExpressionFactory { - - /** - * Creates a unary path expression - * @param operator The unary operator - * @param expression The expression to operate on - * @returns A unary path expression - */ - static createUnary( - operator: UnaryOperator, - expression: PathExpression - ): PathExpression { - return { operator, expression }; - } - - /** - * Creates a binary path expression - * @param operator The binary operator - * @param operand The operand to operate on - * @returns A binary path expression - */ - static createBinary( - operator: BinaryOperator, - operand: Operand - ): PathExpression { - return { operator, operand }; - } - - /** - * Creates a NOT path expression - * @param expression The expression to negate - * @returns A NOT path expression - */ - static createNot(expression: PathExpression): PathExpression { - return this.createUnary('not', expression); - } -} \ No newline at end of file diff --git a/sdk/typescript/src/index.ts b/sdk/typescript/src/index.ts deleted file mode 100644 index a035801..0000000 --- a/sdk/typescript/src/index.ts +++ /dev/null @@ -1,73 +0,0 @@ -import { AudienceBuilder } from './audience-builder'; -import { LogicalExpressionBuilder } from './audience-builder'; -import { QueryBuilder } from './query-builders/query-builder'; -import { Audience } from '@mparticle/audience-typescript-schema'; -/** - * Validates an Audience object - * @param audience The audience to validate - * @returns true if the audience is valid, false otherwise - */ -export function validateAudience(audience: Audience): boolean { - try { - // Ensure the audience has the required structure - if (!audience.schema_version || !audience.audience || !audience.audience.operator || !audience.audience.queries) { - return false; - } - - // Validate that there is at least one query - if (audience.audience.queries.length === 0) { - return false; - } - - // Validate that the operator is either 'and' or 'or' - if (audience.audience.operator !== 'and' && audience.audience.operator !== 'or') { - return false; - } - - return true; - } catch (error) { - return false; - } -} - -/** - * Parses a JSON string into an Audience object - * @param json The JSON string to parse - * @returns The parsed Audience object - * @throws Error if the JSON is invalid or doesn't match the Audience type - */ -export function parseAudience(json: string): Audience { - try { - const audience = JSON.parse(json) as Audience; - if (!validateAudience(audience)) { - throw new Error('Invalid audience structure'); - } - return audience; - } catch (error) { - throw new Error('Failed to parse audience JSON'); - } -} - -/** - * Converts an Audience object to a JSON string - * @param audience The audience to convert - * @returns The JSON string representation of the audience - * @throws Error if the audience is invalid - */ -export function stringifyAudience(audience: Audience): string { - if (!validateAudience(audience)) { - throw new Error('Invalid audience'); - } - return JSON.stringify(audience, null, 2); -} - -export { CountExpressionFactory } from './expression-factory/count-expression-factory'; -export { DateOperandFactory } from './expression-factory/date-operand-factory'; -export { ExpressionFactory } from './expression-factory/expression-factory'; -export { LocationOperandFactory } from './expression-factory/location-operand-factory'; -export { OperandFactory } from './expression-factory/operand-factory'; -export { PathExpressionFactory } from './expression-factory/path-expression-factory'; - -export { QueryBuilder } from './query-builders/query-builder'; - -export { AudienceBuilder } from './audience-builder'; \ No newline at end of file diff --git a/sdk/typescript/src/query-builders/query-builder.ts b/sdk/typescript/src/query-builders/query-builder.ts deleted file mode 100644 index 55afc54..0000000 --- a/sdk/typescript/src/query-builders/query-builder.ts +++ /dev/null @@ -1,39 +0,0 @@ -import { Query } from '@mparticle/audience-typescript-schema/query/query'; -import { Expression } from '@mparticle/audience-typescript-schema/expression/expression'; - -export class QueryBuilder { - protected model?: string; - protected expression?: Expression; - - /** - * Sets the models for the query - * @param models The model names, IDs, or model objects with type - */ - setModel(model: string): this { - this.model = model; - return this; - } - - /** - * Sets the expression for the query - * @param expression The expression to use - */ - setExpression(expression: Expression): this { - this.expression = expression; - return this; - } - - /** - * Builds and returns the query - */ - build(): Query { - if (!this.model) { - throw new Error('Model is required for a general query'); - } - - return { - model: this.model, - ...(this.expression && { expression: this.expression }) - }; - } -} \ No newline at end of file diff --git a/sdk/typescript/tsconfig.json b/sdk/typescript/tsconfig.json deleted file mode 100644 index c88826f..0000000 --- a/sdk/typescript/tsconfig.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "compilerOptions": { - "target": "es2018", - "module": "commonjs", - "declaration": true, - "outDir": "./dist", - "strict": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "rootDir": "./src" - }, - "include": ["src/**/*"], - "exclude": ["node_modules", "dist", "**/*.test.ts"] -} \ No newline at end of file From 9bf7f7b1872034b4a23c37c857d369a96695727e Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Mon, 30 Jun 2025 15:40:09 -0700 Subject: [PATCH 09/16] Update with audience changes --- schema/audience-definition-schema.json | 90 ++++++++++++++----- .../mp_audience_sdk/models/audience_models.py | 48 +++++++--- sdk/typescript-schema/audience.ts | 4 +- .../expression/audience-expression.ts | 15 ---- .../expression/boolean-expression.ts | 24 +++-- .../expression/expression.ts | 6 +- .../expression/number-expression.ts | 4 +- .../literal/audience-operand.ts | 8 -- sdk/typescript-schema/literal/audience.ts | 9 ++ .../literal/model-operand.ts | 3 - sdk/typescript-schema/literal/model-path.ts | 8 ++ .../schema/audience-schema.json | 90 ++++++++++++++----- 12 files changed, 209 insertions(+), 100 deletions(-) delete mode 100644 sdk/typescript-schema/expression/audience-expression.ts delete mode 100644 sdk/typescript-schema/literal/audience-operand.ts create mode 100644 sdk/typescript-schema/literal/audience.ts delete mode 100644 sdk/typescript-schema/literal/model-operand.ts diff --git a/schema/audience-definition-schema.json b/schema/audience-definition-schema.json index 3e747f8..7980716 100644 --- a/schema/audience-definition-schema.json +++ b/schema/audience-definition-schema.json @@ -19,7 +19,7 @@ "additionalProperties": false, "properties": { "condition": { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" }, "group_by_model": { "type": "string" @@ -56,7 +56,7 @@ "description": "Represents a complete audience definition with a root logical expression.\nExamples:\n1. Simple audience:\n{\n\"schema_version\": \"1.0.0\",\n\"audience\": {\n\"operator\": \"and\",\n\"expressions\": [\n{ \"model\": \"user\", \"expression\": { \"operator\": \"exists\", \"operand\": { \"path\": \"id\" } } },\n{ \"model\": \"purchase\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } }\n]\n}\n}\n\n2. Audience with nested logic:\n{\n\"schema_version\": \"1.0.0\",\n\"audience\": {\n\"operator\": \"or\",\n\"expressions\": [\n{ \"model\": \"user\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" } },\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"model\": \"signup\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } },\n{ \"model\": \"user\", \"expression\": { \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 } }\n]\n}\n]\n}\n}", "properties": { "audience": { - "$ref": "#/definitions/BooleanExpression", + "$ref": "#/definitions/BoolExpression", "title": "Audience" }, "schema_version": { @@ -70,6 +70,27 @@ "title": "AudienceDefinition", "type": "object" }, + "AudienceBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/ModelReference" + }, + "operator": { + "$ref": "#/definitions/AudienceOperator" + }, + "right": { + "$ref": "#/definitions/AudienceReference" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "AudienceBoolExpression", + "type": "object" + }, "AudienceOperator": { "description": "Represents operators that work with audiences. Examples:\n- \"in\": { audience: 12345, model: \"users\" }", "enum": [ @@ -78,6 +99,20 @@ ], "type": "string" }, + "AudienceReference": { + "additionalProperties": false, + "description": "Represents an audience. Audience is identified by a string ID.\nExample:\n{ \"audience\": \"12345\" }", + "properties": { + "audience": { + "type": "string" + } + }, + "required": [ + "audience" + ], + "title": "AudienceReference", + "type": "object" + }, "BinaryNumberExpression": { "additionalProperties": false, "properties": { @@ -110,7 +145,7 @@ ], "type": "string" }, - "BooleanExpression": { + "BoolExpression": { "anyOf": [ { "type": "boolean" @@ -137,10 +172,10 @@ "$ref": "#/definitions/LogicalManyBoolExpression" }, { - "$ref": "#/definitions/LocationBooleanExpression" + "$ref": "#/definitions/LocationBoolExpression" } ], - "title": "BooleanExpression" + "title": "BoolExpression" }, "DateBoolExpression": { "additionalProperties": false, @@ -233,7 +268,7 @@ "Expression": { "anyOf": [ { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" }, { "$ref": "#/definitions/DateExpression" @@ -243,9 +278,6 @@ }, { "$ref": "#/definitions/LocationExpression" - }, - { - "$ref": "#/definitions/ModelPath" } ], "description": "Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n\"model\": \"user\",\n\"expression\": {\n\"operator\": \"equals\",\n\"left\": { \"path\": \"age\" },\n\"right\": 18\n}\n}\n\n2. Logical expression (AND):\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" },\n{ \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 }\n]\n}\n\n3. Location expression:\n{\n\"operator\": \"within\",\n\"left\": { \"location\": { \"latitude\": 37.7749, \"longitude\": -122.4194, \"distance\": { \"value\": 10, \"unit\": \"miles\" } } },\n\"right\": { \"model\": \"user\", \"path\": \"location\" }\n}", @@ -321,15 +353,7 @@ "title": "Location", "type": "object" }, - "LocationBoolOperator": { - "description": "Represents operators for location-based comparisons. Examples:\n- \"within\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 }\n- \"equals\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } }", - "enum": [ - "within", - "equals" - ], - "type": "string" - }, - "LocationBooleanExpression": { + "LocationBoolExpression": { "additionalProperties": false, "properties": { "left": { @@ -347,9 +371,17 @@ "left", "right" ], - "title": "LocationBooleanExpression", + "title": "LocationBoolExpression", "type": "object" }, + "LocationBoolOperator": { + "description": "Represents operators for location-based comparisons. Examples:\n- \"within\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 }\n- \"equals\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } }", + "enum": [ + "within", + "equals" + ], + "type": "string" + }, "LocationExpression": { "anyOf": [ { @@ -366,13 +398,13 @@ "additionalProperties": false, "properties": { "left": { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" }, "operator": { "$ref": "#/definitions/LogicalBoolOperator" }, "right": { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" } }, "required": [ @@ -396,7 +428,7 @@ "properties": { "expressions": { "items": { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" }, "type": "array" }, @@ -429,6 +461,20 @@ "title": "ModelPath", "type": "object" }, + "ModelReference": { + "additionalProperties": false, + "description": "Represents a model reference within a data model", + "properties": { + "model": { + "type": "string" + } + }, + "required": [ + "model" + ], + "title": "ModelReference", + "type": "object" + }, "NumberBoolExpression": { "additionalProperties": false, "properties": { diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index cd7e779..7dd6efc 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-06-30T22:28:49+00:00 +# timestamp: 2025-06-30T22:38:00+00:00 from __future__ import annotations @@ -35,6 +35,13 @@ class AudienceOperator(Enum): not_in = "not_in" +class AudienceReference(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + audience: str + + class BinaryNumberOperator(Enum): plus = "plus" minus = "minus" @@ -104,6 +111,13 @@ class ModelPath(BaseModel): path: str +class ModelReference(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + model: str + + class NumberBoolOperator(Enum): equals = "equals" not_equals = "not_equals" @@ -166,6 +180,15 @@ class IsValidAudienceObject(BaseModel): named_args: NamedArgs | None = Field(None, alias="namedArgs") +class AudienceBoolExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + left: ModelReference + operator: AudienceOperator + right: AudienceReference + + class DateLiteralExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -194,7 +217,7 @@ class StringBoolExpression(BaseModel): right: str | ModelPath = Field(..., title="StringExpression") -class LocationBooleanExpression(BaseModel): +class LocationBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) @@ -241,9 +264,9 @@ class AggregateNumberExpression(BaseModel): | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression - | LocationBooleanExpression + | LocationBoolExpression | None - ) = Field(None, title="BooleanExpression") + ) = Field(None, title="BoolExpression") group_by_model: str operand: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( Field( @@ -268,7 +291,7 @@ class AudienceDefinition(BaseModel): | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression - | LocationBooleanExpression + | LocationBoolExpression ) = Field(..., title="Audience") schema_version: str @@ -307,8 +330,8 @@ class LogicalBoolExpression(BaseModel): | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression - | LocationBooleanExpression - ) = Field(..., title="BooleanExpression") + | LocationBoolExpression + ) = Field(..., title="BoolExpression") operator: LogicalBoolOperator right: ( bool @@ -319,8 +342,8 @@ class LogicalBoolExpression(BaseModel): | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression - | LocationBooleanExpression - ) = Field(..., title="BooleanExpression") + | LocationBoolExpression + ) = Field(..., title="BoolExpression") class LogicalManyBoolExpression(BaseModel): @@ -336,7 +359,7 @@ class LogicalManyBoolExpression(BaseModel): | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression - | LocationBooleanExpression + | LocationBoolExpression ] operator: LogicalBoolOperator @@ -367,8 +390,7 @@ class UnaryBoolExpression(BaseModel): extra="forbid", ) operand: ( - ModelPath - | bool + bool | ModelPath | UnaryBoolExpression | NumberBoolExpression @@ -376,7 +398,7 @@ class UnaryBoolExpression(BaseModel): | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression - | LocationBooleanExpression + | LocationBoolExpression | DateLiteralExpression | ModelPath | float diff --git a/sdk/typescript-schema/audience.ts b/sdk/typescript-schema/audience.ts index 5aee5c2..dbec840 100644 --- a/sdk/typescript-schema/audience.ts +++ b/sdk/typescript-schema/audience.ts @@ -1,5 +1,5 @@ import { Version } from "./common/version"; -import { BooleanExpression } from "./expression/boolean-expression"; +import { BoolExpression } from "./expression/boolean-expression"; /** * Represents a logical combination of audience expressions using AND/OR operators. @@ -83,5 +83,5 @@ export type Audience = { /** * @title Audience */ - audience: BooleanExpression + audience: BoolExpression } diff --git a/sdk/typescript-schema/expression/audience-expression.ts b/sdk/typescript-schema/expression/audience-expression.ts deleted file mode 100644 index 34aba90..0000000 --- a/sdk/typescript-schema/expression/audience-expression.ts +++ /dev/null @@ -1,15 +0,0 @@ -// import { AudienceOperand } from "../operand/audience-operand"; -// import { ModelOperand } from "../operand/model-operand"; -// import { AudienceOperator } from "../common/operator"; - - -// /** -// * Represents an expression that operates on an audience and returns a boolean. -// * Example: -// * { -// * operator: "in", -// * expression: { operator: "in", left: { model: "user" }, right": { audience: 12345 } } -// * } -// */ -// export type AudienceExpression = -// { operator: AudienceOperator, left: ModelOperand, right: AudienceOperand } diff --git a/sdk/typescript-schema/expression/boolean-expression.ts b/sdk/typescript-schema/expression/boolean-expression.ts index 6618e15..1d4a582 100644 --- a/sdk/typescript-schema/expression/boolean-expression.ts +++ b/sdk/typescript-schema/expression/boolean-expression.ts @@ -1,5 +1,6 @@ -import { LocationBoolOperator, LogicalBoolOperator, NumberBoolOperator, StringBoolOperator, UnaryBoolOperator } from "../common/operator"; -import { ModelPath } from "../literal/model-path"; +import { AudienceOperator as AudienceBoolOperator, LocationBoolOperator, LogicalBoolOperator, NumberBoolOperator, StringBoolOperator, UnaryBoolOperator } from "../common/operator"; +import { AudienceReference } from "../literal/audience"; +import { ModelPath, ModelReference } from "../literal/model-path"; import { DateExpression } from "./date-expression"; import { Expression } from "./expression"; import { LocationExpression } from "./location-expression"; @@ -29,22 +30,27 @@ export type DateBoolExpression = { operator: NumberBoolOperator, left: DateExpre /** * @title LogicalBoolExpression */ -export type LogicalBoolExpression = { operator: LogicalBoolOperator, left: BooleanExpression, right: BooleanExpression } +export type LogicalBoolExpression = { operator: LogicalBoolOperator, left: BoolExpression, right: BoolExpression } /** * @title LogicalManyBoolExpression */ -export type LogicalManyBoolExpression = { operator: LogicalBoolOperator, expressions: BooleanExpression[] } +export type LogicalManyBoolExpression = { operator: LogicalBoolOperator, expressions: BoolExpression[] } /** - * @title LocationBooleanExpression + * @title LocationBoolExpression */ -export type LocationBooleanExpression = { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } +export type LocationBoolExpression = { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } /** - * @title BooleanExpression +* @title AudienceBoolExpression */ -export type BooleanExpression = +export type AudienceBoolExpression = { operator: AudienceBoolOperator, left: ModelReference, right: AudienceReference } + +/** + * @title BoolExpression + */ +export type BoolExpression = boolean | ModelPath | UnaryBoolExpression @@ -53,5 +59,5 @@ export type BooleanExpression = | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression - | LocationBooleanExpression + | LocationBoolExpression // TODO: | { operator: ListBoolOperator, left: Expression, right: ListExpression } diff --git a/sdk/typescript-schema/expression/expression.ts b/sdk/typescript-schema/expression/expression.ts index b53bf97..8188edc 100644 --- a/sdk/typescript-schema/expression/expression.ts +++ b/sdk/typescript-schema/expression/expression.ts @@ -1,8 +1,7 @@ -import { BooleanExpression } from "./boolean-expression"; +import { BoolExpression } from "./boolean-expression"; import { DateExpression } from "./date-expression"; import { NumberExpression } from "./number-expression"; import { LocationExpression } from "./location-expression"; -import { ModelPath } from "../literal/model-path"; /** * @title Expression @@ -35,8 +34,7 @@ import { ModelPath } from "../literal/model-path"; * } */ export type Expression = - BooleanExpression + BoolExpression | DateExpression | NumberExpression | LocationExpression - | ModelPath diff --git a/sdk/typescript-schema/expression/number-expression.ts b/sdk/typescript-schema/expression/number-expression.ts index a082907..85cbf99 100644 --- a/sdk/typescript-schema/expression/number-expression.ts +++ b/sdk/typescript-schema/expression/number-expression.ts @@ -1,5 +1,5 @@ import { AggregationNumberOperator, BinaryNumberOperator } from "../common/operator"; -import { BooleanExpression } from "./boolean-expression"; +import { BoolExpression } from "./boolean-expression"; import { ModelPath } from "../literal/model-path"; /** @@ -10,7 +10,7 @@ export type BinaryNumberExpression = { operator: BinaryNumberOperator, left: Num /** * @title AggregateNumberExpression */ -export type AggregateNumberExpression = { operator: AggregationNumberOperator, group_by_model: string, operand: NumberExpression, condition?: BooleanExpression } +export type AggregateNumberExpression = { operator: AggregationNumberOperator, group_by_model: string, operand: NumberExpression, condition?: BoolExpression } /** * @title NumberExpression diff --git a/sdk/typescript-schema/literal/audience-operand.ts b/sdk/typescript-schema/literal/audience-operand.ts deleted file mode 100644 index e234404..0000000 --- a/sdk/typescript-schema/literal/audience-operand.ts +++ /dev/null @@ -1,8 +0,0 @@ -/** - * Represents an audience. Audience is identified by a string ID. - * Example: - * { "audience": "12345" } - */ -export type AudienceOperand = { - audience: string -} diff --git a/sdk/typescript-schema/literal/audience.ts b/sdk/typescript-schema/literal/audience.ts new file mode 100644 index 0000000..7097a81 --- /dev/null +++ b/sdk/typescript-schema/literal/audience.ts @@ -0,0 +1,9 @@ +/** + * @title AudienceReference + * @description Represents an audience. Audience is identified by a string ID. + * Example: + * { "audience": "12345" } + */ +export type AudienceReference = { + audience: string +} diff --git a/sdk/typescript-schema/literal/model-operand.ts b/sdk/typescript-schema/literal/model-operand.ts deleted file mode 100644 index 6615940..0000000 --- a/sdk/typescript-schema/literal/model-operand.ts +++ /dev/null @@ -1,3 +0,0 @@ -export type ModelOperand = { - model: string -} diff --git a/sdk/typescript-schema/literal/model-path.ts b/sdk/typescript-schema/literal/model-path.ts index c775ffb..66eafff 100644 --- a/sdk/typescript-schema/literal/model-path.ts +++ b/sdk/typescript-schema/literal/model-path.ts @@ -15,3 +15,11 @@ export type ModelPath = { model: string, path: string } + +/** + * @title ModelReference + * @description Represents a model reference within a data model + */ +export type ModelReference = { + model: string +} diff --git a/sdk/typescript-schema/schema/audience-schema.json b/sdk/typescript-schema/schema/audience-schema.json index 3e747f8..7980716 100644 --- a/sdk/typescript-schema/schema/audience-schema.json +++ b/sdk/typescript-schema/schema/audience-schema.json @@ -19,7 +19,7 @@ "additionalProperties": false, "properties": { "condition": { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" }, "group_by_model": { "type": "string" @@ -56,7 +56,7 @@ "description": "Represents a complete audience definition with a root logical expression.\nExamples:\n1. Simple audience:\n{\n\"schema_version\": \"1.0.0\",\n\"audience\": {\n\"operator\": \"and\",\n\"expressions\": [\n{ \"model\": \"user\", \"expression\": { \"operator\": \"exists\", \"operand\": { \"path\": \"id\" } } },\n{ \"model\": \"purchase\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } }\n]\n}\n}\n\n2. Audience with nested logic:\n{\n\"schema_version\": \"1.0.0\",\n\"audience\": {\n\"operator\": \"or\",\n\"expressions\": [\n{ \"model\": \"user\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" } },\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"model\": \"signup\", \"expression\": { \"operator\": \"equals\", \"left\": { \"path\": \"status\" }, \"right\": \"completed\" } },\n{ \"model\": \"user\", \"expression\": { \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 } }\n]\n}\n]\n}\n}", "properties": { "audience": { - "$ref": "#/definitions/BooleanExpression", + "$ref": "#/definitions/BoolExpression", "title": "Audience" }, "schema_version": { @@ -70,6 +70,27 @@ "title": "AudienceDefinition", "type": "object" }, + "AudienceBoolExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/ModelReference" + }, + "operator": { + "$ref": "#/definitions/AudienceOperator" + }, + "right": { + "$ref": "#/definitions/AudienceReference" + } + }, + "required": [ + "operator", + "left", + "right" + ], + "title": "AudienceBoolExpression", + "type": "object" + }, "AudienceOperator": { "description": "Represents operators that work with audiences. Examples:\n- \"in\": { audience: 12345, model: \"users\" }", "enum": [ @@ -78,6 +99,20 @@ ], "type": "string" }, + "AudienceReference": { + "additionalProperties": false, + "description": "Represents an audience. Audience is identified by a string ID.\nExample:\n{ \"audience\": \"12345\" }", + "properties": { + "audience": { + "type": "string" + } + }, + "required": [ + "audience" + ], + "title": "AudienceReference", + "type": "object" + }, "BinaryNumberExpression": { "additionalProperties": false, "properties": { @@ -110,7 +145,7 @@ ], "type": "string" }, - "BooleanExpression": { + "BoolExpression": { "anyOf": [ { "type": "boolean" @@ -137,10 +172,10 @@ "$ref": "#/definitions/LogicalManyBoolExpression" }, { - "$ref": "#/definitions/LocationBooleanExpression" + "$ref": "#/definitions/LocationBoolExpression" } ], - "title": "BooleanExpression" + "title": "BoolExpression" }, "DateBoolExpression": { "additionalProperties": false, @@ -233,7 +268,7 @@ "Expression": { "anyOf": [ { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" }, { "$ref": "#/definitions/DateExpression" @@ -243,9 +278,6 @@ }, { "$ref": "#/definitions/LocationExpression" - }, - { - "$ref": "#/definitions/ModelPath" } ], "description": "Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n\"model\": \"user\",\n\"expression\": {\n\"operator\": \"equals\",\n\"left\": { \"path\": \"age\" },\n\"right\": 18\n}\n}\n\n2. Logical expression (AND):\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" },\n{ \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 }\n]\n}\n\n3. Location expression:\n{\n\"operator\": \"within\",\n\"left\": { \"location\": { \"latitude\": 37.7749, \"longitude\": -122.4194, \"distance\": { \"value\": 10, \"unit\": \"miles\" } } },\n\"right\": { \"model\": \"user\", \"path\": \"location\" }\n}", @@ -321,15 +353,7 @@ "title": "Location", "type": "object" }, - "LocationBoolOperator": { - "description": "Represents operators for location-based comparisons. Examples:\n- \"within\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 }\n- \"equals\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } }", - "enum": [ - "within", - "equals" - ], - "type": "string" - }, - "LocationBooleanExpression": { + "LocationBoolExpression": { "additionalProperties": false, "properties": { "left": { @@ -347,9 +371,17 @@ "left", "right" ], - "title": "LocationBooleanExpression", + "title": "LocationBoolExpression", "type": "object" }, + "LocationBoolOperator": { + "description": "Represents operators for location-based comparisons. Examples:\n- \"within\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 }, radius: 5 }\n- \"equals\": { location1: { lat: 40, lng: -74 }, location2: { lat: 40, lng: -74 } }", + "enum": [ + "within", + "equals" + ], + "type": "string" + }, "LocationExpression": { "anyOf": [ { @@ -366,13 +398,13 @@ "additionalProperties": false, "properties": { "left": { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" }, "operator": { "$ref": "#/definitions/LogicalBoolOperator" }, "right": { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" } }, "required": [ @@ -396,7 +428,7 @@ "properties": { "expressions": { "items": { - "$ref": "#/definitions/BooleanExpression" + "$ref": "#/definitions/BoolExpression" }, "type": "array" }, @@ -429,6 +461,20 @@ "title": "ModelPath", "type": "object" }, + "ModelReference": { + "additionalProperties": false, + "description": "Represents a model reference within a data model", + "properties": { + "model": { + "type": "string" + } + }, + "required": [ + "model" + ], + "title": "ModelReference", + "type": "object" + }, "NumberBoolExpression": { "additionalProperties": false, "properties": { From 319cf39586d956acab5445794b7bc94fd72273c3 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Mon, 30 Jun 2025 15:40:55 -0700 Subject: [PATCH 10/16] Update version --- sdk/python/pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdk/python/pyproject.toml b/sdk/python/pyproject.toml index ed71aba..43747bc 100644 --- a/sdk/python/pyproject.toml +++ b/sdk/python/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "mp_audience_sdk" -version = "0.2.7" +version = "0.3.0" description = "mParticle Audience SDK" readme = "README.md" requires-python = ">=3.11" From d4fb5a9b8764afd8c298b8df7dc7e70529b628b0 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Mon, 30 Jun 2025 16:29:41 -0700 Subject: [PATCH 11/16] Add back expressions --- .../mp_audience_sdk/models/audience_models.py | 211 +++++++----------- 1 file changed, 84 insertions(+), 127 deletions(-) diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index 7dd6efc..8a12a4a 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-06-30T22:38:00+00:00 +# timestamp: 2025-06-30T23:29:20+00:00 from __future__ import annotations @@ -162,6 +162,10 @@ class StringBoolOperator(Enum): not_in = "not_in" +class StringExpression(RootModel[str | ModelPath]): + root: str | ModelPath = Field(..., title="StringExpression") + + class UnaryBoolOperator(Enum): null = "null" not_null = "not_null" @@ -169,6 +173,10 @@ class UnaryBoolOperator(Enum): not_exists = "not_exists" +class Version(RootModel[str]): + root: str + + class NamedArgs(BaseModel): model_config = ConfigDict( extra="forbid", @@ -189,6 +197,10 @@ class AudienceBoolExpression(BaseModel): right: AudienceReference +class DateLiteral(RootModel[AbsoluteDate | RelativeDate]): + root: AbsoluteDate | RelativeDate = Field(..., title="DateLiteral") + + class DateLiteralExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -196,15 +208,19 @@ class DateLiteralExpression(BaseModel): date: AbsoluteDate | RelativeDate -class Literal( - RootModel[bool | float | str | ModelPath | Location | AbsoluteDate | RelativeDate] -): - root: bool | float | str | ModelPath | Location | AbsoluteDate | RelativeDate = ( - Field( - ..., - description='Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n"hello"\n\n2. Path reference:\n{ path: "user.age" }\n\n3. Arithmetic operation:\n{\noperator: "plus",\nleft: { path: "price" },\nright: { path: "tax" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: "multiply",\nleft: { operator: "plus", left: { path: "base_price" }, right: { path: "shipping" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: "2023-01-01T00:00:00Z" } }', - title="Literal", - ) +class Literal(RootModel[bool | float | str | DateLiteral | ModelPath | Location]): + root: bool | float | str | DateLiteral | ModelPath | Location = Field( + ..., + description='Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n"hello"\n\n2. Path reference:\n{ path: "user.age" }\n\n3. Arithmetic operation:\n{\noperator: "plus",\nleft: { path: "price" },\nright: { path: "tax" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: "multiply",\nleft: { operator: "plus", left: { path: "base_price" }, right: { path: "shipping" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: "2023-01-01T00:00:00Z" } }', + title="Literal", + ) + + +class LocationExpression(RootModel[Location | ModelPath]): + root: Location | ModelPath = Field( + ..., + description='Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator:\n{ operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations:\n{\noperator: "or",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } },\n{ operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } }\n]\n}', + title="LocationExpression", ) @@ -212,69 +228,44 @@ class StringBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: str | ModelPath = Field(..., title="StringExpression") + left: StringExpression operator: StringBoolOperator - right: str | ModelPath = Field(..., title="StringExpression") + right: StringExpression + + +class DateExpression(RootModel[DateLiteralExpression | ModelPath]): + root: DateLiteralExpression | ModelPath = Field( + ..., + description='Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator:\n{ operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates:\n{\noperator: "and",\nexpressions: [\n{ absolute: "2023-01-01T00:00:00Z" },\n{ operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } }\n]\n}', + title="BooleanExpression", + ) class LocationBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: Location | ModelPath = Field( - ..., - description='Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator:\n{ operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations:\n{\noperator: "or",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } },\n{ operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } }\n]\n}', - title="LocationExpression", - ) + left: LocationExpression operator: LocationBoolOperator - right: Location | ModelPath = Field( - ..., - description='Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator:\n{ operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations:\n{\noperator: "or",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } },\n{ operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } }\n]\n}', - title="LocationExpression", - ) + right: LocationExpression class DateBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: DateLiteralExpression | ModelPath = Field( - ..., - description='Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator:\n{ operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates:\n{\noperator: "and",\nexpressions: [\n{ absolute: "2023-01-01T00:00:00Z" },\n{ operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } }\n]\n}', - title="BooleanExpression", - ) + left: DateExpression operator: NumberBoolOperator - right: DateLiteralExpression | ModelPath = Field( - ..., - description='Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator:\n{ operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates:\n{\noperator: "and",\nexpressions: [\n{ absolute: "2023-01-01T00:00:00Z" },\n{ operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } }\n]\n}', - title="BooleanExpression", - ) + right: DateExpression class AggregateNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - condition: ( - bool - | ModelPath - | UnaryBoolExpression - | NumberBoolExpression - | StringBoolExpression - | DateBoolExpression - | LogicalBoolExpression - | LogicalManyBoolExpression - | LocationBoolExpression - | None - ) = Field(None, title="BoolExpression") + condition: BoolExpression | None = None group_by_model: str - operand: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( - Field( - ..., - description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', - title="NumberExpression", - ) - ) + operand: NumberExpression operator: AggregationNumberOperator @@ -282,46 +273,21 @@ class AudienceDefinition(BaseModel): model_config = ConfigDict( extra="forbid", ) - audience: ( - bool - | ModelPath - | UnaryBoolExpression - | NumberBoolExpression - | StringBoolExpression - | DateBoolExpression - | LogicalBoolExpression - | LogicalManyBoolExpression - | LocationBoolExpression - ) = Field(..., title="Audience") - schema_version: str + audience: BoolExpression = Field(..., title="Audience") + schema_version: Version class BinaryNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( - Field( - ..., - description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', - title="NumberExpression", - ) - ) + left: NumberExpression operator: BinaryNumberOperator - right: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( - Field( - ..., - description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', - title="NumberExpression", - ) - ) + right: NumberExpression -class LogicalBoolExpression(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - left: ( +class BoolExpression( + RootModel[ bool | ModelPath | UnaryBoolExpression @@ -331,9 +297,9 @@ class LogicalBoolExpression(BaseModel): | LogicalBoolExpression | LogicalManyBoolExpression | LocationBoolExpression - ) = Field(..., title="BoolExpression") - operator: LogicalBoolOperator - right: ( + ] +): + root: ( bool | ModelPath | UnaryBoolExpression @@ -346,21 +312,32 @@ class LogicalBoolExpression(BaseModel): ) = Field(..., title="BoolExpression") +class Expression( + RootModel[BoolExpression | DateExpression | NumberExpression | LocationExpression] +): + root: BoolExpression | DateExpression | NumberExpression | LocationExpression = ( + Field( + ..., + description='Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n"model": "user",\n"expression": {\n"operator": "equals",\n"left": { "path": "age" },\n"right": 18\n}\n}\n\n2. Logical expression (AND):\n{\n"operator": "and",\n"expressions": [\n{ "operator": "equals", "left": { "path": "country" }, "right": "US" },\n{ "operator": "greater_than", "left": { "path": "age" }, "right": 18 }\n]\n}\n\n3. Location expression:\n{\n"operator": "within",\n"left": { "location": { "latitude": 37.7749, "longitude": -122.4194, "distance": { "value": 10, "unit": "miles" } } },\n"right": { "model": "user", "path": "location" }\n}', + title="Expression", + ) + ) + + +class LogicalBoolExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + left: BoolExpression + operator: LogicalBoolOperator + right: BoolExpression + + class LogicalManyBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - expressions: List[ - bool - | ModelPath - | UnaryBoolExpression - | NumberBoolExpression - | StringBoolExpression - | DateBoolExpression - | LogicalBoolExpression - | LogicalManyBoolExpression - | LocationBoolExpression - ] + expressions: List[BoolExpression] operator: LogicalBoolOperator @@ -368,15 +345,15 @@ class NumberBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( - Field( - ..., - description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', - title="NumberExpression", - ) - ) + left: NumberExpression operator: NumberBoolOperator - right: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( + right: NumberExpression + + +class NumberExpression( + RootModel[float | ModelPath | BinaryNumberExpression | AggregateNumberExpression] +): + root: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( Field( ..., description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', @@ -389,33 +366,13 @@ class UnaryBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) - operand: ( - bool - | ModelPath - | UnaryBoolExpression - | NumberBoolExpression - | StringBoolExpression - | DateBoolExpression - | LogicalBoolExpression - | LogicalManyBoolExpression - | LocationBoolExpression - | DateLiteralExpression - | ModelPath - | float - | ModelPath - | BinaryNumberExpression - | AggregateNumberExpression - | Location - | ModelPath - ) = Field( - ..., - description='Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n"model": "user",\n"expression": {\n"operator": "equals",\n"left": { "path": "age" },\n"right": 18\n}\n}\n\n2. Logical expression (AND):\n{\n"operator": "and",\n"expressions": [\n{ "operator": "equals", "left": { "path": "country" }, "right": "US" },\n{ "operator": "greater_than", "left": { "path": "age" }, "right": 18 }\n]\n}\n\n3. Location expression:\n{\n"operator": "within",\n"left": { "location": { "latitude": 37.7749, "longitude": -122.4194, "distance": { "value": 10, "unit": "miles" } } },\n"right": { "model": "user", "path": "location" }\n}', - title="Expression", - ) + operand: Expression operator: UnaryBoolOperator AggregateNumberExpression.model_rebuild() AudienceDefinition.model_rebuild() BinaryNumberExpression.model_rebuild() +BoolExpression.model_rebuild() +Expression.model_rebuild() NumberBoolExpression.model_rebuild() From 2bd78543d31400651542db6ebca80f7828275a4e Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Mon, 30 Jun 2025 16:46:14 -0700 Subject: [PATCH 12/16] Add type fixing script + fix union types --- Makefile | 3 +- sdk/python/fixup_types.py | 124 ++++++++++++++++++ .../mp_audience_sdk/models/audience_models.py | 30 ++--- 3 files changed, 137 insertions(+), 20 deletions(-) create mode 100644 sdk/python/fixup_types.py diff --git a/Makefile b/Makefile index 95ea77e..052b3f3 100644 --- a/Makefile +++ b/Makefile @@ -4,6 +4,7 @@ PYTHON_OUTPUT_DIR := sdk/python/mp_audience_sdk/models SCHEMA_FILE := schema/audience-definition-schema.json PYTHON_OUTPUT_FILE := $(PYTHON_OUTPUT_DIR)/audience_models.py TYPESCRIPT_SCHEMA_DIR := sdk/typescript-schema +PYTHON_FIX_TYPE_FILE := sdk/python/fixup_types.py build: build-typescript generate-python-models test @@ -24,8 +25,8 @@ generate-python-models: --field-constraints \ --snake-case-field \ --encoding utf-8 \ - --collapse-root-models \ --use-union-operator + python $(PYTHON_FIX_TYPE_FILE) $(PYTHON_OUTPUT_FILE) black $(PYTHON_OUTPUT_DIR) test: diff --git a/sdk/python/fixup_types.py b/sdk/python/fixup_types.py new file mode 100644 index 0000000..2192ac3 --- /dev/null +++ b/sdk/python/fixup_types.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 + +""" +Script to fix RootModel[...] types by wrapping the content in quotes. +Handles both single-line and multi-line type definitions. +Usage: python fixup_types.py +""" + +from collections.abc import Iterable +import sys +import os +import re +import argparse +from pathlib import Path + +ROOT_MODEL_TEXT = "RootModel[" + +def quote_root_model_types(lines: Iterable[str]) -> Iterable[str]: + bracket_count = 0 + acc_line = "" + for line in lines: + cur_idx = 0 + if bracket_count == 0: + root_model_idx = line.find(ROOT_MODEL_TEXT) + + if root_model_idx == -1: + yield line + continue + + cur_idx = root_model_idx + len(ROOT_MODEL_TEXT) + bracket_count = 1 + yield line[:cur_idx] + + for i in range(cur_idx, len(line)): + c = line[i] + + if c == "[": + bracket_count += 1 + elif c == "]": + bracket_count -= 1 + + if bracket_count == 0: + cleaned_line = re.sub(r'[ \t]+', " ", acc_line).replace("\n", "").strip() + yield f'"{cleaned_line}"]' + line[i + 1:] + acc_line = "" + break + + else: + acc_line += c + + +def process_file(file_path: Path): + """Process a single Python file.""" + print(f"Processing: {file_path}") + + try: + # Read the file + with open(file_path, 'r', encoding='utf-8') as f: + original_lines = f.readlines() + + # Fix RootModel types + fixed_lines = list(quote_root_model_types(original_lines)) + + if original_lines != fixed_lines: + # Write the fixed content back + with open(file_path, 'w', encoding='utf-8') as f: + f.writelines(fixed_lines) + + else: + print(f" - No RootModel types found in {file_path}") + + except Exception as e: + print(f" Error processing {file_path}: {e}") + + +def main(): + parser = argparse.ArgumentParser( + description="Fix RootModel[...] types by wrapping content in quotes" + ) + parser.add_argument( + 'target', + help='File or directory to process' + ) + parser.add_argument( + '--dry-run', + action='store_true', + help='Show what would be changed without making changes' + ) + + args = parser.parse_args() + target_path = Path(args.target) + + if not target_path.exists(): + print(f"Error: {target_path} does not exist") + sys.exit(1) + + if target_path.is_file(): + # Single file + if target_path.suffix == '.py': + process_file(target_path) + else: + print(f"Warning: {target_path} is not a Python file") + + elif target_path.is_dir(): + # Directory - find all .py files + print(f"Searching for Python files in: {target_path}") + py_files = list(target_path.rglob('*.py')) + + if not py_files: + print("No Python files found") + return + + for py_file in py_files: + process_file(py_file) + + else: + print(f"Error: {target_path} is neither a file nor a directory") + sys.exit(1) + + print("Done!") + + +if __name__ == "__main__": + main() diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index 8a12a4a..75e8999 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-06-30T23:29:20+00:00 +# timestamp: 2025-06-30T23:44:09+00:00 from __future__ import annotations @@ -10,7 +10,7 @@ from pydantic import BaseModel, ConfigDict, Field, RootModel -class Model(RootModel[Any]): +class Model(RootModel["Any"]): root: Any @@ -162,7 +162,7 @@ class StringBoolOperator(Enum): not_in = "not_in" -class StringExpression(RootModel[str | ModelPath]): +class StringExpression(RootModel["str | ModelPath"]): root: str | ModelPath = Field(..., title="StringExpression") @@ -173,7 +173,7 @@ class UnaryBoolOperator(Enum): not_exists = "not_exists" -class Version(RootModel[str]): +class Version(RootModel["str"]): root: str @@ -197,7 +197,7 @@ class AudienceBoolExpression(BaseModel): right: AudienceReference -class DateLiteral(RootModel[AbsoluteDate | RelativeDate]): +class DateLiteral(RootModel["AbsoluteDate | RelativeDate"]): root: AbsoluteDate | RelativeDate = Field(..., title="DateLiteral") @@ -208,7 +208,7 @@ class DateLiteralExpression(BaseModel): date: AbsoluteDate | RelativeDate -class Literal(RootModel[bool | float | str | DateLiteral | ModelPath | Location]): +class Literal(RootModel["bool | float | str | DateLiteral | ModelPath | Location"]): root: bool | float | str | DateLiteral | ModelPath | Location = Field( ..., description='Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n"hello"\n\n2. Path reference:\n{ path: "user.age" }\n\n3. Arithmetic operation:\n{\noperator: "plus",\nleft: { path: "price" },\nright: { path: "tax" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: "multiply",\nleft: { operator: "plus", left: { path: "base_price" }, right: { path: "shipping" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: "2023-01-01T00:00:00Z" } }', @@ -216,7 +216,7 @@ class Literal(RootModel[bool | float | str | DateLiteral | ModelPath | Location] ) -class LocationExpression(RootModel[Location | ModelPath]): +class LocationExpression(RootModel["Location | ModelPath"]): root: Location | ModelPath = Field( ..., description='Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator:\n{ operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations:\n{\noperator: "or",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } },\n{ operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } }\n]\n}', @@ -233,7 +233,7 @@ class StringBoolExpression(BaseModel): right: StringExpression -class DateExpression(RootModel[DateLiteralExpression | ModelPath]): +class DateExpression(RootModel["DateLiteralExpression | ModelPath"]): root: DateLiteralExpression | ModelPath = Field( ..., description='Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator:\n{ operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates:\n{\noperator: "and",\nexpressions: [\n{ absolute: "2023-01-01T00:00:00Z" },\n{ operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } }\n]\n}', @@ -288,15 +288,7 @@ class BinaryNumberExpression(BaseModel): class BoolExpression( RootModel[ - bool - | ModelPath - | UnaryBoolExpression - | NumberBoolExpression - | StringBoolExpression - | DateBoolExpression - | LogicalBoolExpression - | LogicalManyBoolExpression - | LocationBoolExpression + "bool | ModelPath | UnaryBoolExpression | NumberBoolExpression | StringBoolExpression | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression | LocationBoolExpression" ] ): root: ( @@ -313,7 +305,7 @@ class BoolExpression( class Expression( - RootModel[BoolExpression | DateExpression | NumberExpression | LocationExpression] + RootModel["BoolExpression | DateExpression | NumberExpression | LocationExpression"] ): root: BoolExpression | DateExpression | NumberExpression | LocationExpression = ( Field( @@ -351,7 +343,7 @@ class NumberBoolExpression(BaseModel): class NumberExpression( - RootModel[float | ModelPath | BinaryNumberExpression | AggregateNumberExpression] + RootModel["float | ModelPath | BinaryNumberExpression | AggregateNumberExpression"] ): root: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( Field( From a14e27a2b0d3a25c1e0f2b915e3d3aac75e38e23 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Mon, 30 Jun 2025 17:24:41 -0700 Subject: [PATCH 13/16] Change how expression is defined --- schema/audience-definition-schema.json | 222 ++++++++++++------ .../mp_audience_sdk/models/audience_models.py | 152 ++++++++---- sdk/python/tests/test_audience_models.py | 6 +- .../expression/boolean-expression.ts | 36 ++- .../expression/date-expression.ts | 31 +-- .../expression/expression.ts | 75 +++--- .../expression/location-expression.ts | 25 +- .../expression/number-expression.ts | 25 +- .../expression/string-expression.ts | 9 +- .../schema/audience-schema.json | 222 ++++++++++++------ 10 files changed, 496 insertions(+), 307 deletions(-) diff --git a/schema/audience-definition-schema.json b/schema/audience-definition-schema.json index 7980716..ecd0df1 100644 --- a/schema/audience-definition-schema.json +++ b/schema/audience-definition-schema.json @@ -15,6 +15,10 @@ "title": "AbsoluteDate", "type": "object" }, + "AggregateExpression": { + "$ref": "#/definitions/AggregateNumberExpression", + "title": "AggregateExpression" + }, "AggregateNumberExpression": { "additionalProperties": false, "properties": { @@ -113,6 +117,37 @@ "title": "AudienceReference", "type": "object" }, + "BinaryBoolExpression": { + "anyOf": [ + { + "$ref": "#/definitions/AudienceBoolExpression" + }, + { + "$ref": "#/definitions/LocationBoolExpression" + }, + { + "$ref": "#/definitions/DateBoolExpression" + }, + { + "$ref": "#/definitions/StringBoolExpression" + }, + { + "$ref": "#/definitions/NumberBoolExpression" + } + ], + "title": "BoolBinaryExpression" + }, + "BinaryExpression": { + "anyOf": [ + { + "$ref": "#/definitions/BinaryBoolExpression" + }, + { + "$ref": "#/definitions/BinaryNumberExpression" + } + ], + "title": "BinaryExpression" + }, "BinaryNumberExpression": { "additionalProperties": false, "properties": { @@ -148,31 +183,16 @@ "BoolExpression": { "anyOf": [ { - "type": "boolean" - }, - { - "$ref": "#/definitions/ModelPath" + "$ref": "#/definitions/ValueBoolExpression" }, { "$ref": "#/definitions/UnaryBoolExpression" }, { - "$ref": "#/definitions/NumberBoolExpression" - }, - { - "$ref": "#/definitions/StringBoolExpression" + "$ref": "#/definitions/BinaryBoolExpression" }, { - "$ref": "#/definitions/DateBoolExpression" - }, - { - "$ref": "#/definitions/LogicalBoolExpression" - }, - { - "$ref": "#/definitions/LogicalManyBoolExpression" - }, - { - "$ref": "#/definitions/LocationBoolExpression" + "$ref": "#/definitions/ManyBoolExpression" } ], "title": "BoolExpression" @@ -199,16 +219,9 @@ "type": "object" }, "DateExpression": { - "anyOf": [ - { - "$ref": "#/definitions/DateLiteralExpression" - }, - { - "$ref": "#/definitions/ModelPath" - } - ], - "description": "Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: \"day\" } }\n\n3. Date with binary operator:\n{ operator: \"greater_than\", operand: { absolute: \"2023-01-01T00:00:00Z\" } }\n\n4. Logical combination of dates:\n{\noperator: \"and\",\nexpressions: [\n{ absolute: \"2023-01-01T00:00:00Z\" },\n{ operator: \"less_than\", operand: { relative: { offset: 0, unit: \"month\", boundary: \"end\" } } }\n]\n}", - "title": "BooleanExpression" + "$ref": "#/definitions/ValueDateExpression", + "description": "Represents an expression that evaluates to a date", + "title": "DateExpression" }, "DateLiteral": { "anyOf": [ @@ -221,26 +234,6 @@ ], "title": "DateLiteral" }, - "DateLiteralExpression": { - "additionalProperties": false, - "properties": { - "date": { - "anyOf": [ - { - "$ref": "#/definitions/AbsoluteDate" - }, - { - "$ref": "#/definitions/RelativeDate" - } - ] - } - }, - "required": [ - "date" - ], - "title": "DateLiteralExpression", - "type": "object" - }, "DateUnit": { "description": "Represents units of time that can be used in relative date calculations.\nExamples:\n- 'second': 1 second\n- 'minute': 60 seconds\n- 'hour': 60 minutes\n- 'day': 24 hours\n- 'week': 7 days\n- 'month': ~30 days\n- 'quarter': 3 months\n- 'year': 12 months", "enum": [ @@ -268,19 +261,19 @@ "Expression": { "anyOf": [ { - "$ref": "#/definitions/BoolExpression" + "$ref": "#/definitions/ValueExpression" }, { - "$ref": "#/definitions/DateExpression" + "$ref": "#/definitions/UnaryExpression" }, { - "$ref": "#/definitions/NumberExpression" + "$ref": "#/definitions/BinaryExpression" }, { - "$ref": "#/definitions/LocationExpression" + "$ref": "#/definitions/ManyExpression" } ], - "description": "Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n\"model\": \"user\",\n\"expression\": {\n\"operator\": \"equals\",\n\"left\": { \"path\": \"age\" },\n\"right\": 18\n}\n}\n\n2. Logical expression (AND):\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" },\n{ \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 }\n]\n}\n\n3. Location expression:\n{\n\"operator\": \"within\",\n\"left\": { \"location\": { \"latitude\": 37.7749, \"longitude\": -122.4194, \"distance\": { \"value\": 10, \"unit\": \"miles\" } } },\n\"right\": { \"model\": \"user\", \"path\": \"location\" }\n}", + "description": "Represents an expression that accepts a variety of arguments and evaluates to a value.", "title": "Expression" }, "ListBoolOperator": { @@ -383,15 +376,8 @@ "type": "string" }, "LocationExpression": { - "anyOf": [ - { - "$ref": "#/definitions/Location" - }, - { - "$ref": "#/definitions/ModelPath" - } - ], - "description": "Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }\n\n2. Location with operator:\n{ operator: \"within\", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Logical combination of locations:\n{\noperator: \"or\",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } },\n{ operator: \"within\", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: \"miles\" } } }\n]\n}", + "$ref": "#/definitions/ValueLocationExpression", + "description": "Represents an expression that evaluates to a location or location-based condition.", "title": "LocationExpression" }, "LogicalBoolExpression": { @@ -443,6 +429,14 @@ "title": "LogicalManyBoolExpression", "type": "object" }, + "ManyBoolExpression": { + "$ref": "#/definitions/LogicalManyBoolExpression", + "title": "ManyBoolExpression" + }, + "ManyExpression": { + "$ref": "#/definitions/ManyBoolExpression", + "title": "ManyExpression" + }, "ModelPath": { "additionalProperties": false, "description": "Represents a model path reference within a data model.\nExamples:\n1. Simple model path:\n{ \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path:\n{ \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path:\n{ \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", @@ -511,10 +505,7 @@ "NumberExpression": { "anyOf": [ { - "type": "number" - }, - { - "$ref": "#/definitions/ModelPath" + "$ref": "#/definitions/ValueNumberExpression" }, { "$ref": "#/definitions/BinaryNumberExpression" @@ -523,7 +514,7 @@ "$ref": "#/definitions/AggregateNumberExpression" } ], - "description": "Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n\n3. Logical group of count expressions:\n{\noperator: \"and\",\nexpressions: [\n1,\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n]\n}", + "description": "Represents an expression that evaluates to a number.", "title": "NumberExpression" }, "RelativeDate": { @@ -598,14 +589,7 @@ "type": "string" }, "StringExpression": { - "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/ModelPath" - } - ], + "$ref": "#/definitions/ValueStringExpression", "title": "StringExpression" }, "UnaryBoolExpression": { @@ -635,6 +619,94 @@ ], "type": "string" }, + "UnaryExpression": { + "$ref": "#/definitions/UnaryBoolExpression", + "title": "UnaryExpression" + }, + "ValueBoolExpression": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueBoolExpression" + }, + "ValueDateExpression": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "date": { + "$ref": "#/definitions/DateLiteral" + } + }, + "required": [ + "date" + ], + "type": "object" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueDateExpression" + }, + "ValueExpression": { + "anyOf": [ + { + "$ref": "#/definitions/ValueBoolExpression" + }, + { + "$ref": "#/definitions/ValueDateExpression" + }, + { + "$ref": "#/definitions/ValueLocationExpression" + }, + { + "$ref": "#/definitions/ValueNumberExpression" + }, + { + "$ref": "#/definitions/ValueStringExpression" + } + ], + "title": "ValueExpression" + }, + "ValueLocationExpression": { + "anyOf": [ + { + "$ref": "#/definitions/Location" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueLocationExpression" + }, + "ValueNumberExpression": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueNumberExpression" + }, + "ValueStringExpression": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueStringExpression" + }, "Version": { "type": [ "string" diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index 75e8999..b1622a5 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-06-30T23:44:09+00:00 +# timestamp: 2025-07-01T00:24:24+00:00 from __future__ import annotations @@ -162,10 +162,6 @@ class StringBoolOperator(Enum): not_in = "not_in" -class StringExpression(RootModel["str | ModelPath"]): - root: str | ModelPath = Field(..., title="StringExpression") - - class UnaryBoolOperator(Enum): null = "null" not_null = "not_null" @@ -173,6 +169,22 @@ class UnaryBoolOperator(Enum): not_exists = "not_exists" +class ValueBoolExpression(RootModel["bool | ModelPath"]): + root: bool | ModelPath = Field(..., title="ValueBoolExpression") + + +class ValueLocationExpression(RootModel["Location | ModelPath"]): + root: Location | ModelPath = Field(..., title="ValueLocationExpression") + + +class ValueNumberExpression(RootModel["float | ModelPath"]): + root: float | ModelPath = Field(..., title="ValueNumberExpression") + + +class ValueStringExpression(RootModel["str | ModelPath"]): + root: str | ModelPath = Field(..., title="ValueStringExpression") + + class Version(RootModel["str"]): root: str @@ -201,13 +213,6 @@ class DateLiteral(RootModel["AbsoluteDate | RelativeDate"]): root: AbsoluteDate | RelativeDate = Field(..., title="DateLiteral") -class DateLiteralExpression(BaseModel): - model_config = ConfigDict( - extra="forbid", - ) - date: AbsoluteDate | RelativeDate - - class Literal(RootModel["bool | float | str | DateLiteral | ModelPath | Location"]): root: bool | float | str | DateLiteral | ModelPath | Location = Field( ..., @@ -216,28 +221,48 @@ class Literal(RootModel["bool | float | str | DateLiteral | ModelPath | Location ) -class LocationExpression(RootModel["Location | ModelPath"]): - root: Location | ModelPath = Field( +class LocationExpression(RootModel["ValueLocationExpression"]): + root: ValueLocationExpression = Field( ..., - description='Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }\n\n2. Location with operator:\n{ operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } }\n\n3. Logical combination of locations:\n{\noperator: "or",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } },\n{ operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } }\n]\n}', + description="Represents an expression that evaluates to a location or location-based condition.", title="LocationExpression", ) -class StringBoolExpression(BaseModel): +class StringExpression(RootModel["ValueStringExpression"]): + root: ValueStringExpression = Field(..., title="StringExpression") + + +class ValueDateExpression1(BaseModel): model_config = ConfigDict( extra="forbid", ) - left: StringExpression - operator: StringBoolOperator - right: StringExpression + date: DateLiteral + + +class ValueDateExpression(RootModel["ValueDateExpression1 | ModelPath"]): + root: ValueDateExpression1 | ModelPath = Field(..., title="ValueDateExpression") -class DateExpression(RootModel["DateLiteralExpression | ModelPath"]): - root: DateLiteralExpression | ModelPath = Field( +class ValueExpression( + RootModel[ + "ValueBoolExpression | ValueDateExpression | ValueLocationExpression | ValueNumberExpression | ValueStringExpression" + ] +): + root: ( + ValueBoolExpression + | ValueDateExpression + | ValueLocationExpression + | ValueNumberExpression + | ValueStringExpression + ) = Field(..., title="ValueExpression") + + +class DateExpression(RootModel["ValueDateExpression"]): + root: ValueDateExpression = Field( ..., - description='Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: "2023-01-01T00:00:00Z" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: "day" } }\n\n3. Date with binary operator:\n{ operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } }\n\n4. Logical combination of dates:\n{\noperator: "and",\nexpressions: [\n{ absolute: "2023-01-01T00:00:00Z" },\n{ operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } }\n]\n}', - title="BooleanExpression", + description="Represents an expression that evaluates to a date", + title="DateExpression", ) @@ -250,6 +275,15 @@ class LocationBoolExpression(BaseModel): right: LocationExpression +class StringBoolExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + left: StringExpression + operator: StringBoolOperator + right: StringExpression + + class DateBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -259,6 +293,10 @@ class DateBoolExpression(BaseModel): right: DateExpression +class AggregateExpression(RootModel["AggregateNumberExpression"]): + root: AggregateNumberExpression = Field(..., title="AggregateExpression") + + class AggregateNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -277,6 +315,26 @@ class AudienceDefinition(BaseModel): schema_version: Version +class BinaryBoolExpression( + RootModel[ + "AudienceBoolExpression | LocationBoolExpression | DateBoolExpression | StringBoolExpression | NumberBoolExpression" + ] +): + root: ( + AudienceBoolExpression + | LocationBoolExpression + | DateBoolExpression + | StringBoolExpression + | NumberBoolExpression + ) = Field(..., title="BoolBinaryExpression") + + +class BinaryExpression(RootModel["BinaryBoolExpression | BinaryNumberExpression"]): + root: BinaryBoolExpression | BinaryNumberExpression = Field( + ..., title="BinaryExpression" + ) + + class BinaryNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -288,31 +346,24 @@ class BinaryNumberExpression(BaseModel): class BoolExpression( RootModel[ - "bool | ModelPath | UnaryBoolExpression | NumberBoolExpression | StringBoolExpression | DateBoolExpression | LogicalBoolExpression | LogicalManyBoolExpression | LocationBoolExpression" + "ValueBoolExpression | UnaryBoolExpression | BinaryBoolExpression | ManyBoolExpression" ] ): root: ( - bool - | ModelPath + ValueBoolExpression | UnaryBoolExpression - | NumberBoolExpression - | StringBoolExpression - | DateBoolExpression - | LogicalBoolExpression - | LogicalManyBoolExpression - | LocationBoolExpression + | BinaryBoolExpression + | ManyBoolExpression ) = Field(..., title="BoolExpression") class Expression( - RootModel["BoolExpression | DateExpression | NumberExpression | LocationExpression"] + RootModel["ValueExpression | UnaryExpression | BinaryExpression | ManyExpression"] ): - root: BoolExpression | DateExpression | NumberExpression | LocationExpression = ( - Field( - ..., - description='Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n"model": "user",\n"expression": {\n"operator": "equals",\n"left": { "path": "age" },\n"right": 18\n}\n}\n\n2. Logical expression (AND):\n{\n"operator": "and",\n"expressions": [\n{ "operator": "equals", "left": { "path": "country" }, "right": "US" },\n{ "operator": "greater_than", "left": { "path": "age" }, "right": 18 }\n]\n}\n\n3. Location expression:\n{\n"operator": "within",\n"left": { "location": { "latitude": 37.7749, "longitude": -122.4194, "distance": { "value": 10, "unit": "miles" } } },\n"right": { "model": "user", "path": "location" }\n}', - title="Expression", - ) + root: ValueExpression | UnaryExpression | BinaryExpression | ManyExpression = Field( + ..., + description="Represents an expression that accepts a variety of arguments and evaluates to a value.", + title="Expression", ) @@ -333,6 +384,14 @@ class LogicalManyBoolExpression(BaseModel): operator: LogicalBoolOperator +class ManyBoolExpression(RootModel["LogicalManyBoolExpression"]): + root: LogicalManyBoolExpression = Field(..., title="ManyBoolExpression") + + +class ManyExpression(RootModel["ManyBoolExpression"]): + root: ManyBoolExpression = Field(..., title="ManyExpression") + + class NumberBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -343,12 +402,14 @@ class NumberBoolExpression(BaseModel): class NumberExpression( - RootModel["float | ModelPath | BinaryNumberExpression | AggregateNumberExpression"] + RootModel[ + "ValueNumberExpression | BinaryNumberExpression | AggregateNumberExpression" + ] ): - root: float | ModelPath | BinaryNumberExpression | AggregateNumberExpression = ( + root: ValueNumberExpression | BinaryNumberExpression | AggregateNumberExpression = ( Field( ..., - description='Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: "greater_than", operand: { path: "event.count" } }\n\n3. Logical group of count expressions:\n{\noperator: "and",\nexpressions: [\n1,\n{ operator: "greater_than", operand: { path: "event.count" } }\n]\n}', + description="Represents an expression that evaluates to a number.", title="NumberExpression", ) ) @@ -362,8 +423,15 @@ class UnaryBoolExpression(BaseModel): operator: UnaryBoolOperator +class UnaryExpression(RootModel["UnaryBoolExpression"]): + root: UnaryBoolExpression = Field(..., title="UnaryExpression") + + +AggregateExpression.model_rebuild() AggregateNumberExpression.model_rebuild() AudienceDefinition.model_rebuild() +BinaryBoolExpression.model_rebuild() +BinaryExpression.model_rebuild() BinaryNumberExpression.model_rebuild() BoolExpression.model_rebuild() Expression.model_rebuild() diff --git a/sdk/python/tests/test_audience_models.py b/sdk/python/tests/test_audience_models.py index 7826666..551adf3 100644 --- a/sdk/python/tests/test_audience_models.py +++ b/sdk/python/tests/test_audience_models.py @@ -14,7 +14,7 @@ NumberBoolOperator, Relative, RelativeDate, - DateLiteralExpression, + ValueDateExpression, StringBoolExpression, StringBoolOperator, ) @@ -187,13 +187,13 @@ def test_user_query_with_single_model(): absolute_date_expr = DateBoolExpression( operator=NumberBoolOperator.equals, left=ModelPath(model="user", path="registration_date"), - right=DateLiteralExpression(date=AbsoluteDate(absolute="2024-01-15T00:00:00Z")), + right=ValueDateExpression(date=AbsoluteDate(absolute="2024-01-15T00:00:00Z")), ) relative_date_expr = DateBoolExpression( operator=NumberBoolOperator.greater_than_equal, left=ModelPath(model="user", path="last_seen_date"), - right=DateLiteralExpression( + right=ValueDateExpression( date=RelativeDate(relative=Relative(offset=-30, unit=DateUnit.day)) ), ) diff --git a/sdk/typescript-schema/expression/boolean-expression.ts b/sdk/typescript-schema/expression/boolean-expression.ts index 1d4a582..b7c3579 100644 --- a/sdk/typescript-schema/expression/boolean-expression.ts +++ b/sdk/typescript-schema/expression/boolean-expression.ts @@ -7,6 +7,11 @@ import { LocationExpression } from "./location-expression"; import { NumberExpression } from "./number-expression"; import { StringExpression } from "./string-expression"; +/** + * @title ValueBoolExpression + */ +export type ValueBoolExpression = boolean | ModelPath + /** * @title UnaryBoolExpression */ @@ -32,11 +37,6 @@ export type DateBoolExpression = { operator: NumberBoolOperator, left: DateExpre */ export type LogicalBoolExpression = { operator: LogicalBoolOperator, left: BoolExpression, right: BoolExpression } -/** - * @title LogicalManyBoolExpression - */ -export type LogicalManyBoolExpression = { operator: LogicalBoolOperator, expressions: BoolExpression[] } - /** * @title LocationBoolExpression */ @@ -47,17 +47,27 @@ export type LocationBoolExpression = { operator: LocationBoolOperator, left: Loc */ export type AudienceBoolExpression = { operator: AudienceBoolOperator, left: ModelReference, right: AudienceReference } +/** + * @title BoolBinaryExpression + */ +export type BinaryBoolExpression = AudienceBoolExpression | LocationBoolExpression | LocationBoolExpression | DateBoolExpression | StringBoolExpression | NumberBoolExpression; + +/** + * @title LogicalManyBoolExpression + */ +export type LogicalManyBoolExpression = { operator: LogicalBoolOperator, expressions: BoolExpression[] } + +/** + * @title ManyBoolExpression + */ +export type ManyBoolExpression = LogicalManyBoolExpression + /** * @title BoolExpression */ export type BoolExpression = - boolean - | ModelPath + ValueBoolExpression | UnaryBoolExpression - | NumberBoolExpression - | StringBoolExpression - | DateBoolExpression - | LogicalBoolExpression - | LogicalManyBoolExpression - | LocationBoolExpression + | BinaryBoolExpression + | ManyBoolExpression // TODO: | { operator: ListBoolOperator, left: Expression, right: ListExpression } diff --git a/sdk/typescript-schema/expression/date-expression.ts b/sdk/typescript-schema/expression/date-expression.ts index 575ea9e..29ef3aa 100644 --- a/sdk/typescript-schema/expression/date-expression.ts +++ b/sdk/typescript-schema/expression/date-expression.ts @@ -1,33 +1,14 @@ -import { AbsoluteDate, RelativeDate } from "../literal/date"; +import { DateLiteral } from "../literal/date"; import { ModelPath } from "../literal/model-path"; /** - * @title DateLiteralExpression + * @title ValueDateExpression */ -export type DateLiteralExpression = { date: AbsoluteDate | RelativeDate } +export type ValueDateExpression = { date: DateLiteral } | ModelPath /** - * @title BooleanExpression - * @description Represents an expression that evaluates to a date or date-based condition. - * Examples: - * 1. Absolute date: - * { absolute: "2023-01-01T00:00:00Z" } - * - * 2. Relative date: - * { relative: { offset: -30, unit: "day" } } - * - * 3. Date with binary operator: - * { operator: "greater_than", operand: { absolute: "2023-01-01T00:00:00Z" } } - * - * 4. Logical combination of dates: - * { - * operator: "and", - * expressions: [ - * { absolute: "2023-01-01T00:00:00Z" }, - * { operator: "less_than", operand: { relative: { offset: 0, unit: "month", boundary: "end" } } } - * ] - * } + * @title DateExpression + * @description Represents an expression that evaluates to a date */ export type DateExpression = - DateLiteralExpression - | ModelPath + ValueDateExpression diff --git a/sdk/typescript-schema/expression/expression.ts b/sdk/typescript-schema/expression/expression.ts index 8188edc..5148ce1 100644 --- a/sdk/typescript-schema/expression/expression.ts +++ b/sdk/typescript-schema/expression/expression.ts @@ -1,40 +1,45 @@ -import { BoolExpression } from "./boolean-expression"; -import { DateExpression } from "./date-expression"; -import { NumberExpression } from "./number-expression"; -import { LocationExpression } from "./location-expression"; +import { BinaryBoolExpression, ManyBoolExpression, UnaryBoolExpression, ValueBoolExpression } from "./boolean-expression"; +import { ValueDateExpression } from "./date-expression"; +import { AggregateNumberExpression, BinaryNumberExpression, ValueNumberExpression } from "./number-expression"; +import { ValueLocationExpression } from "./location-expression"; +import { ValueStringExpression } from "./string-expression"; + +/** + * @title ValueExpression + */ +export type ValueExpression = + ValueBoolExpression + | ValueDateExpression + | ValueLocationExpression + | ValueNumberExpression + | ValueStringExpression + +/** + * @title UnaryExpression + */ +export type UnaryExpression = UnaryBoolExpression + +/** + * @title BinaryExpression + */ +export type BinaryExpression = BinaryBoolExpression | BinaryNumberExpression + +/** + * @title ManyExpression + */ +export type ManyExpression = ManyBoolExpression + +/** + * @title AggregateExpression + */ +export type AggregateExpression = AggregateNumberExpression /** * @title Expression - * @description Represents a complex expression that can evaluate to true, false, or noop. - * Examples: - * 1. Join expression (combining expressions from different models): - * { - * "model": "user", - * "expression": { - * "operator": "equals", - * "left": { "path": "age" }, - * "right": 18 - * } - * } - * - * 2. Logical expression (AND): - * { - * "operator": "and", - * "expressions": [ - * { "operator": "equals", "left": { "path": "country" }, "right": "US" }, - * { "operator": "greater_than", "left": { "path": "age" }, "right": 18 } - * ] - * } - * - * 3. Location expression: - * { - * "operator": "within", - * "left": { "location": { "latitude": 37.7749, "longitude": -122.4194, "distance": { "value": 10, "unit": "miles" } } }, - * "right": { "model": "user", "path": "location" } - * } + * @description Represents an expression that accepts a variety of arguments and evaluates to a value. */ export type Expression = - BoolExpression - | DateExpression - | NumberExpression - | LocationExpression + ValueExpression + | UnaryExpression + | BinaryExpression + | ManyExpression diff --git a/sdk/typescript-schema/expression/location-expression.ts b/sdk/typescript-schema/expression/location-expression.ts index 006449a..4b82a99 100644 --- a/sdk/typescript-schema/expression/location-expression.ts +++ b/sdk/typescript-schema/expression/location-expression.ts @@ -1,25 +1,14 @@ import { Location } from "../literal/location"; import { ModelPath } from "../literal/model-path"; +/** + * @title ValueLocationExpression + */ +export type ValueLocationExpression = Location + | ModelPath + /** * @title LocationExpression * @description Represents an expression that evaluates to a location or location-based condition. - * Examples: - * 1. Simple location: - * { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } - * - * 2. Location with operator: - * { operator: "within", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } } } - * - * 3. Logical combination of locations: - * { - * operator: "or", - * expressions: [ - * { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: "miles" } }, - * { operator: "within", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: "miles" } } } - * ] - * } */ -export type LocationExpression = - Location - | ModelPath +export type LocationExpression = ValueLocationExpression diff --git a/sdk/typescript-schema/expression/number-expression.ts b/sdk/typescript-schema/expression/number-expression.ts index 85cbf99..ccdd283 100644 --- a/sdk/typescript-schema/expression/number-expression.ts +++ b/sdk/typescript-schema/expression/number-expression.ts @@ -2,6 +2,11 @@ import { AggregationNumberOperator, BinaryNumberOperator } from "../common/opera import { BoolExpression } from "./boolean-expression"; import { ModelPath } from "../literal/model-path"; +/** + * @title ValueNumberExpression + */ +export type ValueNumberExpression = number | ModelPath + /** * @title BinaryNumberExpression */ @@ -14,25 +19,9 @@ export type AggregateNumberExpression = { operator: AggregationNumberOperator, g /** * @title NumberExpression - * @description Represents a count expression, which can be a number, a binary operation, or a logical group. - * Examples: - * 1. Simple count: - * 5 - * - * 2. Binary count expression: - * { operator: "greater_than", operand: { path: "event.count" } } - * - * 3. Logical group of count expressions: - * { - * operator: "and", - * expressions: [ - * 1, - * { operator: "greater_than", operand: { path: "event.count" } } - * ] - * } + * @description Represents an expression that evaluates to a number. */ export type NumberExpression = - number - | ModelPath + ValueNumberExpression | BinaryNumberExpression | AggregateNumberExpression diff --git a/sdk/typescript-schema/expression/string-expression.ts b/sdk/typescript-schema/expression/string-expression.ts index 40533d9..80e3f45 100644 --- a/sdk/typescript-schema/expression/string-expression.ts +++ b/sdk/typescript-schema/expression/string-expression.ts @@ -1,8 +1,11 @@ import { ModelPath } from "../literal/model-path"; +/** + * @title ValueStringExpression + */ +export type ValueStringExpression = string | ModelPath + /** * @title StringExpression */ -export type StringExpression = - string - | ModelPath +export type StringExpression = ValueStringExpression diff --git a/sdk/typescript-schema/schema/audience-schema.json b/sdk/typescript-schema/schema/audience-schema.json index 7980716..ecd0df1 100644 --- a/sdk/typescript-schema/schema/audience-schema.json +++ b/sdk/typescript-schema/schema/audience-schema.json @@ -15,6 +15,10 @@ "title": "AbsoluteDate", "type": "object" }, + "AggregateExpression": { + "$ref": "#/definitions/AggregateNumberExpression", + "title": "AggregateExpression" + }, "AggregateNumberExpression": { "additionalProperties": false, "properties": { @@ -113,6 +117,37 @@ "title": "AudienceReference", "type": "object" }, + "BinaryBoolExpression": { + "anyOf": [ + { + "$ref": "#/definitions/AudienceBoolExpression" + }, + { + "$ref": "#/definitions/LocationBoolExpression" + }, + { + "$ref": "#/definitions/DateBoolExpression" + }, + { + "$ref": "#/definitions/StringBoolExpression" + }, + { + "$ref": "#/definitions/NumberBoolExpression" + } + ], + "title": "BoolBinaryExpression" + }, + "BinaryExpression": { + "anyOf": [ + { + "$ref": "#/definitions/BinaryBoolExpression" + }, + { + "$ref": "#/definitions/BinaryNumberExpression" + } + ], + "title": "BinaryExpression" + }, "BinaryNumberExpression": { "additionalProperties": false, "properties": { @@ -148,31 +183,16 @@ "BoolExpression": { "anyOf": [ { - "type": "boolean" - }, - { - "$ref": "#/definitions/ModelPath" + "$ref": "#/definitions/ValueBoolExpression" }, { "$ref": "#/definitions/UnaryBoolExpression" }, { - "$ref": "#/definitions/NumberBoolExpression" - }, - { - "$ref": "#/definitions/StringBoolExpression" + "$ref": "#/definitions/BinaryBoolExpression" }, { - "$ref": "#/definitions/DateBoolExpression" - }, - { - "$ref": "#/definitions/LogicalBoolExpression" - }, - { - "$ref": "#/definitions/LogicalManyBoolExpression" - }, - { - "$ref": "#/definitions/LocationBoolExpression" + "$ref": "#/definitions/ManyBoolExpression" } ], "title": "BoolExpression" @@ -199,16 +219,9 @@ "type": "object" }, "DateExpression": { - "anyOf": [ - { - "$ref": "#/definitions/DateLiteralExpression" - }, - { - "$ref": "#/definitions/ModelPath" - } - ], - "description": "Represents an expression that evaluates to a date or date-based condition.\nExamples:\n1. Absolute date:\n{ absolute: \"2023-01-01T00:00:00Z\" }\n\n2. Relative date:\n{ relative: { offset: -30, unit: \"day\" } }\n\n3. Date with binary operator:\n{ operator: \"greater_than\", operand: { absolute: \"2023-01-01T00:00:00Z\" } }\n\n4. Logical combination of dates:\n{\noperator: \"and\",\nexpressions: [\n{ absolute: \"2023-01-01T00:00:00Z\" },\n{ operator: \"less_than\", operand: { relative: { offset: 0, unit: \"month\", boundary: \"end\" } } }\n]\n}", - "title": "BooleanExpression" + "$ref": "#/definitions/ValueDateExpression", + "description": "Represents an expression that evaluates to a date", + "title": "DateExpression" }, "DateLiteral": { "anyOf": [ @@ -221,26 +234,6 @@ ], "title": "DateLiteral" }, - "DateLiteralExpression": { - "additionalProperties": false, - "properties": { - "date": { - "anyOf": [ - { - "$ref": "#/definitions/AbsoluteDate" - }, - { - "$ref": "#/definitions/RelativeDate" - } - ] - } - }, - "required": [ - "date" - ], - "title": "DateLiteralExpression", - "type": "object" - }, "DateUnit": { "description": "Represents units of time that can be used in relative date calculations.\nExamples:\n- 'second': 1 second\n- 'minute': 60 seconds\n- 'hour': 60 minutes\n- 'day': 24 hours\n- 'week': 7 days\n- 'month': ~30 days\n- 'quarter': 3 months\n- 'year': 12 months", "enum": [ @@ -268,19 +261,19 @@ "Expression": { "anyOf": [ { - "$ref": "#/definitions/BoolExpression" + "$ref": "#/definitions/ValueExpression" }, { - "$ref": "#/definitions/DateExpression" + "$ref": "#/definitions/UnaryExpression" }, { - "$ref": "#/definitions/NumberExpression" + "$ref": "#/definitions/BinaryExpression" }, { - "$ref": "#/definitions/LocationExpression" + "$ref": "#/definitions/ManyExpression" } ], - "description": "Represents a complex expression that can evaluate to true, false, or noop.\nExamples:\n1. Join expression (combining expressions from different models):\n{\n\"model\": \"user\",\n\"expression\": {\n\"operator\": \"equals\",\n\"left\": { \"path\": \"age\" },\n\"right\": 18\n}\n}\n\n2. Logical expression (AND):\n{\n\"operator\": \"and\",\n\"expressions\": [\n{ \"operator\": \"equals\", \"left\": { \"path\": \"country\" }, \"right\": \"US\" },\n{ \"operator\": \"greater_than\", \"left\": { \"path\": \"age\" }, \"right\": 18 }\n]\n}\n\n3. Location expression:\n{\n\"operator\": \"within\",\n\"left\": { \"location\": { \"latitude\": 37.7749, \"longitude\": -122.4194, \"distance\": { \"value\": 10, \"unit\": \"miles\" } } },\n\"right\": { \"model\": \"user\", \"path\": \"location\" }\n}", + "description": "Represents an expression that accepts a variety of arguments and evaluates to a value.", "title": "Expression" }, "ListBoolOperator": { @@ -383,15 +376,8 @@ "type": "string" }, "LocationExpression": { - "anyOf": [ - { - "$ref": "#/definitions/Location" - }, - { - "$ref": "#/definitions/ModelPath" - } - ], - "description": "Represents an expression that evaluates to a location or location-based condition.\nExamples:\n1. Simple location:\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } }\n\n2. Location with operator:\n{ operator: \"within\", operand: { latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } } }\n\n3. Logical combination of locations:\n{\noperator: \"or\",\nexpressions: [\n{ latitude: 40.7128, longitude: -74.0060, distance: { value: 5, unit: \"miles\" } },\n{ operator: \"within\", operand: { latitude: 34.0522, longitude: -118.2437, distance: { value: 10, unit: \"miles\" } } }\n]\n}", + "$ref": "#/definitions/ValueLocationExpression", + "description": "Represents an expression that evaluates to a location or location-based condition.", "title": "LocationExpression" }, "LogicalBoolExpression": { @@ -443,6 +429,14 @@ "title": "LogicalManyBoolExpression", "type": "object" }, + "ManyBoolExpression": { + "$ref": "#/definitions/LogicalManyBoolExpression", + "title": "ManyBoolExpression" + }, + "ManyExpression": { + "$ref": "#/definitions/ManyBoolExpression", + "title": "ManyExpression" + }, "ModelPath": { "additionalProperties": false, "description": "Represents a model path reference within a data model.\nExamples:\n1. Simple model path:\n{ \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path:\n{ \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path:\n{ \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", @@ -511,10 +505,7 @@ "NumberExpression": { "anyOf": [ { - "type": "number" - }, - { - "$ref": "#/definitions/ModelPath" + "$ref": "#/definitions/ValueNumberExpression" }, { "$ref": "#/definitions/BinaryNumberExpression" @@ -523,7 +514,7 @@ "$ref": "#/definitions/AggregateNumberExpression" } ], - "description": "Represents a count expression, which can be a number, a binary operation, or a logical group.\nExamples:\n1. Simple count:\n5\n\n2. Binary count expression:\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n\n3. Logical group of count expressions:\n{\noperator: \"and\",\nexpressions: [\n1,\n{ operator: \"greater_than\", operand: { path: \"event.count\" } }\n]\n}", + "description": "Represents an expression that evaluates to a number.", "title": "NumberExpression" }, "RelativeDate": { @@ -598,14 +589,7 @@ "type": "string" }, "StringExpression": { - "anyOf": [ - { - "type": "string" - }, - { - "$ref": "#/definitions/ModelPath" - } - ], + "$ref": "#/definitions/ValueStringExpression", "title": "StringExpression" }, "UnaryBoolExpression": { @@ -635,6 +619,94 @@ ], "type": "string" }, + "UnaryExpression": { + "$ref": "#/definitions/UnaryBoolExpression", + "title": "UnaryExpression" + }, + "ValueBoolExpression": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueBoolExpression" + }, + "ValueDateExpression": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "date": { + "$ref": "#/definitions/DateLiteral" + } + }, + "required": [ + "date" + ], + "type": "object" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueDateExpression" + }, + "ValueExpression": { + "anyOf": [ + { + "$ref": "#/definitions/ValueBoolExpression" + }, + { + "$ref": "#/definitions/ValueDateExpression" + }, + { + "$ref": "#/definitions/ValueLocationExpression" + }, + { + "$ref": "#/definitions/ValueNumberExpression" + }, + { + "$ref": "#/definitions/ValueStringExpression" + } + ], + "title": "ValueExpression" + }, + "ValueLocationExpression": { + "anyOf": [ + { + "$ref": "#/definitions/Location" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueLocationExpression" + }, + "ValueNumberExpression": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueNumberExpression" + }, + "ValueStringExpression": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ModelPath" + } + ], + "title": "ValueStringExpression" + }, "Version": { "type": [ "string" From bffff87cf5106c8dde34f76e4f8cc1c7c0be93c7 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Mon, 30 Jun 2025 17:53:24 -0700 Subject: [PATCH 14/16] Use classes + interfaces --- schema/audience-definition-schema.json | 114 +++++++++++++++--- .../mp_audience_sdk/models/audience_models.py | 67 +++++++++- .../expression/boolean-expression.ts | 56 +++++++-- .../expression/expression-interfaces.ts | 20 +++ .../expression/expression.ts | 23 +++- .../expression/number-expression.ts | 14 ++- sdk/typescript-schema/literal/literal.ts | 5 +- .../schema/audience-schema.json | 114 +++++++++++++++--- 8 files changed, 362 insertions(+), 51 deletions(-) create mode 100644 sdk/typescript-schema/expression/expression-interfaces.ts diff --git a/schema/audience-definition-schema.json b/schema/audience-definition-schema.json index ecd0df1..b54a348 100644 --- a/schema/audience-definition-schema.json +++ b/schema/audience-definition-schema.json @@ -36,9 +36,9 @@ } }, "required": [ - "operator", "group_by_model", - "operand" + "operand", + "operator" ], "title": "AggregateNumberExpression", "type": "object" @@ -88,8 +88,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "AudienceBoolExpression", @@ -162,8 +162,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "BinaryNumberExpression", @@ -211,8 +211,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "DateBoolExpression", @@ -267,15 +267,95 @@ "$ref": "#/definitions/UnaryExpression" }, { - "$ref": "#/definitions/BinaryExpression" + "$ref": "#/definitions/IBinaryExpression" }, { "$ref": "#/definitions/ManyExpression" + }, + { + "$ref": "#/definitions/BoolExpression" + }, + { + "$ref": "#/definitions/NumberExpression" + }, + { + "$ref": "#/definitions/StringExpression" + }, + { + "$ref": "#/definitions/LocationExpression" + }, + { + "$ref": "#/definitions/DateExpression" + }, + { + "$ref": "#/definitions/Literal" } ], "description": "Represents an expression that accepts a variety of arguments and evaluates to a value.", "title": "Expression" }, + "IAggregateExpression": { + "additionalProperties": false, + "properties": { + "condition": { + "$ref": "#/definitions/Expression" + }, + "group_by_model": { + "type": "string" + }, + "operand": { + "$ref": "#/definitions/Expression" + } + }, + "required": [ + "operand", + "group_by_model" + ], + "type": "object" + }, + "IBinaryExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/Expression" + }, + "right": { + "$ref": "#/definitions/Expression" + } + }, + "required": [ + "left", + "right" + ], + "type": "object" + }, + "IManyExpression": { + "additionalProperties": false, + "properties": { + "expressions": { + "items": { + "$ref": "#/definitions/Expression" + }, + "type": "array" + } + }, + "required": [ + "expressions" + ], + "type": "object" + }, + "IUnaryExpression": { + "additionalProperties": false, + "properties": { + "operand": { + "$ref": "#/definitions/Expression" + } + }, + "required": [ + "operand" + ], + "type": "object" + }, "ListBoolOperator": { "description": "Represents operators that work with lists of values. Examples:\n- \"contains\": { list: [1, 2, 3], value: 2 }\n- \"between\": { list: [1, 10], value: 5 }\n- \"match_any\": { list: [\"a\", \"b\"], value: \"a\" }\n- \"in\": { list: [1, 2, 3], value: 2 }", "enum": [ @@ -307,6 +387,12 @@ }, { "$ref": "#/definitions/Location" + }, + { + "$ref": "#/definitions/ModelReference" + }, + { + "$ref": "#/definitions/AudienceReference" } ], "description": "Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n\"hello\"\n\n2. Path reference:\n{ path: \"user.age\" }\n\n3. Arithmetic operation:\n{\noperator: \"plus\",\nleft: { path: \"price\" },\nright: { path: \"tax\" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: \"multiply\",\nleft: { operator: \"plus\", left: { path: \"base_price\" }, right: { path: \"shipping\" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: \"2023-01-01T00:00:00Z\" } }", @@ -360,8 +446,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "LocationBoolExpression", @@ -394,8 +480,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "LogicalBoolExpression", @@ -423,8 +509,8 @@ } }, "required": [ - "operator", - "expressions" + "expressions", + "operator" ], "title": "LogicalManyBoolExpression", "type": "object" @@ -483,8 +569,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "NumberBoolExpression", @@ -565,8 +651,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "StringBoolExpression", @@ -603,8 +689,8 @@ } }, "required": [ - "operator", - "operand" + "operand", + "operator" ], "title": "UnaryBoolExpression", "type": "object" diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index b1622a5..53358cb 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-07-01T00:24:24+00:00 +# timestamp: 2025-07-01T00:52:21+00:00 from __future__ import annotations @@ -213,8 +213,21 @@ class DateLiteral(RootModel["AbsoluteDate | RelativeDate"]): root: AbsoluteDate | RelativeDate = Field(..., title="DateLiteral") -class Literal(RootModel["bool | float | str | DateLiteral | ModelPath | Location"]): - root: bool | float | str | DateLiteral | ModelPath | Location = Field( +class Literal( + RootModel[ + "bool | float | str | DateLiteral | ModelPath | Location | ModelReference | AudienceReference" + ] +): + root: ( + bool + | float + | str + | DateLiteral + | ModelPath + | Location + | ModelReference + | AudienceReference + ) = Field( ..., description='Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n"hello"\n\n2. Path reference:\n{ path: "user.age" }\n\n3. Arithmetic operation:\n{\noperator: "plus",\nleft: { path: "price" },\nright: { path: "tax" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: "multiply",\nleft: { operator: "plus", left: { path: "base_price" }, right: { path: "shipping" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: "2023-01-01T00:00:00Z" } }', title="Literal", @@ -358,15 +371,59 @@ class BoolExpression( class Expression( - RootModel["ValueExpression | UnaryExpression | BinaryExpression | ManyExpression"] + RootModel[ + "ValueExpression | UnaryExpression | IBinaryExpression | ManyExpression | BoolExpression | NumberExpression | StringExpression | LocationExpression | DateExpression | Literal" + ] ): - root: ValueExpression | UnaryExpression | BinaryExpression | ManyExpression = Field( + root: ( + ValueExpression + | UnaryExpression + | IBinaryExpression + | ManyExpression + | BoolExpression + | NumberExpression + | StringExpression + | LocationExpression + | DateExpression + | Literal + ) = Field( ..., description="Represents an expression that accepts a variety of arguments and evaluates to a value.", title="Expression", ) +class IAggregateExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + condition: Expression | None = None + group_by_model: str + operand: Expression + + +class IBinaryExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + left: Expression + right: Expression + + +class IManyExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + expressions: List[Expression] + + +class IUnaryExpressionExpression(BaseModel): + model_config = ConfigDict( + extra="forbid", + ) + operand: Expression + + class LogicalBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", diff --git a/sdk/typescript-schema/expression/boolean-expression.ts b/sdk/typescript-schema/expression/boolean-expression.ts index b7c3579..5c83b89 100644 --- a/sdk/typescript-schema/expression/boolean-expression.ts +++ b/sdk/typescript-schema/expression/boolean-expression.ts @@ -3,6 +3,7 @@ import { AudienceReference } from "../literal/audience"; import { ModelPath, ModelReference } from "../literal/model-path"; import { DateExpression } from "./date-expression"; import { Expression } from "./expression"; +import { IBinaryExpression, IManyExpression, IUnaryExpression } from "./expression-interfaces"; import { LocationExpression } from "./location-expression"; import { NumberExpression } from "./number-expression"; import { StringExpression } from "./string-expression"; @@ -15,37 +16,71 @@ export type ValueBoolExpression = boolean | ModelPath /** * @title UnaryBoolExpression */ -export type UnaryBoolExpression = { operator: UnaryBoolOperator, operand: Expression } +export class UnaryBoolExpression implements IUnaryExpression { + operator: UnaryBoolOperator + operand: Expression + +} /** * @title NumberBoolExpression */ -export type NumberBoolExpression = { operator: NumberBoolOperator, left: NumberExpression, right: NumberExpression } +export class NumberBoolExpression implements IBinaryExpression { + operator: NumberBoolOperator + left: NumberExpression + right: NumberExpression + +} /** * @title StringBoolExpression */ -export type StringBoolExpression = { operator: StringBoolOperator, left: StringExpression, right: StringExpression } +export class StringBoolExpression implements IBinaryExpression { + operator: StringBoolOperator + left: StringExpression + right: StringExpression + +} /** * @title DateBoolExpression */ -export type DateBoolExpression = { operator: NumberBoolOperator, left: DateExpression, right: DateExpression } +export class DateBoolExpression implements IBinaryExpression { + operator: NumberBoolOperator + left: DateExpression + right: DateExpression + +} /** * @title LogicalBoolExpression */ -export type LogicalBoolExpression = { operator: LogicalBoolOperator, left: BoolExpression, right: BoolExpression } +export class LogicalBoolExpression implements IBinaryExpression { + operator: LogicalBoolOperator + left: BoolExpression + right: BoolExpression + +} /** * @title LocationBoolExpression */ -export type LocationBoolExpression = { operator: LocationBoolOperator, left: LocationExpression, right: LocationExpression } +export class LocationBoolExpression implements IBinaryExpression { + operator: LocationBoolOperator + left: LocationExpression + right: LocationExpression + +} /** * @title AudienceBoolExpression */ -export type AudienceBoolExpression = { operator: AudienceBoolOperator, left: ModelReference, right: AudienceReference } +export class AudienceBoolExpression implements IBinaryExpression { + operator: AudienceBoolOperator + left: ModelReference + right: AudienceReference + +} /** * @title BoolBinaryExpression @@ -55,7 +90,11 @@ export type BinaryBoolExpression = AudienceBoolExpression | LocationBoolExpressi /** * @title LogicalManyBoolExpression */ -export type LogicalManyBoolExpression = { operator: LogicalBoolOperator, expressions: BoolExpression[] } +export class LogicalManyBoolExpression implements IManyExpression { + operator: LogicalBoolOperator + expressions: BoolExpression[] + +} /** * @title ManyBoolExpression @@ -70,4 +109,3 @@ export type BoolExpression = | UnaryBoolExpression | BinaryBoolExpression | ManyBoolExpression -// TODO: | { operator: ListBoolOperator, left: Expression, right: ListExpression } diff --git a/sdk/typescript-schema/expression/expression-interfaces.ts b/sdk/typescript-schema/expression/expression-interfaces.ts new file mode 100644 index 0000000..9916225 --- /dev/null +++ b/sdk/typescript-schema/expression/expression-interfaces.ts @@ -0,0 +1,20 @@ +import { Expression } from "./expression" + +export interface IUnaryExpression { + operand: T +} + +export interface IBinaryExpression { + left: Expression + right: Expression +} + +export interface IManyExpression { + expressions: Expression[] +} + +export interface IAggregateExpression { + condition?: Expression + operand: Expression + group_by_model: string +} diff --git a/sdk/typescript-schema/expression/expression.ts b/sdk/typescript-schema/expression/expression.ts index 5148ce1..c2b2c1f 100644 --- a/sdk/typescript-schema/expression/expression.ts +++ b/sdk/typescript-schema/expression/expression.ts @@ -1,8 +1,10 @@ -import { BinaryBoolExpression, ManyBoolExpression, UnaryBoolExpression, ValueBoolExpression } from "./boolean-expression"; -import { ValueDateExpression } from "./date-expression"; -import { AggregateNumberExpression, BinaryNumberExpression, ValueNumberExpression } from "./number-expression"; -import { ValueLocationExpression } from "./location-expression"; -import { ValueStringExpression } from "./string-expression"; +import { BinaryBoolExpression, BoolExpression, ManyBoolExpression, UnaryBoolExpression, ValueBoolExpression } from "./boolean-expression"; +import { DateExpression, ValueDateExpression } from "./date-expression"; +import { AggregateNumberExpression, BinaryNumberExpression, NumberExpression, ValueNumberExpression } from "./number-expression"; +import { LocationExpression, ValueLocationExpression } from "./location-expression"; +import { StringExpression, ValueStringExpression } from "./string-expression"; +import { IBinaryExpression } from "./expression-interfaces"; +import { Literal } from "../literal/literal"; /** * @title ValueExpression @@ -29,6 +31,8 @@ export type BinaryExpression = BinaryBoolExpression | BinaryNumberExpression */ export type ManyExpression = ManyBoolExpression + + /** * @title AggregateExpression */ @@ -41,5 +45,12 @@ export type AggregateExpression = AggregateNumberExpression export type Expression = ValueExpression | UnaryExpression - | BinaryExpression + // | BinaryExpression + | IBinaryExpression | ManyExpression + | BoolExpression + | NumberExpression + | StringExpression + | LocationExpression + | DateExpression + | Literal diff --git a/sdk/typescript-schema/expression/number-expression.ts b/sdk/typescript-schema/expression/number-expression.ts index ccdd283..f565c1b 100644 --- a/sdk/typescript-schema/expression/number-expression.ts +++ b/sdk/typescript-schema/expression/number-expression.ts @@ -1,6 +1,7 @@ import { AggregationNumberOperator, BinaryNumberOperator } from "../common/operator"; import { BoolExpression } from "./boolean-expression"; import { ModelPath } from "../literal/model-path"; +import { IAggregateExpression, IBinaryExpression } from "./expression-interfaces"; /** * @title ValueNumberExpression @@ -10,12 +11,21 @@ export type ValueNumberExpression = number | ModelPath /** * @title BinaryNumberExpression */ -export type BinaryNumberExpression = { operator: BinaryNumberOperator, left: NumberExpression, right: NumberExpression } +export class BinaryNumberExpression implements IBinaryExpression { + operator: BinaryNumberOperator; + left: NumberExpression; + right: NumberExpression +} /** * @title AggregateNumberExpression */ -export type AggregateNumberExpression = { operator: AggregationNumberOperator, group_by_model: string, operand: NumberExpression, condition?: BoolExpression } +export class AggregateNumberExpression implements IAggregateExpression { + operator: AggregationNumberOperator + group_by_model: string + operand: NumberExpression + condition?: BoolExpression +} /** * @title NumberExpression diff --git a/sdk/typescript-schema/literal/literal.ts b/sdk/typescript-schema/literal/literal.ts index 6b99595..b493e26 100644 --- a/sdk/typescript-schema/literal/literal.ts +++ b/sdk/typescript-schema/literal/literal.ts @@ -1,6 +1,7 @@ import { DateLiteral } from "./date"; -import { ModelPath } from "./model-path"; +import { ModelPath, ModelReference } from "./model-path"; import { Location } from "./location"; +import { AudienceReference } from "./audience"; /** * @title Literal @@ -38,3 +39,5 @@ export type Literal = | DateLiteral | ModelPath | Location + | ModelReference + | AudienceReference diff --git a/sdk/typescript-schema/schema/audience-schema.json b/sdk/typescript-schema/schema/audience-schema.json index ecd0df1..b54a348 100644 --- a/sdk/typescript-schema/schema/audience-schema.json +++ b/sdk/typescript-schema/schema/audience-schema.json @@ -36,9 +36,9 @@ } }, "required": [ - "operator", "group_by_model", - "operand" + "operand", + "operator" ], "title": "AggregateNumberExpression", "type": "object" @@ -88,8 +88,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "AudienceBoolExpression", @@ -162,8 +162,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "BinaryNumberExpression", @@ -211,8 +211,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "DateBoolExpression", @@ -267,15 +267,95 @@ "$ref": "#/definitions/UnaryExpression" }, { - "$ref": "#/definitions/BinaryExpression" + "$ref": "#/definitions/IBinaryExpression" }, { "$ref": "#/definitions/ManyExpression" + }, + { + "$ref": "#/definitions/BoolExpression" + }, + { + "$ref": "#/definitions/NumberExpression" + }, + { + "$ref": "#/definitions/StringExpression" + }, + { + "$ref": "#/definitions/LocationExpression" + }, + { + "$ref": "#/definitions/DateExpression" + }, + { + "$ref": "#/definitions/Literal" } ], "description": "Represents an expression that accepts a variety of arguments and evaluates to a value.", "title": "Expression" }, + "IAggregateExpression": { + "additionalProperties": false, + "properties": { + "condition": { + "$ref": "#/definitions/Expression" + }, + "group_by_model": { + "type": "string" + }, + "operand": { + "$ref": "#/definitions/Expression" + } + }, + "required": [ + "operand", + "group_by_model" + ], + "type": "object" + }, + "IBinaryExpression": { + "additionalProperties": false, + "properties": { + "left": { + "$ref": "#/definitions/Expression" + }, + "right": { + "$ref": "#/definitions/Expression" + } + }, + "required": [ + "left", + "right" + ], + "type": "object" + }, + "IManyExpression": { + "additionalProperties": false, + "properties": { + "expressions": { + "items": { + "$ref": "#/definitions/Expression" + }, + "type": "array" + } + }, + "required": [ + "expressions" + ], + "type": "object" + }, + "IUnaryExpression": { + "additionalProperties": false, + "properties": { + "operand": { + "$ref": "#/definitions/Expression" + } + }, + "required": [ + "operand" + ], + "type": "object" + }, "ListBoolOperator": { "description": "Represents operators that work with lists of values. Examples:\n- \"contains\": { list: [1, 2, 3], value: 2 }\n- \"between\": { list: [1, 10], value: 5 }\n- \"match_any\": { list: [\"a\", \"b\"], value: \"a\" }\n- \"in\": { list: [1, 2, 3], value: 2 }", "enum": [ @@ -307,6 +387,12 @@ }, { "$ref": "#/definitions/Location" + }, + { + "$ref": "#/definitions/ModelReference" + }, + { + "$ref": "#/definitions/AudienceReference" } ], "description": "Represents a value that can be used in expressions, including primitive values, paths, and arithmetic operations.\nExamples:\n1. Primitive values:\ntrue\n42\n\"hello\"\n\n2. Path reference:\n{ path: \"user.age\" }\n\n3. Arithmetic operation:\n{\noperator: \"plus\",\nleft: { path: \"price\" },\nright: { path: \"tax\" }\n}\n\n4. Nested arithmetic operation:\n{\noperator: \"multiply\",\nleft: { operator: \"plus\", left: { path: \"base_price\" }, right: { path: \"shipping\" } },\nright: 1.1\n}\n\n5. Date operand:\n{ date: { absolute: \"2023-01-01T00:00:00Z\" } }", @@ -360,8 +446,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "LocationBoolExpression", @@ -394,8 +480,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "LogicalBoolExpression", @@ -423,8 +509,8 @@ } }, "required": [ - "operator", - "expressions" + "expressions", + "operator" ], "title": "LogicalManyBoolExpression", "type": "object" @@ -483,8 +569,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "NumberBoolExpression", @@ -565,8 +651,8 @@ } }, "required": [ - "operator", "left", + "operator", "right" ], "title": "StringBoolExpression", @@ -603,8 +689,8 @@ } }, "required": [ - "operator", - "operand" + "operand", + "operator" ], "title": "UnaryBoolExpression", "type": "object" From f92ad20fb44e4e4880f67a5c3871a258cfb295ed Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Mon, 30 Jun 2025 17:56:21 -0700 Subject: [PATCH 15/16] More changes --- schema/audience-definition-schema.json | 32 +++----------- .../mp_audience_sdk/models/audience_models.py | 31 +++----------- .../expression/boolean-expression.ts | 2 +- .../expression/expression-interfaces.ts | 4 +- .../expression/expression.ts | 42 +++++++++---------- .../schema/audience-schema.json | 32 +++----------- 6 files changed, 42 insertions(+), 101 deletions(-) diff --git a/schema/audience-definition-schema.json b/schema/audience-definition-schema.json index b54a348..c9b2bb3 100644 --- a/schema/audience-definition-schema.json +++ b/schema/audience-definition-schema.json @@ -15,10 +15,6 @@ "title": "AbsoluteDate", "type": "object" }, - "AggregateExpression": { - "$ref": "#/definitions/AggregateNumberExpression", - "title": "AggregateExpression" - }, "AggregateNumberExpression": { "additionalProperties": false, "properties": { @@ -137,17 +133,6 @@ ], "title": "BoolBinaryExpression" }, - "BinaryExpression": { - "anyOf": [ - { - "$ref": "#/definitions/BinaryBoolExpression" - }, - { - "$ref": "#/definitions/BinaryNumberExpression" - } - ], - "title": "BinaryExpression" - }, "BinaryNumberExpression": { "additionalProperties": false, "properties": { @@ -264,13 +249,16 @@ "$ref": "#/definitions/ValueExpression" }, { - "$ref": "#/definitions/UnaryExpression" + "$ref": "#/definitions/IUnaryExpression" }, { "$ref": "#/definitions/IBinaryExpression" }, { - "$ref": "#/definitions/ManyExpression" + "$ref": "#/definitions/IManyExpression" + }, + { + "$ref": "#/definitions/IAggregateExpression" }, { "$ref": "#/definitions/BoolExpression" @@ -344,7 +332,7 @@ ], "type": "object" }, - "IUnaryExpression": { + "IUnaryExpression": { "additionalProperties": false, "properties": { "operand": { @@ -519,10 +507,6 @@ "$ref": "#/definitions/LogicalManyBoolExpression", "title": "ManyBoolExpression" }, - "ManyExpression": { - "$ref": "#/definitions/ManyBoolExpression", - "title": "ManyExpression" - }, "ModelPath": { "additionalProperties": false, "description": "Represents a model path reference within a data model.\nExamples:\n1. Simple model path:\n{ \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path:\n{ \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path:\n{ \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", @@ -705,10 +689,6 @@ ], "type": "string" }, - "UnaryExpression": { - "$ref": "#/definitions/UnaryBoolExpression", - "title": "UnaryExpression" - }, "ValueBoolExpression": { "anyOf": [ { diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index 53358cb..5ea27fd 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-07-01T00:52:21+00:00 +# timestamp: 2025-07-01T00:56:12+00:00 from __future__ import annotations @@ -306,10 +306,6 @@ class DateBoolExpression(BaseModel): right: DateExpression -class AggregateExpression(RootModel["AggregateNumberExpression"]): - root: AggregateNumberExpression = Field(..., title="AggregateExpression") - - class AggregateNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -342,12 +338,6 @@ class BinaryBoolExpression( ) = Field(..., title="BoolBinaryExpression") -class BinaryExpression(RootModel["BinaryBoolExpression | BinaryNumberExpression"]): - root: BinaryBoolExpression | BinaryNumberExpression = Field( - ..., title="BinaryExpression" - ) - - class BinaryNumberExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -372,14 +362,15 @@ class BoolExpression( class Expression( RootModel[ - "ValueExpression | UnaryExpression | IBinaryExpression | ManyExpression | BoolExpression | NumberExpression | StringExpression | LocationExpression | DateExpression | Literal" + "ValueExpression | IUnaryExpression | IBinaryExpression | IManyExpression | IAggregateExpression | BoolExpression | NumberExpression | StringExpression | LocationExpression | DateExpression | Literal" ] ): root: ( ValueExpression - | UnaryExpression + | IUnaryExpression | IBinaryExpression - | ManyExpression + | IManyExpression + | IAggregateExpression | BoolExpression | NumberExpression | StringExpression @@ -417,7 +408,7 @@ class IManyExpression(BaseModel): expressions: List[Expression] -class IUnaryExpressionExpression(BaseModel): +class IUnaryExpression(BaseModel): model_config = ConfigDict( extra="forbid", ) @@ -445,10 +436,6 @@ class ManyBoolExpression(RootModel["LogicalManyBoolExpression"]): root: LogicalManyBoolExpression = Field(..., title="ManyBoolExpression") -class ManyExpression(RootModel["ManyBoolExpression"]): - root: ManyBoolExpression = Field(..., title="ManyExpression") - - class NumberBoolExpression(BaseModel): model_config = ConfigDict( extra="forbid", @@ -480,15 +467,9 @@ class UnaryBoolExpression(BaseModel): operator: UnaryBoolOperator -class UnaryExpression(RootModel["UnaryBoolExpression"]): - root: UnaryBoolExpression = Field(..., title="UnaryExpression") - - -AggregateExpression.model_rebuild() AggregateNumberExpression.model_rebuild() AudienceDefinition.model_rebuild() BinaryBoolExpression.model_rebuild() -BinaryExpression.model_rebuild() BinaryNumberExpression.model_rebuild() BoolExpression.model_rebuild() Expression.model_rebuild() diff --git a/sdk/typescript-schema/expression/boolean-expression.ts b/sdk/typescript-schema/expression/boolean-expression.ts index 5c83b89..0ddacc2 100644 --- a/sdk/typescript-schema/expression/boolean-expression.ts +++ b/sdk/typescript-schema/expression/boolean-expression.ts @@ -16,7 +16,7 @@ export type ValueBoolExpression = boolean | ModelPath /** * @title UnaryBoolExpression */ -export class UnaryBoolExpression implements IUnaryExpression { +export class UnaryBoolExpression implements IUnaryExpression { operator: UnaryBoolOperator operand: Expression diff --git a/sdk/typescript-schema/expression/expression-interfaces.ts b/sdk/typescript-schema/expression/expression-interfaces.ts index 9916225..736363a 100644 --- a/sdk/typescript-schema/expression/expression-interfaces.ts +++ b/sdk/typescript-schema/expression/expression-interfaces.ts @@ -1,7 +1,7 @@ import { Expression } from "./expression" -export interface IUnaryExpression { - operand: T +export interface IUnaryExpression { + operand: Expression } export interface IBinaryExpression { diff --git a/sdk/typescript-schema/expression/expression.ts b/sdk/typescript-schema/expression/expression.ts index c2b2c1f..cf851a6 100644 --- a/sdk/typescript-schema/expression/expression.ts +++ b/sdk/typescript-schema/expression/expression.ts @@ -1,9 +1,9 @@ -import { BinaryBoolExpression, BoolExpression, ManyBoolExpression, UnaryBoolExpression, ValueBoolExpression } from "./boolean-expression"; +import { BoolExpression, ValueBoolExpression } from "./boolean-expression"; import { DateExpression, ValueDateExpression } from "./date-expression"; -import { AggregateNumberExpression, BinaryNumberExpression, NumberExpression, ValueNumberExpression } from "./number-expression"; +import { NumberExpression, ValueNumberExpression } from "./number-expression"; import { LocationExpression, ValueLocationExpression } from "./location-expression"; import { StringExpression, ValueStringExpression } from "./string-expression"; -import { IBinaryExpression } from "./expression-interfaces"; +import { IAggregateExpression, IBinaryExpression, IManyExpression, IUnaryExpression } from "./expression-interfaces"; import { Literal } from "../literal/literal"; /** @@ -17,26 +17,26 @@ export type ValueExpression = | ValueStringExpression /** - * @title UnaryExpression - */ -export type UnaryExpression = UnaryBoolExpression +// * @title UnaryExpression +// */ +// export type UnaryExpression = UnaryBoolExpression -/** - * @title BinaryExpression - */ -export type BinaryExpression = BinaryBoolExpression | BinaryNumberExpression +// /** +// * @title BinaryExpression +// */ +// export type BinaryExpression = BinaryBoolExpression | BinaryNumberExpression -/** - * @title ManyExpression - */ -export type ManyExpression = ManyBoolExpression +// /** +// * @title ManyExpression +// */ +// export type ManyExpression = ManyBoolExpression -/** - * @title AggregateExpression - */ -export type AggregateExpression = AggregateNumberExpression +// /** +// * @title AggregateExpression +// */ +// export type AggregateExpression = AggregateNumberExpression /** * @title Expression @@ -44,10 +44,10 @@ export type AggregateExpression = AggregateNumberExpression */ export type Expression = ValueExpression - | UnaryExpression - // | BinaryExpression + | IUnaryExpression | IBinaryExpression - | ManyExpression + | IManyExpression + | IAggregateExpression | BoolExpression | NumberExpression | StringExpression diff --git a/sdk/typescript-schema/schema/audience-schema.json b/sdk/typescript-schema/schema/audience-schema.json index b54a348..c9b2bb3 100644 --- a/sdk/typescript-schema/schema/audience-schema.json +++ b/sdk/typescript-schema/schema/audience-schema.json @@ -15,10 +15,6 @@ "title": "AbsoluteDate", "type": "object" }, - "AggregateExpression": { - "$ref": "#/definitions/AggregateNumberExpression", - "title": "AggregateExpression" - }, "AggregateNumberExpression": { "additionalProperties": false, "properties": { @@ -137,17 +133,6 @@ ], "title": "BoolBinaryExpression" }, - "BinaryExpression": { - "anyOf": [ - { - "$ref": "#/definitions/BinaryBoolExpression" - }, - { - "$ref": "#/definitions/BinaryNumberExpression" - } - ], - "title": "BinaryExpression" - }, "BinaryNumberExpression": { "additionalProperties": false, "properties": { @@ -264,13 +249,16 @@ "$ref": "#/definitions/ValueExpression" }, { - "$ref": "#/definitions/UnaryExpression" + "$ref": "#/definitions/IUnaryExpression" }, { "$ref": "#/definitions/IBinaryExpression" }, { - "$ref": "#/definitions/ManyExpression" + "$ref": "#/definitions/IManyExpression" + }, + { + "$ref": "#/definitions/IAggregateExpression" }, { "$ref": "#/definitions/BoolExpression" @@ -344,7 +332,7 @@ ], "type": "object" }, - "IUnaryExpression": { + "IUnaryExpression": { "additionalProperties": false, "properties": { "operand": { @@ -519,10 +507,6 @@ "$ref": "#/definitions/LogicalManyBoolExpression", "title": "ManyBoolExpression" }, - "ManyExpression": { - "$ref": "#/definitions/ManyBoolExpression", - "title": "ManyExpression" - }, "ModelPath": { "additionalProperties": false, "description": "Represents a model path reference within a data model.\nExamples:\n1. Simple model path:\n{ \"model\": \"user\", \"path\": \"email\" }\n\n2. Nested model path:\n{ \"model\": \"order\", \"path\": \"items.productId\" }\n\n3. Deeply nested model path:\n{ \"model\": \"event\", \"path\": \"attributes.purchase.amount\" }", @@ -705,10 +689,6 @@ ], "type": "string" }, - "UnaryExpression": { - "$ref": "#/definitions/UnaryBoolExpression", - "title": "UnaryExpression" - }, "ValueBoolExpression": { "anyOf": [ { From 93af3f4d4e4a4a4e0063be2671b5bb4f274ca771 Mon Sep 17 00:00:00 2001 From: cbowie-mp Date: Tue, 1 Jul 2025 09:49:12 -0700 Subject: [PATCH 16/16] Fix operator --- schema/audience-definition-schema.json | 53 +++++++++++++++++-- .../mp_audience_sdk/models/audience_models.py | 24 ++++++++- sdk/typescript-schema/common/operator.ts | 2 + .../expression/expression-interfaces.ts | 13 +++-- .../schema/audience-schema.json | 53 +++++++++++++++++-- 5 files changed, 134 insertions(+), 11 deletions(-) diff --git a/schema/audience-definition-schema.json b/schema/audience-definition-schema.json index c9b2bb3..9f1c58a 100644 --- a/schema/audience-definition-schema.json +++ b/schema/audience-definition-schema.json @@ -293,11 +293,15 @@ }, "operand": { "$ref": "#/definitions/Expression" + }, + "operator": { + "$ref": "#/definitions/Operator" } }, "required": [ + "group_by_model", "operand", - "group_by_model" + "operator" ], "type": "object" }, @@ -307,12 +311,16 @@ "left": { "$ref": "#/definitions/Expression" }, + "operator": { + "$ref": "#/definitions/Operator" + }, "right": { "$ref": "#/definitions/Expression" } }, "required": [ "left", + "operator", "right" ], "type": "object" @@ -325,10 +333,14 @@ "$ref": "#/definitions/Expression" }, "type": "array" + }, + "operator": { + "$ref": "#/definitions/Operator" } }, "required": [ - "expressions" + "expressions", + "operator" ], "type": "object" }, @@ -337,10 +349,14 @@ "properties": { "operand": { "$ref": "#/definitions/Expression" + }, + "operator": { + "$ref": "#/definitions/Operator" } }, "required": [ - "operand" + "operand", + "operator" ], "type": "object" }, @@ -587,6 +603,37 @@ "description": "Represents an expression that evaluates to a number.", "title": "NumberExpression" }, + "Operator": { + "anyOf": [ + { + "$ref": "#/definitions/LogicalBoolOperator" + }, + { + "$ref": "#/definitions/LocationBoolOperator" + }, + { + "$ref": "#/definitions/AggregationNumberOperator" + }, + { + "$ref": "#/definitions/BinaryNumberOperator" + }, + { + "$ref": "#/definitions/AudienceOperator" + }, + { + "$ref": "#/definitions/ListBoolOperator" + }, + { + "$ref": "#/definitions/StringBoolOperator" + }, + { + "$ref": "#/definitions/NumberBoolOperator" + }, + { + "$ref": "#/definitions/UnaryBoolOperator" + } + ] + }, "RelativeDate": { "additionalProperties": false, "description": "Represents a date/time relative to the current time.\nExamples:\n1. 7 days ago:\n{ relative: { offset: -7, unit: \"day\" } }\n\n2. Start of current month:\n{ relative: { offset: 0, unit: \"month\", boundary: \"start\" } }\n\n3. End of previous quarter:\n{ relative: { offset: -1, unit: \"quarter\", boundary: \"end\" } }", diff --git a/sdk/python/mp_audience_sdk/models/audience_models.py b/sdk/python/mp_audience_sdk/models/audience_models.py index 5ea27fd..ee53e53 100644 --- a/sdk/python/mp_audience_sdk/models/audience_models.py +++ b/sdk/python/mp_audience_sdk/models/audience_models.py @@ -1,6 +1,6 @@ # generated by datamodel-codegen: # filename: audience-definition-schema.json -# timestamp: 2025-07-01T00:56:12+00:00 +# timestamp: 2025-07-01T01:01:04+00:00 from __future__ import annotations @@ -242,6 +242,24 @@ class LocationExpression(RootModel["ValueLocationExpression"]): ) +class Operator( + RootModel[ + "LogicalBoolOperator | LocationBoolOperator | AggregationNumberOperator | BinaryNumberOperator | AudienceOperator | ListBoolOperator | StringBoolOperator | NumberBoolOperator | UnaryBoolOperator" + ] +): + root: ( + LogicalBoolOperator + | LocationBoolOperator + | AggregationNumberOperator + | BinaryNumberOperator + | AudienceOperator + | ListBoolOperator + | StringBoolOperator + | NumberBoolOperator + | UnaryBoolOperator + ) + + class StringExpression(RootModel["ValueStringExpression"]): root: ValueStringExpression = Field(..., title="StringExpression") @@ -391,6 +409,7 @@ class IAggregateExpression(BaseModel): condition: Expression | None = None group_by_model: str operand: Expression + operator: Operator class IBinaryExpression(BaseModel): @@ -398,6 +417,7 @@ class IBinaryExpression(BaseModel): extra="forbid", ) left: Expression + operator: Operator right: Expression @@ -406,6 +426,7 @@ class IManyExpression(BaseModel): extra="forbid", ) expressions: List[Expression] + operator: Operator class IUnaryExpression(BaseModel): @@ -413,6 +434,7 @@ class IUnaryExpression(BaseModel): extra="forbid", ) operand: Expression + operator: Operator class LogicalBoolExpression(BaseModel): diff --git a/sdk/typescript-schema/common/operator.ts b/sdk/typescript-schema/common/operator.ts index fddd643..5232c20 100644 --- a/sdk/typescript-schema/common/operator.ts +++ b/sdk/typescript-schema/common/operator.ts @@ -114,3 +114,5 @@ export type LocationBoolOperator = export type LogicalBoolOperator = "and" | "or" + +export type Operator = LogicalBoolOperator | LocationBoolOperator | AggregationNumberOperator | BinaryNumberOperator | AudienceOperator | ListBoolOperator | StringBoolOperator | NumberBoolOperator | UnaryBoolOperator diff --git a/sdk/typescript-schema/expression/expression-interfaces.ts b/sdk/typescript-schema/expression/expression-interfaces.ts index 736363a..caeb006 100644 --- a/sdk/typescript-schema/expression/expression-interfaces.ts +++ b/sdk/typescript-schema/expression/expression-interfaces.ts @@ -1,19 +1,24 @@ +import { Operator } from "../common/operator" import { Expression } from "./expression" -export interface IUnaryExpression { +interface IExpression { + operator: Operator +} + +export interface IUnaryExpression extends IExpression { operand: Expression } -export interface IBinaryExpression { +export interface IBinaryExpression extends IExpression { left: Expression right: Expression } -export interface IManyExpression { +export interface IManyExpression extends IExpression { expressions: Expression[] } -export interface IAggregateExpression { +export interface IAggregateExpression extends IExpression { condition?: Expression operand: Expression group_by_model: string diff --git a/sdk/typescript-schema/schema/audience-schema.json b/sdk/typescript-schema/schema/audience-schema.json index c9b2bb3..9f1c58a 100644 --- a/sdk/typescript-schema/schema/audience-schema.json +++ b/sdk/typescript-schema/schema/audience-schema.json @@ -293,11 +293,15 @@ }, "operand": { "$ref": "#/definitions/Expression" + }, + "operator": { + "$ref": "#/definitions/Operator" } }, "required": [ + "group_by_model", "operand", - "group_by_model" + "operator" ], "type": "object" }, @@ -307,12 +311,16 @@ "left": { "$ref": "#/definitions/Expression" }, + "operator": { + "$ref": "#/definitions/Operator" + }, "right": { "$ref": "#/definitions/Expression" } }, "required": [ "left", + "operator", "right" ], "type": "object" @@ -325,10 +333,14 @@ "$ref": "#/definitions/Expression" }, "type": "array" + }, + "operator": { + "$ref": "#/definitions/Operator" } }, "required": [ - "expressions" + "expressions", + "operator" ], "type": "object" }, @@ -337,10 +349,14 @@ "properties": { "operand": { "$ref": "#/definitions/Expression" + }, + "operator": { + "$ref": "#/definitions/Operator" } }, "required": [ - "operand" + "operand", + "operator" ], "type": "object" }, @@ -587,6 +603,37 @@ "description": "Represents an expression that evaluates to a number.", "title": "NumberExpression" }, + "Operator": { + "anyOf": [ + { + "$ref": "#/definitions/LogicalBoolOperator" + }, + { + "$ref": "#/definitions/LocationBoolOperator" + }, + { + "$ref": "#/definitions/AggregationNumberOperator" + }, + { + "$ref": "#/definitions/BinaryNumberOperator" + }, + { + "$ref": "#/definitions/AudienceOperator" + }, + { + "$ref": "#/definitions/ListBoolOperator" + }, + { + "$ref": "#/definitions/StringBoolOperator" + }, + { + "$ref": "#/definitions/NumberBoolOperator" + }, + { + "$ref": "#/definitions/UnaryBoolOperator" + } + ] + }, "RelativeDate": { "additionalProperties": false, "description": "Represents a date/time relative to the current time.\nExamples:\n1. 7 days ago:\n{ relative: { offset: -7, unit: \"day\" } }\n\n2. Start of current month:\n{ relative: { offset: 0, unit: \"month\", boundary: \"start\" } }\n\n3. End of previous quarter:\n{ relative: { offset: -1, unit: \"quarter\", boundary: \"end\" } }",