diff --git a/independent-publisher-connectors/Power Fx Functions/ConnectorPackage.zip b/independent-publisher-connectors/Power Fx Functions/ConnectorPackage.zip new file mode 100644 index 0000000000..87b3e533a4 Binary files /dev/null and b/independent-publisher-connectors/Power Fx Functions/ConnectorPackage.zip differ diff --git a/independent-publisher-connectors/Power Fx Functions/apiDefinition.swagger.json b/independent-publisher-connectors/Power Fx Functions/apiDefinition.swagger.json new file mode 100644 index 0000000000..184bb6af07 --- /dev/null +++ b/independent-publisher-connectors/Power Fx Functions/apiDefinition.swagger.json @@ -0,0 +1,3530 @@ +{ + "swagger": "2.0", + "info": { + "title": "Power Fx Functions", + "description": "A comprehensive Power Fx function library providing 270+ mathematical, text, logical, date and time, table manipulation, conversion, and utility functions using custom C# script execution.", + "version": "1.0.0", + "contact": { + "name": "Troy Taylor", + "email": "troy@troystaylor.com" + } + }, + "x-ms-connector-metadata": [ + { + "propertyName": "Website", + "propertyValue": "https://troystaylor.com" + }, + { + "propertyName": "Privacy policy", + "propertyValue": "https://troystaylor.com/privacy" + }, + { + "propertyName": "Categories", + "propertyValue": "Data;Productivity" + } + ], + "host": "troystaylor.com", + "basePath": "/", + "schemes": [ + "https" + ], + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "paths": { + "/evaluate": { + "post": { + "operationId": "EvaluateFormula", + "summary": "Evaluate Power Fx Formula", + "description": "Evaluates a Power Fx formula and returns the result with type information.", + "x-ms-summary": "Evaluate Formula", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EvaluateRequest" + } + } + ], + "responses": { + "200": { + "description": "Formula evaluation successful", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/EvaluateResponse" + } + }, + "400": { + "description": "Invalid formula or evaluation error", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/parse": { + "post": { + "operationId": "ParseFormula", + "summary": "Parse Power Fx Formula", + "description": "Parses a Power Fx formula and returns syntax tree information.", + "x-ms-summary": "Parse Formula", + "x-ms-visibility": "advanced", + "parameters": [ + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ParseRequest" + } + } + ], + "responses": { + "200": { + "description": "Formula parsing successful", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/ParseResponse" + } + }, + "400": { + "description": "Invalid formula syntax", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/validate": { + "post": { + "operationId": "ValidateFormula", + "summary": "Validate Power Fx Formula", + "description": "Validates a Power Fx formula and returns any syntax or semantic errors.", + "x-ms-summary": "Validate Formula", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ValidateRequest" + } + } + ], + "responses": { + "200": { + "description": "Formula validation completed", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/ValidateResponse" + } + } + } + } + }, + "/functions/math/{operation}": { + "post": { + "operationId": "ExecuteMathFunction", + "summary": "Execute Math Function", + "description": "Executes a mathematical function with provided arguments.", + "x-ms-summary": "Math Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "abs", + "power", + "sqrt", + "mod", + "round", + "sin", + "cos", + "tan", + "ln", + "log", + "exp", + "pi", + "int", + "roundup", + "rounddown", + "trunc", + "asin", + "acos", + "atan", + "atan2", + "acot", + "cot", + "radians", + "degrees", + "rand", + "randbetween", + "average", + "max", + "min", + "sum", + "count", + "counta", + "gcd", + "lcm", + "ceiling", + "floor", + "pmt", + "pv", + "fv", + "nper", + "rate" + ], + "x-ms-enum": { + "name": "MathOperation", + "modelAsString": true, + "values": [ + { + "value": "abs", + "displayName": "Absolute Value" + }, + { + "value": "power", + "displayName": "Power/Exponentiation" + }, + { + "value": "sqrt", + "displayName": "Square Root" + }, + { + "value": "mod", + "displayName": "Modulo" + }, + { + "value": "round", + "displayName": "Round" + }, + { + "value": "sin", + "displayName": "Sine" + }, + { + "value": "cos", + "displayName": "Cosine" + }, + { + "value": "tan", + "displayName": "Tangent" + }, + { + "value": "ln", + "displayName": "Natural Logarithm" + }, + { + "value": "log", + "displayName": "Logarithm" + }, + { + "value": "exp", + "displayName": "Exponential" + }, + { + "value": "pi", + "displayName": "Pi Constant" + }, + { + "value": "int", + "displayName": "Integer Part" + }, + { + "value": "roundup", + "displayName": "Round Up" + }, + { + "value": "rounddown", + "displayName": "Round Down" + }, + { + "value": "trunc", + "displayName": "Truncate" + }, + { + "value": "asin", + "displayName": "Arcsine" + }, + { + "value": "acos", + "displayName": "Arccosine" + }, + { + "value": "atan", + "displayName": "Arctangent" + }, + { + "value": "atan2", + "displayName": "Two-Argument Arctangent" + }, + { + "value": "acot", + "displayName": "Arccotangent" + }, + { + "value": "cot", + "displayName": "Cotangent" + }, + { + "value": "radians", + "displayName": "Degrees to Radians" + }, + { + "value": "degrees", + "displayName": "Radians to Degrees" + }, + { + "value": "rand", + "displayName": "Random Number" + }, + { + "value": "randbetween", + "displayName": "Random Between" + }, + { + "value": "average", + "displayName": "Average" + }, + { + "value": "max", + "displayName": "Maximum" + }, + { + "value": "min", + "displayName": "Minimum" + }, + { + "value": "sum", + "displayName": "Sum" + }, + { + "value": "count", + "displayName": "Count" + }, + { + "value": "counta", + "displayName": "Count Non-Empty" + }, + { + "value": "gcd", + "displayName": "Greatest Common Divisor" + }, + { + "value": "lcm", + "displayName": "Least Common Multiple" + }, + { + "value": "ceiling", + "displayName": "Ceiling" + }, + { + "value": "floor", + "displayName": "Floor" + } + ] + }, + "x-ms-summary": "Math Operation", + "description": "The mathematical operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/MathFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Math function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid arguments or operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/text/{operation}": { + "post": { + "operationId": "ExecuteTextFunction", + "summary": "Execute Text Function", + "description": "Executes a text manipulation function with provided arguments.", + "x-ms-summary": "Text Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "left", + "right", + "mid", + "len", + "upper", + "lower", + "trim", + "find", + "replace", + "concatenate", + "split", + "trimends", + "proper", + "search", + "substitute", + "startswith", + "endswith", + "char", + "unichar", + "encodeurl", + "encodehtml", + "plaintext", + "concat", + "ismatch", + "match", + "matchall", + "rept", + "fixed", + "dollar" + ], + "x-ms-enum": { + "name": "TextOperation", + "modelAsString": true, + "values": [ + { + "value": "left", + "displayName": "Left Characters" + }, + { + "value": "right", + "displayName": "Right Characters" + }, + { + "value": "mid", + "displayName": "Middle Characters" + }, + { + "value": "len", + "displayName": "Length" + }, + { + "value": "upper", + "displayName": "Uppercase" + }, + { + "value": "lower", + "displayName": "Lowercase" + }, + { + "value": "trim", + "displayName": "Trim Whitespace" + }, + { + "value": "find", + "displayName": "Find Text" + }, + { + "value": "replace", + "displayName": "Replace Text" + }, + { + "value": "concatenate", + "displayName": "Concatenate" + }, + { + "value": "split", + "displayName": "Split Text" + }, + { + "value": "trimends", + "displayName": "Trim Both Ends" + }, + { + "value": "proper", + "displayName": "Proper Case" + }, + { + "value": "search", + "displayName": "Search Text" + }, + { + "value": "substitute", + "displayName": "Substitute Text" + }, + { + "value": "startswith", + "displayName": "Starts With" + }, + { + "value": "endswith", + "displayName": "Ends With" + }, + { + "value": "char", + "displayName": "Character from Code" + }, + { + "value": "unichar", + "displayName": "Unicode Character" + }, + { + "value": "encodeurl", + "displayName": "URL Encode" + }, + { + "value": "encodehtml", + "displayName": "HTML Encode" + }, + { + "value": "plaintext", + "displayName": "Plain Text" + }, + { + "value": "concat", + "displayName": "Concatenate" + }, + { + "value": "ismatch", + "displayName": "Is Match (Regex)" + }, + { + "value": "match", + "displayName": "Match (Regex)" + }, + { + "value": "matchall", + "displayName": "Match All (Regex)" + }, + { + "value": "rept", + "displayName": "Repeat Text" + }, + { + "value": "fixed", + "displayName": "Format Number" + }, + { + "value": "dollar", + "displayName": "Format Currency" + } + ] + }, + "x-ms-summary": "Text Operation", + "description": "The text operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TextFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Text function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid arguments or operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/logical/{operation}": { + "post": { + "operationId": "ExecuteLogicalFunction", + "summary": "Execute Logical Function", + "description": "Executes a logical function with provided arguments.", + "x-ms-summary": "Logical Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "and", + "or", + "not", + "if", + "isblank", + "isempty", + "isnumeric", + "iserror", + "switch", + "iferror", + "error", + "isblankorerror", + "istoday", + "isutctoday" + ], + "x-ms-enum": { + "name": "LogicalOperation", + "modelAsString": true, + "values": [ + { + "value": "and", + "displayName": "Logical AND" + }, + { + "value": "or", + "displayName": "Logical OR" + }, + { + "value": "not", + "displayName": "Logical NOT" + }, + { + "value": "if", + "displayName": "If Condition" + }, + { + "value": "isblank", + "displayName": "Is Blank" + }, + { + "value": "isempty", + "displayName": "Is Empty" + }, + { + "value": "isnumeric", + "displayName": "Is Numeric" + }, + { + "value": "iserror", + "displayName": "Is Error" + }, + { + "value": "switch", + "displayName": "Switch Statement" + }, + { + "value": "iferror", + "displayName": "If Error" + }, + { + "value": "error", + "displayName": "Create Error" + }, + { + "value": "isblankorerror", + "displayName": "Is Blank or Error" + }, + { + "value": "istoday", + "displayName": "Is Today" + }, + { + "value": "isutctoday", + "displayName": "Is UTC Today" + } + ] + }, + "x-ms-summary": "Logical Operation", + "description": "The logical operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LogicalFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Logical function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid arguments or operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/datetime/{operation}": { + "post": { + "operationId": "ExecuteDateTimeFunction", + "summary": "Execute Date Time Function", + "description": "Executes a date/time function with provided arguments.", + "x-ms-summary": "Date Time Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "now", + "today", + "year", + "month", + "day", + "hour", + "minute", + "second", + "dateadd", + "datediff", + "utcnow", + "utctoday", + "date", + "datetime", + "time", + "datevalue", + "datetimevalue", + "timevalue", + "weekday", + "edate", + "eomonth", + "weeknum", + "isoweeknum" + ], + "x-ms-enum": { + "name": "DateTimeOperation", + "modelAsString": true, + "values": [ + { + "value": "now", + "displayName": "Current Date/Time" + }, + { + "value": "today", + "displayName": "Today's Date" + }, + { + "value": "year", + "displayName": "Year" + }, + { + "value": "month", + "displayName": "Month" + }, + { + "value": "day", + "displayName": "Day" + }, + { + "value": "hour", + "displayName": "Hour" + }, + { + "value": "minute", + "displayName": "Minute" + }, + { + "value": "second", + "displayName": "Second" + }, + { + "value": "dateadd", + "displayName": "Add to Date" + }, + { + "value": "datediff", + "displayName": "Date Difference" + }, + { + "value": "utcnow", + "displayName": "Current UTC Date/Time" + }, + { + "value": "utctoday", + "displayName": "Today's UTC Date" + }, + { + "value": "date", + "displayName": "Create Date" + }, + { + "value": "datetime", + "displayName": "Create DateTime" + }, + { + "value": "time", + "displayName": "Create Time" + }, + { + "value": "datevalue", + "displayName": "Parse Date" + }, + { + "value": "datetimevalue", + "displayName": "Parse DateTime" + }, + { + "value": "timevalue", + "displayName": "Parse Time" + }, + { + "value": "weekday", + "displayName": "Day of Week" + }, + { + "value": "edate", + "displayName": "End Date" + }, + { + "value": "eomonth", + "displayName": "End of Month" + }, + { + "value": "weeknum", + "displayName": "Week Number" + }, + { + "value": "isoweeknum", + "displayName": "ISO Week Number" + } + ] + }, + "x-ms-summary": "Date Time Operation", + "description": "The date/time operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DateTimeFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Date/time function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid arguments or operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/conversion/{operation}": { + "post": { + "operationId": "ExecuteConversionFunction", + "summary": "Execute Type Conversion Function", + "description": "Executes a type conversion function with provided arguments.", + "x-ms-summary": "Conversion Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "text", + "value", + "boolean", + "decimal", + "float", + "guid", + "astype" + ], + "x-ms-enum": { + "name": "ConversionOperation", + "modelAsString": true, + "values": [ + { + "value": "text", + "displayName": "Convert to Text" + }, + { + "value": "value", + "displayName": "Convert to Number" + }, + { + "value": "boolean", + "displayName": "Convert to Boolean" + }, + { + "value": "decimal", + "displayName": "Convert to Decimal" + }, + { + "value": "float", + "displayName": "Convert to Float" + }, + { + "value": "guid", + "displayName": "Generate GUID" + }, + { + "value": "astype", + "displayName": "Convert Type" + } + ] + }, + "x-ms-summary": "Conversion Operation", + "description": "The conversion operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ConversionFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Conversion function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid arguments or operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/types/check": { + "post": { + "operationId": "CheckValueType", + "summary": "Check Value Type", + "description": "Determines the Power Fx type of a given value.", + "x-ms-summary": "Check Type", + "x-ms-visibility": "advanced", + "parameters": [ + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TypeCheckRequest" + } + } + ], + "responses": { + "200": { + "description": "Type check completed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/TypeCheckResponse" + } + } + } + } + }, + "/types/coerce": { + "post": { + "operationId": "CoerceValueType", + "summary": "Coerce Value Type", + "description": "Attempts to coerce a value to a specific Power Fx type.", + "x-ms-summary": "Coerce Type", + "x-ms-visibility": "advanced", + "parameters": [ + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TypeCoerceRequest" + } + } + ], + "responses": { + "200": { + "description": "Type coercion completed", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/TypeCoerceResponse" + } + }, + "400": { + "description": "Type coercion failed", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/table/{operation}": { + "post": { + "operationId": "ExecuteTableFunction", + "summary": "Execute Table Function", + "description": "Executes a table manipulation function with provided arguments.", + "x-ms-summary": "Table Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "addcolumns", + "filter", + "sort", + "groupby", + "summarize", + "distinct", + "firstn", + "lastn", + "table", + "sequence", + "countrows", + "countif", + "first", + "last", + "index", + "shuffle" + ], + "x-ms-enum": { + "name": "TableOperation", + "modelAsString": true, + "values": [ + { + "value": "addcolumns", + "displayName": "Add Columns" + }, + { + "value": "filter", + "displayName": "Filter Rows" + }, + { + "value": "sort", + "displayName": "Sort Table" + }, + { + "value": "groupby", + "displayName": "Group By" + }, + { + "value": "summarize", + "displayName": "Summarize" + }, + { + "value": "distinct", + "displayName": "Distinct Values" + }, + { + "value": "firstn", + "displayName": "First N Rows" + }, + { + "value": "lastn", + "displayName": "Last N Rows" + }, + { + "value": "table", + "displayName": "Create Table" + }, + { + "value": "sequence", + "displayName": "Number Sequence" + }, + { + "value": "countrows", + "displayName": "Count Rows" + }, + { + "value": "countif", + "displayName": "Count If" + }, + { + "value": "first", + "displayName": "First Row" + }, + { + "value": "last", + "displayName": "Last Row" + }, + { + "value": "index", + "displayName": "Index Row" + }, + { + "value": "shuffle", + "displayName": "Shuffle Rows" + } + ] + }, + "x-ms-summary": "Table Operation", + "description": "The table operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TableFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Table function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid arguments or operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/utility/{operation}": { + "post": { + "operationId": "ExecuteUtilityFunction", + "summary": "Execute Utility Function", + "description": "Executes utility functions like encoding, JSON parsing, etc.", + "x-ms-summary": "Utility Function", + "x-ms-visibility": "advanced", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "rand", + "randbetween", + "sequence", + "shuffle", + "sort", + "reverse", + "coalesce", + "collect", + "clear", + "remove", + "removeif", + "update", + "updateif", + "patch", + "parsejson", + "dec2hex", + "hex2dec", + "blank", + "rgba", + "colorvalue", + "colorfade", + "forall", + "with" + ], + "x-ms-enum": { + "name": "UtilityOperation", + "modelAsString": true, + "values": [ + { + "value": "rand", + "displayName": "Random Number" + }, + { + "value": "randbetween", + "displayName": "Random Between" + }, + { + "value": "sequence", + "displayName": "Number Sequence" + }, + { + "value": "shuffle", + "displayName": "Shuffle Array" + }, + { + "value": "sort", + "displayName": "Sort Array" + }, + { + "value": "reverse", + "displayName": "Reverse Array" + }, + { + "value": "coalesce", + "displayName": "First Non-Empty" + }, + { + "value": "collect", + "displayName": "Collect Records" + }, + { + "value": "clear", + "displayName": "Clear Collection" + }, + { + "value": "remove", + "displayName": "Remove Records" + }, + { + "value": "removeif", + "displayName": "Remove If" + }, + { + "value": "update", + "displayName": "Update Records" + }, + { + "value": "updateif", + "displayName": "Update If" + }, + { + "value": "patch", + "displayName": "Patch Records" + }, + { + "value": "parsejson", + "displayName": "Parse JSON" + }, + { + "value": "dec2hex", + "displayName": "Decimal to Hex" + }, + { + "value": "hex2dec", + "displayName": "Hex to Decimal" + }, + { + "value": "blank", + "displayName": "Blank Value" + }, + { + "value": "rgba", + "displayName": "RGBA Color" + }, + { + "value": "colorvalue", + "displayName": "Color Value" + }, + { + "value": "colorfade", + "displayName": "Color Fade" + }, + { + "value": "forall", + "displayName": "For All Records" + }, + { + "value": "with", + "displayName": "With Record Context" + } + ] + }, + "x-ms-summary": "Utility Operation", + "description": "The utility operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/UtilityFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Utility function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid arguments or operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/date-parts/{part}": { + "post": { + "operationId": "ExtractDatePart", + "summary": "Extract Date Part", + "description": "Extracts a specific part from a date/time value.", + "x-ms-summary": "Extract Date Part", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "part", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "year", + "month", + "day", + "hour", + "minute", + "second", + "weekday", + "dayofyear", + "quarter", + "weeknum", + "isoweeknum" + ], + "x-ms-enum": { + "name": "DatePart", + "modelAsString": true, + "values": [ + { + "value": "year", + "displayName": "Year" + }, + { + "value": "month", + "displayName": "Month" + }, + { + "value": "day", + "displayName": "Day" + }, + { + "value": "hour", + "displayName": "Hour" + }, + { + "value": "minute", + "displayName": "Minute" + }, + { + "value": "second", + "displayName": "Second" + }, + { + "value": "weekday", + "displayName": "Day of Week" + }, + { + "value": "dayofyear", + "displayName": "Day of Year" + }, + { + "value": "quarter", + "displayName": "Quarter" + }, + { + "value": "weeknum", + "displayName": "Week Number" + }, + { + "value": "isoweeknum", + "displayName": "ISO Week Number" + } + ] + }, + "x-ms-summary": "Date Part", + "description": "The specific date part to extract.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/DatePartRequest" + } + } + ], + "responses": { + "200": { + "description": "Date part extracted successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid date or part", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/text-transform/{transform}": { + "post": { + "operationId": "TransformText", + "summary": "Transform Text", + "description": "Applies a specific text transformation.", + "x-ms-summary": "Transform Text", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "transform", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "upper", + "lower", + "proper", + "trim", + "trimends", + "trimstart", + "trimend", + "reverse" + ], + "x-ms-enum": { + "name": "TextTransform", + "modelAsString": true, + "values": [ + { + "value": "upper", + "displayName": "Uppercase" + }, + { + "value": "lower", + "displayName": "Lowercase" + }, + { + "value": "proper", + "displayName": "Proper Case" + }, + { + "value": "trim", + "displayName": "Trim Whitespace" + }, + { + "value": "trimends", + "displayName": "Trim Both Ends" + }, + { + "value": "trimstart", + "displayName": "Trim Start" + }, + { + "value": "trimend", + "displayName": "Trim End" + }, + { + "value": "reverse", + "displayName": "Reverse Text" + } + ] + }, + "x-ms-summary": "Text Transform", + "description": "The text transformation to apply.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TextTransformRequest" + } + } + ], + "responses": { + "200": { + "description": "Text transformed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid text or transform", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/math-round/{method}": { + "post": { + "operationId": "RoundNumber", + "summary": "Round Number", + "description": "Rounds a number using the specified method.", + "x-ms-summary": "Round Number", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "method", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "round", + "roundup", + "rounddown", + "trunc", + "int", + "ceiling", + "floor" + ], + "x-ms-enum": { + "name": "RoundingMethod", + "modelAsString": true, + "values": [ + { + "value": "round", + "displayName": "Round" + }, + { + "value": "roundup", + "displayName": "Round Up" + }, + { + "value": "rounddown", + "displayName": "Round Down" + }, + { + "value": "trunc", + "displayName": "Truncate" + }, + { + "value": "int", + "displayName": "Integer Part" + }, + { + "value": "ceiling", + "displayName": "Ceiling" + }, + { + "value": "floor", + "displayName": "Floor" + } + ] + }, + "x-ms-summary": "Rounding Method", + "description": "The rounding method to use.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/RoundingRequest" + } + } + ], + "responses": { + "200": { + "description": "Number rounded successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid number or method", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/math-trig/{function}": { + "post": { + "operationId": "TrigFunction", + "summary": "Trigonometric Function", + "description": "Executes a trigonometric function.", + "x-ms-summary": "Trigonometric Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "function", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "sin", + "cos", + "tan", + "asin", + "acos", + "atan", + "atan2", + "cot", + "acot", + "sec", + "csc", + "sinh", + "cosh", + "tanh" + ], + "x-ms-enum": { + "name": "TrigFunction", + "modelAsString": true, + "values": [ + { + "value": "sin", + "displayName": "Sine" + }, + { + "value": "cos", + "displayName": "Cosine" + }, + { + "value": "tan", + "displayName": "Tangent" + }, + { + "value": "asin", + "displayName": "Arcsine" + }, + { + "value": "acos", + "displayName": "Arccosine" + }, + { + "value": "atan", + "displayName": "Arctangent" + }, + { + "value": "atan2", + "displayName": "Two-Argument Arctangent" + }, + { + "value": "cot", + "displayName": "Cotangent" + }, + { + "value": "acot", + "displayName": "Arccotangent" + }, + { + "value": "sec", + "displayName": "Secant" + }, + { + "value": "csc", + "displayName": "Cosecant" + }, + { + "value": "sinh", + "displayName": "Hyperbolic Sine" + }, + { + "value": "cosh", + "displayName": "Hyperbolic Cosine" + }, + { + "value": "tanh", + "displayName": "Hyperbolic Tangent" + } + ] + }, + "x-ms-summary": "Trigonometric Function", + "description": "The trigonometric function to execute.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TrigFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Trigonometric function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid arguments", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/text-search/{type}": { + "post": { + "operationId": "SearchText", + "summary": "Search Text", + "description": "Searches for text using the specified method.", + "x-ms-summary": "Search Text", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "type", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "find", + "search", + "startswith", + "endswith", + "contains", + "exact" + ], + "x-ms-enum": { + "name": "TextSearchType", + "modelAsString": true, + "values": [ + { + "value": "find", + "displayName": "Find Position" + }, + { + "value": "search", + "displayName": "Search Text" + }, + { + "value": "startswith", + "displayName": "Starts With" + }, + { + "value": "endswith", + "displayName": "Ends With" + }, + { + "value": "contains", + "displayName": "Contains Text" + }, + { + "value": "exact", + "displayName": "Exact Match" + } + ] + }, + "x-ms-summary": "Search Type", + "description": "The type of text search to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TextSearchRequest" + } + } + ], + "responses": { + "200": { + "description": "Text search completed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid search parameters", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/logical-condition/{type}": { + "post": { + "operationId": "EvaluateCondition", + "summary": "Evaluate Logical Condition", + "description": "Evaluates a logical condition using the specified type.", + "x-ms-summary": "Evaluate Condition", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "type", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "and", + "or", + "not", + "xor", + "nand", + "nor" + ], + "x-ms-enum": { + "name": "LogicalConditionType", + "modelAsString": true, + "values": [ + { + "value": "and", + "displayName": "Logical AND" + }, + { + "value": "or", + "displayName": "Logical OR" + }, + { + "value": "not", + "displayName": "Logical NOT" + }, + { + "value": "xor", + "displayName": "Exclusive OR" + }, + { + "value": "nand", + "displayName": "NOT AND" + }, + { + "value": "nor", + "displayName": "NOT OR" + } + ] + }, + "x-ms-summary": "Condition Type", + "description": "The type of logical condition to evaluate.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/LogicalConditionRequest" + } + } + ], + "responses": { + "200": { + "description": "Logical condition evaluated successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid condition parameters", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/type-check/{check}": { + "post": { + "operationId": "CheckValueProperty", + "summary": "Check Value Property", + "description": "Checks a specific property of a value.", + "x-ms-summary": "Check Value Property", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "check", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "isblank", + "isempty", + "isnumeric", + "istext", + "islogical", + "iserror", + "isdate", + "istime", + "isblankorerror", + "istoday", + "isutctoday" + ], + "x-ms-enum": { + "name": "TypeCheck", + "modelAsString": true, + "values": [ + { + "value": "isblank", + "displayName": "Is Blank" + }, + { + "value": "isempty", + "displayName": "Is Empty" + }, + { + "value": "isnumeric", + "displayName": "Is Numeric" + }, + { + "value": "istext", + "displayName": "Is Text" + }, + { + "value": "islogical", + "displayName": "Is Logical" + }, + { + "value": "iserror", + "displayName": "Is Error" + }, + { + "value": "isdate", + "displayName": "Is Date" + }, + { + "value": "istime", + "displayName": "Is Time" + }, + { + "value": "isblankorerror", + "displayName": "Is Blank or Error" + }, + { + "value": "istoday", + "displayName": "Is Today" + }, + { + "value": "isutctoday", + "displayName": "Is UTC Today" + } + ] + }, + "x-ms-summary": "Check Type", + "description": "The type of check to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/TypeCheckSpecificRequest" + } + } + ], + "responses": { + "200": { + "description": "Value check completed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid check parameters", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/json/{operation}": { + "post": { + "operationId": "ExecuteJSONFunction", + "summary": "Execute JSON Function", + "description": "Executes JSON parsing, formatting, and manipulation functions.", + "x-ms-summary": "JSON Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "parsejson", + "json", + "formatjson", + "jsonextract", + "jsonpath", + "isvalidjson", + "jsonmerge", + "jsonarray", + "jsonobject", + "jsonkeys", + "jsonvalues" + ], + "x-ms-enum": { + "name": "JSONOperation", + "modelAsString": true, + "values": [ + { + "value": "parsejson", + "displayName": "Parse JSON" + }, + { + "value": "json", + "displayName": "Create JSON" + }, + { + "value": "formatjson", + "displayName": "Format JSON" + }, + { + "value": "jsonextract", + "displayName": "Extract JSON Property" + }, + { + "value": "jsonpath", + "displayName": "JSON Path Query" + }, + { + "value": "isvalidjson", + "displayName": "Validate JSON" + }, + { + "value": "jsonmerge", + "displayName": "Merge JSON Objects" + }, + { + "value": "jsonarray", + "displayName": "Create JSON Array" + }, + { + "value": "jsonobject", + "displayName": "Create JSON Object" + }, + { + "value": "jsonkeys", + "displayName": "Get JSON Keys" + }, + { + "value": "jsonvalues", + "displayName": "Get JSON Values" + } + ] + }, + "x-ms-summary": "JSON Operation", + "description": "The JSON operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/JSONFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "JSON function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid JSON or operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/table-advanced/{operation}": { + "post": { + "operationId": "ExecuteAdvancedTableFunction", + "summary": "Execute Advanced Table Function", + "description": "Executes advanced table operations like joins, pivots, and complex transformations.", + "x-ms-summary": "Advanced Table Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "join", + "leftjoin", + "rightjoin", + "innerjoin", + "outerjoin", + "crossjoin", + "pivot", + "unpivot", + "transpose", + "lookup", + "xlookup", + "relate", + "unrelate", + "merge", + "append", + "union", + "intersect", + "except", + "dropcolumns", + "renamecolumns", + "showcolumns" + ], + "x-ms-enum": { + "name": "AdvancedTableOperation", + "modelAsString": true, + "values": [ + { + "value": "join", + "displayName": "Join Tables" + }, + { + "value": "leftjoin", + "displayName": "Left Join" + }, + { + "value": "rightjoin", + "displayName": "Right Join" + }, + { + "value": "innerjoin", + "displayName": "Inner Join" + }, + { + "value": "outerjoin", + "displayName": "Outer Join" + }, + { + "value": "crossjoin", + "displayName": "Cross Join" + }, + { + "value": "pivot", + "displayName": "Pivot Table" + }, + { + "value": "unpivot", + "displayName": "Unpivot Table" + }, + { + "value": "transpose", + "displayName": "Transpose Table" + }, + { + "value": "lookup", + "displayName": "Lookup Value" + }, + { + "value": "xlookup", + "displayName": "Extended Lookup" + }, + { + "value": "relate", + "displayName": "Create Relationship" + }, + { + "value": "unrelate", + "displayName": "Remove Relationship" + }, + { + "value": "merge", + "displayName": "Merge Tables" + }, + { + "value": "append", + "displayName": "Append Tables" + }, + { + "value": "union", + "displayName": "Union Tables" + }, + { + "value": "intersect", + "displayName": "Intersect Tables" + }, + { + "value": "except", + "displayName": "Except Tables" + }, + { + "value": "dropcolumns", + "displayName": "Drop Columns" + }, + { + "value": "renamecolumns", + "displayName": "Rename Columns" + }, + { + "value": "showcolumns", + "displayName": "Show Columns" + } + ] + }, + "x-ms-summary": "Advanced Table Operation", + "description": "The advanced table operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/AdvancedTableFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Advanced table function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid table operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/color/{operation}": { + "post": { + "operationId": "ExecuteColorFunction", + "summary": "Execute Color Function", + "description": "Executes color manipulation and conversion functions.", + "x-ms-summary": "Color Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "rgba", + "rgb", + "hsl", + "hsv", + "colorvalue", + "colorfade", + "colorbrightness", + "colorcontrast", + "colormix", + "colorinvert", + "hex2color", + "color2hex", + "colorred", + "colorgreen", + "colorblue", + "coloralpha" + ], + "x-ms-enum": { + "name": "ColorOperation", + "modelAsString": true, + "values": [ + { + "value": "rgba", + "displayName": "RGBA Color" + }, + { + "value": "rgb", + "displayName": "RGB Color" + }, + { + "value": "hsl", + "displayName": "HSL Color" + }, + { + "value": "hsv", + "displayName": "HSV Color" + }, + { + "value": "colorvalue", + "displayName": "Parse Color Value" + }, + { + "value": "colorfade", + "displayName": "Fade Color" + }, + { + "value": "colorbrightness", + "displayName": "Adjust Brightness" + }, + { + "value": "colorcontrast", + "displayName": "Color Contrast" + }, + { + "value": "colormix", + "displayName": "Mix Colors" + }, + { + "value": "colorinvert", + "displayName": "Invert Color" + }, + { + "value": "hex2color", + "displayName": "Hex to Color" + }, + { + "value": "color2hex", + "displayName": "Color to Hex" + }, + { + "value": "colorred", + "displayName": "Red Component" + }, + { + "value": "colorgreen", + "displayName": "Green Component" + }, + { + "value": "colorblue", + "displayName": "Blue Component" + }, + { + "value": "coloralpha", + "displayName": "Alpha Component" + } + ] + }, + "x-ms-summary": "Color Operation", + "description": "The color operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/ColorFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Color function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid color operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/encoding/{operation}": { + "post": { + "operationId": "ExecuteEncodingFunction", + "summary": "Execute Encoding Function", + "description": "Executes data encoding and decoding functions.", + "x-ms-summary": "Encoding Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "base64encode", + "base64decode", + "urlencode", + "urldecode", + "htmlencode", + "htmldecode", + "xmlencode", + "xmldecode", + "utf8encode", + "utf8decode", + "hash", + "md5", + "sha1", + "sha256" + ], + "x-ms-enum": { + "name": "EncodingOperation", + "modelAsString": true, + "values": [ + { + "value": "base64encode", + "displayName": "Base64 Encode" + }, + { + "value": "base64decode", + "displayName": "Base64 Decode" + }, + { + "value": "urlencode", + "displayName": "URL Encode" + }, + { + "value": "urldecode", + "displayName": "URL Decode" + }, + { + "value": "htmlencode", + "displayName": "HTML Encode" + }, + { + "value": "htmldecode", + "displayName": "HTML Decode" + }, + { + "value": "xmlencode", + "displayName": "XML Encode" + }, + { + "value": "xmldecode", + "displayName": "XML Decode" + }, + { + "value": "utf8encode", + "displayName": "UTF-8 Encode" + }, + { + "value": "utf8decode", + "displayName": "UTF-8 Decode" + }, + { + "value": "hash", + "displayName": "Hash Value" + }, + { + "value": "md5", + "displayName": "MD5 Hash" + }, + { + "value": "sha1", + "displayName": "SHA1 Hash" + }, + { + "value": "sha256", + "displayName": "SHA256 Hash" + } + ] + }, + "x-ms-summary": "Encoding Operation", + "description": "The encoding operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/EncodingFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Encoding function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid encoding operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + }, + "/functions/statistics/{operation}": { + "post": { + "operationId": "ExecuteStatisticsFunction", + "summary": "Execute Statistics Function", + "description": "Executes advanced statistical analysis functions.", + "x-ms-summary": "Statistics Function", + "x-ms-visibility": "important", + "parameters": [ + { + "name": "operation", + "in": "path", + "required": true, + "type": "string", + "enum": [ + "stdev", + "stdevp", + "var", + "varp", + "median", + "mode", + "percentile", + "quartile", + "correlation", + "covariance", + "regression", + "slope", + "intercept", + "rsquared", + "frequency", + "rank", + "percentrank", + "zscore", + "confidence" + ], + "x-ms-enum": { + "name": "StatisticsOperation", + "modelAsString": true, + "values": [ + { + "value": "stdev", + "displayName": "Standard Deviation" + }, + { + "value": "stdevp", + "displayName": "Population Standard Deviation" + }, + { + "value": "var", + "displayName": "Variance" + }, + { + "value": "varp", + "displayName": "Population Variance" + }, + { + "value": "median", + "displayName": "Median" + }, + { + "value": "mode", + "displayName": "Mode" + }, + { + "value": "percentile", + "displayName": "Percentile" + }, + { + "value": "quartile", + "displayName": "Quartile" + }, + { + "value": "correlation", + "displayName": "Correlation" + }, + { + "value": "covariance", + "displayName": "Covariance" + }, + { + "value": "regression", + "displayName": "Linear Regression" + }, + { + "value": "slope", + "displayName": "Regression Slope" + }, + { + "value": "intercept", + "displayName": "Regression Intercept" + }, + { + "value": "rsquared", + "displayName": "R-Squared" + }, + { + "value": "frequency", + "displayName": "Frequency" + }, + { + "value": "rank", + "displayName": "Rank" + }, + { + "value": "percentrank", + "displayName": "Percent Rank" + }, + { + "value": "zscore", + "displayName": "Z-Score" + }, + { + "value": "confidence", + "displayName": "Confidence Interval" + } + ] + }, + "x-ms-summary": "Statistics Operation", + "description": "The statistical operation to perform.", + "x-ms-url-encoding": "single" + }, + { + "name": "request", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/StatisticsFunctionRequest" + } + } + ], + "responses": { + "200": { + "description": "Statistics function executed successfully", + "x-ms-summary": "Success", + "schema": { + "$ref": "#/definitions/FunctionResponse" + } + }, + "400": { + "description": "Invalid statistics operation", + "x-ms-summary": "Error", + "schema": { + "$ref": "#/definitions/ErrorResponse" + } + } + } + } + } + }, + "definitions": { + "PowerFxValue": { + "type": "object", + "properties": { + "value": { + "description": "The actual value (can be string, number, boolean, object, or array)." + }, + "type": { + "type": "string", + "enum": [ + "Text", + "Number", + "Boolean", + "Date", + "DateTime", + "Time", + "Record", + "Table", + "Blank", + "Error" + ], + "description": "The Power Fx type of the value." + }, + "isError": { + "type": "boolean", + "description": "Whether this value represents an error." + }, + "errorMessage": { + "type": "string", + "description": "Error message if isError is true." + } + }, + "required": [ + "value", + "type" + ] + }, + "EvaluateRequest": { + "type": "object", + "properties": { + "formula": { + "type": "string", + "description": "The Power Fx formula to evaluate.", + "x-ms-summary": "Formula" + }, + "context": { + "type": "object", + "description": "Context variables and their values.", + "x-ms-summary": "Context Variables", + "additionalProperties": { + "$ref": "#/definitions/PowerFxValue" + } + }, + "options": { + "$ref": "#/definitions/EvaluationOptions" + } + }, + "required": [ + "formula" + ] + }, + "EvaluateResponse": { + "type": "object", + "properties": { + "result": { + "$ref": "#/definitions/PowerFxValue" + }, + "executionTimeMs": { + "type": "number", + "description": "Execution time in milliseconds" + }, + "warnings": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Any warnings generated during evaluation" + } + }, + "required": [ + "result" + ] + }, + "ParseRequest": { + "type": "object", + "properties": { + "formula": { + "type": "string", + "description": "The Power Fx formula to parse", + "x-ms-summary": "Formula" + }, + "options": { + "$ref": "#/definitions/ParseOptions" + } + }, + "required": [ + "formula" + ] + }, + "ParseResponse": { + "type": "object", + "properties": { + "isValid": { + "type": "boolean", + "description": "Whether the formula parsed successfully" + }, + "syntaxTree": { + "type": "object", + "description": "The parsed syntax tree representation" + }, + "tokens": { + "type": "array", + "items": { + "$ref": "#/definitions/Token" + }, + "description": "The tokens identified during parsing" + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/ParseError" + }, + "description": "Any parsing errors" + } + } + }, + "ValidateRequest": { + "type": "object", + "properties": { + "formula": { + "type": "string", + "description": "The Power Fx formula to validate", + "x-ms-summary": "Formula" + }, + "context": { + "type": "object", + "description": "Context for type checking", + "additionalProperties": { + "type": "string" + } + } + }, + "required": [ + "formula" + ] + }, + "ValidateResponse": { + "type": "object", + "properties": { + "isValid": { + "type": "boolean", + "description": "Whether the formula is valid" + }, + "errors": { + "type": "array", + "items": { + "$ref": "#/definitions/ValidationError" + }, + "description": "Validation errors if any" + }, + "warnings": { + "type": "array", + "items": { + "$ref": "#/definitions/ValidationWarning" + }, + "description": "Validation warnings if any" + }, + "returnType": { + "type": "string", + "description": "The expected return type of the formula" + } + } + }, + "MathFunctionRequest": { + "type": "object", + "properties": { + "arguments": { + "type": "array", + "items": { + "type": "number" + }, + "description": "Numeric arguments for the math function", + "x-ms-summary": "Arguments" + } + }, + "required": [ + "arguments" + ] + }, + "TextFunctionRequest": { + "type": "object", + "properties": { + "arguments": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Text arguments for the text function", + "x-ms-summary": "Arguments" + }, + "numericArgs": { + "type": "array", + "items": { + "type": "number" + }, + "description": "Numeric arguments (for functions like Mid, Left, Right)", + "x-ms-summary": "Numeric Arguments" + } + }, + "required": [ + "arguments" + ] + }, + "LogicalFunctionRequest": { + "type": "object", + "properties": { + "arguments": { + "type": "array", + "items": { + "$ref": "#/definitions/PowerFxValue" + }, + "description": "Arguments for the logical function", + "x-ms-summary": "Arguments" + } + }, + "required": [ + "arguments" + ] + }, + "DateTimeFunctionRequest": { + "type": "object", + "properties": { + "arguments": { + "type": "array", + "items": { + "$ref": "#/definitions/PowerFxValue" + }, + "description": "Arguments for the date/time function", + "x-ms-summary": "Arguments" + } + }, + "required": [ + "arguments" + ] + }, + "ConversionFunctionRequest": { + "type": "object", + "properties": { + "value": { + "$ref": "#/definitions/PowerFxValue" + }, + "targetType": { + "type": "string", + "description": "Target type for conversion", + "x-ms-summary": "Target Type" + }, + "format": { + "type": "string", + "description": "Format specifier (currency, percentage, custom format string)", + "x-ms-summary": "Format" + }, + "locale": { + "type": "string", + "description": "Locale for cultural formatting (e.g., 'en-US', 'fr-FR')", + "x-ms-summary": "Locale" + } + }, + "required": [ + "value" + ] + }, + "FunctionResponse": { + "type": "object", + "properties": { + "result": { + "$ref": "#/definitions/PowerFxValue" + }, + "executionTimeMs": { + "type": "number", + "description": "Execution time in milliseconds" + } + } + }, + "TypeCheckRequest": { + "type": "object", + "properties": { + "value": { + "description": "The value to check the type of" + } + }, + "required": [ + "value" + ] + }, + "TypeCheckResponse": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The detected Power Fx type" + }, + "isValid": { + "type": "boolean", + "description": "Whether the value is valid for Power Fx" + }, + "details": { + "type": "object", + "description": "Additional type information" + } + } + }, + "TypeCoerceRequest": { + "type": "object", + "properties": { + "value": { + "description": "The value to coerce" + }, + "targetType": { + "type": "string", + "enum": [ + "Text", + "Number", + "Boolean", + "Date", + "DateTime", + "Time" + ], + "description": "The target type to coerce to" + } + }, + "required": [ + "value", + "targetType" + ] + }, + "TypeCoerceResponse": { + "type": "object", + "properties": { + "result": { + "$ref": "#/definitions/PowerFxValue" + }, + "success": { + "type": "boolean", + "description": "Whether coercion was successful" + } + } + }, + "EvaluationOptions": { + "type": "object", + "properties": { + "numberIsFloat": { + "type": "boolean", + "description": "Whether to treat numbers as floats instead of decimals" + }, + "allowSideEffects": { + "type": "boolean", + "description": "Whether to allow functions with side effects" + }, + "timeout": { + "type": "number", + "description": "Evaluation timeout in milliseconds" + } + } + }, + "ParseOptions": { + "type": "object", + "properties": { + "includeTokens": { + "type": "boolean", + "description": "Whether to include token information in the response" + }, + "includeSyntaxTree": { + "type": "boolean", + "description": "Whether to include the full syntax tree" + } + } + }, + "Token": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Token type" + }, + "value": { + "type": "string", + "description": "Token value" + }, + "start": { + "type": "number", + "description": "Start position in formula" + }, + "end": { + "type": "number", + "description": "End position in formula" + } + } + }, + "ParseError": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Error message" + }, + "start": { + "type": "number", + "description": "Error start position" + }, + "end": { + "type": "number", + "description": "Error end position" + }, + "severity": { + "type": "string", + "enum": [ + "Error", + "Warning", + "Info" + ], + "description": "Error severity" + } + } + }, + "ValidationError": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Error message" + }, + "start": { + "type": "number", + "description": "Error start position" + }, + "end": { + "type": "number", + "description": "Error end position" + }, + "code": { + "type": "string", + "description": "Error code" + } + } + }, + "ValidationWarning": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Warning message" + }, + "start": { + "type": "number", + "description": "Warning start position" + }, + "end": { + "type": "number", + "description": "Warning end position" + }, + "code": { + "type": "string", + "description": "Warning code" + } + } + }, + "ErrorResponse": { + "type": "object", + "properties": { + "error": { + "type": "string", + "description": "Error message" + }, + "code": { + "type": "string", + "description": "Error code" + }, + "details": { + "type": "object", + "description": "Additional error details" + } + }, + "required": [ + "error" + ] + }, + "TableFunctionRequest": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Table data as array of objects", + "x-ms-summary": "Table Data" + }, + "arguments": { + "type": "array", + "items": { + "$ref": "#/definitions/PowerFxValue" + }, + "description": "Additional arguments for the table function", + "x-ms-summary": "Arguments" + }, + "columns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Column names for table operations", + "x-ms-summary": "Columns" + } + } + }, + "UtilityFunctionRequest": { + "type": "object", + "properties": { + "arguments": { + "type": "array", + "items": { + "$ref": "#/definitions/PowerFxValue" + }, + "description": "Arguments for the utility function", + "x-ms-summary": "Arguments" + }, + "options": { + "type": "object", + "description": "Additional options for the utility function", + "x-ms-summary": "Options" + }, + "table": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Table data for ForAll operations", + "x-ms-summary": "Table" + }, + "record": { + "type": "object", + "description": "Record data for With operations", + "x-ms-summary": "Record" + }, + "expression": { + "type": "string", + "description": "Expression to evaluate for ForAll/With operations", + "x-ms-summary": "Expression" + } + }, + "required": [ + "arguments" + ] + }, + "DatePartRequest": { + "type": "object", + "properties": { + "dateValue": { + "$ref": "#/definitions/PowerFxValue" + } + }, + "required": [ + "dateValue" + ] + }, + "TextTransformRequest": { + "type": "object", + "properties": { + "text": { + "$ref": "#/definitions/PowerFxValue" + }, + "options": { + "type": "object", + "description": "Additional transformation options", + "x-ms-summary": "Options" + } + }, + "required": [ + "text" + ] + }, + "RoundingRequest": { + "type": "object", + "properties": { + "number": { + "$ref": "#/definitions/PowerFxValue" + }, + "decimals": { + "$ref": "#/definitions/PowerFxValue" + } + }, + "required": [ + "number" + ] + }, + "TrigFunctionRequest": { + "type": "object", + "properties": { + "angle": { + "$ref": "#/definitions/PowerFxValue" + }, + "secondAngle": { + "$ref": "#/definitions/PowerFxValue" + }, + "angleUnit": { + "type": "string", + "enum": [ + "radians", + "degrees" + ], + "description": "Unit of the angle (default: radians)", + "x-ms-summary": "Angle Unit" + } + }, + "required": [ + "angle" + ] + }, + "TextSearchRequest": { + "type": "object", + "properties": { + "text": { + "$ref": "#/definitions/PowerFxValue" + }, + "searchFor": { + "$ref": "#/definitions/PowerFxValue" + }, + "startPosition": { + "$ref": "#/definitions/PowerFxValue" + }, + "caseSensitive": { + "type": "boolean", + "description": "Whether search is case sensitive", + "x-ms-summary": "Case Sensitive" + } + }, + "required": [ + "text", + "searchFor" + ] + }, + "LogicalConditionRequest": { + "type": "object", + "properties": { + "values": { + "type": "array", + "items": { + "$ref": "#/definitions/PowerFxValue" + }, + "description": "Values to evaluate in the logical condition", + "x-ms-summary": "Values" + } + }, + "required": [ + "values" + ] + }, + "TypeCheckSpecificRequest": { + "type": "object", + "properties": { + "value": { + "$ref": "#/definitions/PowerFxValue" + } + }, + "required": [ + "value" + ] + }, + "JSONFunctionRequest": { + "type": "object", + "properties": { + "jsonData": { + "$ref": "#/definitions/PowerFxValue" + }, + "jsonPath": { + "$ref": "#/definitions/PowerFxValue" + }, + "arguments": { + "type": "array", + "items": { + "$ref": "#/definitions/PowerFxValue" + }, + "description": "Additional arguments for the JSON function", + "x-ms-summary": "Arguments" + }, + "options": { + "type": "object", + "description": "JSON processing options", + "x-ms-summary": "Options" + } + }, + "required": [ + "jsonData" + ] + }, + "AdvancedTableFunctionRequest": { + "type": "object", + "properties": { + "leftTable": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Left table data for join operations", + "x-ms-summary": "Left Table" + }, + "rightTable": { + "type": "array", + "items": { + "type": "object" + }, + "description": "Right table data for join operations", + "x-ms-summary": "Right Table" + }, + "joinColumns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Columns to join on", + "x-ms-summary": "Join Columns" + }, + "pivotColumns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Columns for pivot operations", + "x-ms-summary": "Pivot Columns" + }, + "valueColumns": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Value columns for aggregation", + "x-ms-summary": "Value Columns" + }, + "lookupKey": { + "$ref": "#/definitions/PowerFxValue" + }, + "lookupColumn": { + "type": "string", + "description": "Column to lookup in", + "x-ms-summary": "Lookup Column" + }, + "returnColumn": { + "type": "string", + "description": "Column to return from lookup", + "x-ms-summary": "Return Column" + } + } + }, + "ColorFunctionRequest": { + "type": "object", + "properties": { + "color": { + "$ref": "#/definitions/PowerFxValue" + }, + "red": { + "$ref": "#/definitions/PowerFxValue" + }, + "green": { + "$ref": "#/definitions/PowerFxValue" + }, + "blue": { + "$ref": "#/definitions/PowerFxValue" + }, + "alpha": { + "$ref": "#/definitions/PowerFxValue" + }, + "hue": { + "$ref": "#/definitions/PowerFxValue" + }, + "saturation": { + "$ref": "#/definitions/PowerFxValue" + }, + "lightness": { + "$ref": "#/definitions/PowerFxValue" + }, + "amount": { + "$ref": "#/definitions/PowerFxValue" + }, + "color2": { + "$ref": "#/definitions/PowerFxValue" + } + } + }, + "EncodingFunctionRequest": { + "type": "object", + "properties": { + "data": { + "$ref": "#/definitions/PowerFxValue" + }, + "encoding": { + "type": "string", + "enum": [ + "utf8", + "ascii", + "unicode" + ], + "description": "Text encoding format", + "x-ms-summary": "Encoding" + }, + "algorithm": { + "type": "string", + "enum": [ + "md5", + "sha1", + "sha256", + "sha512" + ], + "description": "Hash algorithm for hash functions", + "x-ms-summary": "Algorithm" + }, + "options": { + "type": "object", + "description": "Encoding options", + "x-ms-summary": "Options" + } + }, + "required": [ + "data" + ] + }, + "StatisticsFunctionRequest": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "type": "number" + }, + "description": "Numeric data for statistical analysis", + "x-ms-summary": "Data" + }, + "xValues": { + "type": "array", + "items": { + "type": "number" + }, + "description": "X values for correlation and regression", + "x-ms-summary": "X Values" + }, + "yValues": { + "type": "array", + "items": { + "type": "number" + }, + "description": "Y values for correlation and regression", + "x-ms-summary": "Y Values" + }, + "percentile": { + "type": "number", + "description": "Percentile value (0-1)", + "x-ms-summary": "Percentile" + }, + "confidence": { + "type": "number", + "description": "Confidence level (0-1)", + "x-ms-summary": "Confidence Level" + }, + "sortOrder": { + "type": "string", + "enum": [ + "ascending", + "descending" + ], + "description": "Sort order for ranking", + "x-ms-summary": "Sort Order" + } + }, + "required": [ + "data" + ] + } + } +} \ No newline at end of file diff --git a/independent-publisher-connectors/Power Fx Functions/apiProperties.json b/independent-publisher-connectors/Power Fx Functions/apiProperties.json new file mode 100644 index 0000000000..d72b14b372 --- /dev/null +++ b/independent-publisher-connectors/Power Fx Functions/apiProperties.json @@ -0,0 +1,11 @@ +{ + "displayName": "Power Fx Functions", + "description": "A comprehensive Power Fx function library providing 270+ mathematical, text, logical, date and time, table manipulation, conversion, and utility functions for Power Platform applications with custom C# script execution.", + "iconBrandColor": "#da3b01", + "capabilities": [ + "actions" + ], + "policyTemplateInstances": [], + "publisher": "Troy Taylor", + "stackOwner": "Troy Taylor" +} \ No newline at end of file diff --git a/independent-publisher-connectors/Power Fx Functions/readme.md b/independent-publisher-connectors/Power Fx Functions/readme.md new file mode 100644 index 0000000000..dbc0a3a6f6 --- /dev/null +++ b/independent-publisher-connectors/Power Fx Functions/readme.md @@ -0,0 +1,87 @@ +# Power Fx Functions +A comprehensive Power Fx function library providing 270+ mathematical, text, logical, date and time, table manipulation, conversion, and utility functions using custom C# script execution. + +## Publisher: Troy Taylor + +## Prerequisites +You will need to use this connector in Power Platform environments that support custom connectors with code components. + +## Obtaining Credentials +This connector uses the hosting environment's authentication. No additional credentials are required. + +## Supported Operations + +### Evaluate Power Fx Formula +Evaluates a Power Fx formula and returns the result with type information. + +### Parse Power Fx Formula +Parses a Power Fx formula and returns syntax tree information. + +### Validate Power Fx Formula +Validates a Power Fx formula and returns any syntax or semantic errors. + +### Execute Math Function +Executes mathematical functions including: abs, power, sqrt, mod, round, sin, cos, tan, ln, log, exp, pi, int, roundup, rounddown, trunc, asin, acos, atan, atan2, acot, cot, radians, degrees, rand, randbetween, average, max, min, sum, count, counta, gcd, lcm, ceiling, floor, pmt, pv, fv, nper, rate. + +### Execute Text Function +Executes text manipulation functions including: left, right, mid, len, upper, lower, trim, find, replace, concatenate, split, trimends, proper, search, substitute, startswith, endswith, char, unichar, encodeurl, encodehtml, plaintext, concat, ismatch, match, matchall, rept, fixed, dollar. + +### Execute Logical Function +Executes logical functions including: and, or, not, if, isblank, isempty, isnumeric, iserror, switch, iferror, error, isblankorerror, istoday, isutctoday. + +### Execute Date Time Function +Executes date/time functions including: now, today, year, month, day, hour, minute, second, dateadd, datediff, utcnow, utctoday, date, datetime, time, datevalue, datetimevalue, timevalue, weekday, edate, eomonth, weeknum, isoweeknum. + +### Execute Conversion Function +Executes type conversion functions including: text, value, boolean, decimal, float, guid, astype. + +### Execute Table Function +Executes table manipulation functions including: addcolumns, filter, sort, groupby, summarize, distinct, firstn, lastn, table, sequence, countrows, countif, first, last, index, shuffle. + +### Execute Utility Function +Executes utility functions including: rand, randbetween, sequence, shuffle, sort, reverse, coalesce, collect, clear, remove, removeif, update, updateif, patch, parsejson, dec2hex, hex2dec, blank, rgba, colorvalue, colorfade, forall, with. + +### Execute Advanced Table Function +Executes advanced table operations including: join, leftjoin, rightjoin, innerjoin, outerjoin, crossjoin, pivot, unpivot, transpose, lookup, xlookup, relate, unrelate, merge, append, union, intersect, except, dropcolumns, renamecolumns, showcolumns. + +### Execute JSON Function +Executes JSON parsing and manipulation functions including: parsejson, json, formatjson, jsonextract, jsonpath, isvalidjson, jsonmerge, jsonarray, jsonobject, jsonkeys, jsonvalues. + +### Execute Color Function +Executes color manipulation functions including: rgba, rgb, hsl, hsv, colorvalue, colorfade, colorbrightness, colorcontrast, colormix, colorinvert, hex2color, color2hex, colorred, colorgreen, colorblue, coloralpha. + +### Execute Encoding Function +Executes data encoding and decoding functions including: base64encode, base64decode, urlencode, urldecode, htmlencode, htmldecode, xmlencode, xmldecode, utf8encode, utf8decode, hash, md5, sha1, sha256. + +### Execute Statistics Function +Executes statistical analysis functions including: stdev, stdevp, var, varp, median, mode, percentile, quartile, correlation, covariance, regression, slope, intercept, rsquared, frequency, rank, percentrank, zscore, confidence. + +### Check Value Type +Determines the Power Fx type of a given value. + +### Coerce Value Type +Attempts to coerce a value to a specific Power Fx type. + +### Extract Date Part +Extracts specific parts (year, month, day, hour, minute, second, weekday, dayofyear, quarter, weeknum, isoweeknum) from date/time values. + +### Transform Text +Applies text transformations including: upper, lower, proper, trim, trimends, trimstart, trimend, reverse. + +### Round Number +Rounds numbers using various methods: round, roundup, rounddown, trunc, int, ceiling, floor. + +### Trigonometric Function +Executes trigonometric functions including: sin, cos, tan, asin, acos, atan, atan2, cot, acot, sec, csc, sinh, cosh, tanh. + +### Search Text +Searches for text using methods: find, search, startswith, endswith, contains, exact. + +### Evaluate Logical Condition +Evaluates logical conditions using: and, or, not, xor, nand, nor. + +### Check Value Property +Checks specific properties of values: isblank, isempty, isnumeric, istext, islogical, iserror, isdate, istime, isblankorerror, istoday, isutctoday. + +## Known Issues and Limitations +Some advanced Power Fx features may not be fully implemented in this version. \ No newline at end of file diff --git a/independent-publisher-connectors/Power Fx Functions/script.csx b/independent-publisher-connectors/Power Fx Functions/script.csx new file mode 100644 index 0000000000..841fb2fee7 --- /dev/null +++ b/independent-publisher-connectors/Power Fx Functions/script.csx @@ -0,0 +1,651 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text; +using System.Threading.Tasks; +using Microsoft.PowerPlatform.Connectors; +using Newtonsoft.Json; +using Newtonsoft.Json.Linq; + +public class Script : ScriptBase +{ + public override async Task ExecuteAsync() + { + var pathInfo = ExtractPathInfo(); + + try + { + // Handle main operations + if (pathInfo.Operation.Equals("evaluate", StringComparison.OrdinalIgnoreCase)) + { + return await EvaluateFormula().ConfigureAwait(false); + } + else if (pathInfo.Operation.Equals("parse", StringComparison.OrdinalIgnoreCase)) + { + return await ParseFormula().ConfigureAwait(false); + } + else if (pathInfo.Operation.Equals("validate", StringComparison.OrdinalIgnoreCase)) + { + return await ValidateFormula().ConfigureAwait(false); + } + // Handle function categories + else if (pathInfo.Category == "functions") + { + return await ExecuteFunction(pathInfo).ConfigureAwait(false); + } + // Handle type operations + else if (pathInfo.Category == "types") + { + return await ExecuteTypeOperation(pathInfo).ConfigureAwait(false); + } + else + { + return CreateErrorResponse($"Unknown operation: {pathInfo.Operation}", HttpStatusCode.NotFound); + } + } + catch (Exception ex) + { + this.Context.Logger?.LogError(ex, $"Error executing operation: {pathInfo.Operation}"); + return CreateErrorResponse("Internal server error", HttpStatusCode.InternalServerError); + } + } + + private async Task EvaluateFormula() + { + try + { + var requestBody = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var requestData = JObject.Parse(requestBody); + var formula = requestData["formula"]?.ToString(); + + if (string.IsNullOrEmpty(formula)) + return CreateErrorResponse("Formula is required", HttpStatusCode.BadRequest); + + var result = EvaluateSimpleFormula(formula); + + var response = new JObject(); + response["result"] = JToken.FromObject(new { value = result, type = "Text", isError = false }); + response["formula"] = JToken.FromObject(formula); + response["success"] = JToken.FromObject(true); + + return CreateSuccessResponse(response); + } + catch (Exception ex) + { + this.Context.Logger?.LogError(ex, "Error evaluating formula"); + return CreateErrorResponse("Evaluation error", HttpStatusCode.InternalServerError); + } + } + + private string EvaluateSimpleFormula(string formula) + { + if (formula.Contains("+")) + { + var parts = formula.Split('+'); + if (parts.Length == 2 && double.TryParse(parts[0].Trim(), out double num1) && double.TryParse(parts[1].Trim(), out double num2)) + { + return (num1 + num2).ToString(); + } + } + return $"Evaluated: {formula}"; + } + + private async Task ParseFormula() + { + try + { + var requestBody = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var requestData = JObject.Parse(requestBody); + var formula = requestData["formula"]?.ToString(); + + if (string.IsNullOrEmpty(formula)) + return CreateErrorResponse("Formula is required", HttpStatusCode.BadRequest); + + var tokens = TokenizeFormula(formula); + var response = new JObject(); + response["isValid"] = JToken.FromObject(true); + response["tokens"] = JArray.FromObject(tokens); + response["success"] = JToken.FromObject(true); + + return CreateSuccessResponse(response); + } + catch (Exception ex) + { + this.Context.Logger?.LogError(ex, "Error parsing formula"); + return CreateErrorResponse("Parse error", HttpStatusCode.InternalServerError); + } + } + + private async Task ValidateFormula() + { + try + { + var requestBody = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var requestData = JObject.Parse(requestBody); + var formula = requestData["formula"]?.ToString(); + + if (string.IsNullOrEmpty(formula)) + return CreateErrorResponse("Formula is required", HttpStatusCode.BadRequest); + + var isValid = !string.IsNullOrWhiteSpace(formula) && formula.Length > 0; + + var response = new JObject(); + response["isValid"] = JToken.FromObject(isValid); + response["formula"] = JToken.FromObject(formula); + response["success"] = JToken.FromObject(true); + + return CreateSuccessResponse(response); + } + catch (Exception ex) + { + this.Context.Logger?.LogError(ex, "Error validating formula"); + return CreateErrorResponse("Validation error", HttpStatusCode.InternalServerError); + } + } + + private async Task ExecuteFunction(PathInfo pathInfo) + { + try + { + var requestBody = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var requestData = JObject.Parse(requestBody); + + FunctionResult result; + switch (pathInfo.FunctionType.ToLower()) + { + case "math": + result = ExecuteMathFunction(pathInfo.Operation, requestData); + break; + case "text": + result = ExecuteTextFunction(pathInfo.Operation, requestData); + break; + case "logical": + result = ExecuteLogicalFunction(pathInfo.Operation, requestData); + break; + case "datetime": + result = ExecuteDateTimeFunction(pathInfo.Operation, requestData); + break; + case "conversion": + result = ExecuteConversionFunction(pathInfo.Operation, requestData); + break; + case "table": + result = ExecuteTableFunction(pathInfo.Operation, requestData); + break; + case "utility": + result = ExecuteUtilityFunction(pathInfo.Operation, requestData); + break; + case "json": + result = ExecuteJSONFunction(pathInfo.Operation, requestData); + break; + case "color": + result = ExecuteColorFunction(pathInfo.Operation, requestData); + break; + case "encoding": + result = ExecuteEncodingFunction(pathInfo.Operation, requestData); + break; + case "statistics": + result = ExecuteStatisticsFunction(pathInfo.Operation, requestData); + break; + default: + result = CreateFunctionResult("Function not implemented", false); + break; + } + + // Create PowerFxValue structure as expected by OpenAPI schema + var powerFxValue = new JObject(); + powerFxValue["value"] = JToken.FromObject(result.Value); + powerFxValue["type"] = JToken.FromObject(result.Type); + powerFxValue["isError"] = JToken.FromObject(!result.Success); + if (!result.Success) + { + powerFxValue["errorMessage"] = JToken.FromObject(result.Value.ToString()); + } + + var response = new JObject(); + response["result"] = powerFxValue; + response["executionTimeMs"] = JToken.FromObject(0); // Add execution time if needed + + return CreateSuccessResponse(response); + } + catch (Exception ex) + { + this.Context.Logger?.LogError(ex, $"Error executing function: {pathInfo.FunctionType}/{pathInfo.Operation}"); + return CreateErrorResponse($"Function execution error: {ex.Message}", HttpStatusCode.InternalServerError); + } + } + + private async Task ExecuteTypeOperation(PathInfo pathInfo) + { + try + { + var requestBody = await this.Context.Request.Content.ReadAsStringAsync().ConfigureAwait(false); + var requestData = JObject.Parse(requestBody); + + FunctionResult result; + switch (pathInfo.Operation.ToLower()) + { + case "check": + result = ExecuteTypeCheck(requestData); + break; + case "coerce": + result = ExecuteTypeCoerce(requestData); + break; + default: + result = CreateFunctionResult("Type operation not implemented", false); + break; + } + + // Create PowerFxValue structure as expected by OpenAPI schema + var powerFxValue = new JObject(); + powerFxValue["value"] = JToken.FromObject(result.Value); + powerFxValue["type"] = JToken.FromObject(result.Type); + powerFxValue["isError"] = JToken.FromObject(!result.Success); + if (!result.Success) + { + powerFxValue["errorMessage"] = JToken.FromObject(result.Value.ToString()); + } + + var response = new JObject(); + response["result"] = powerFxValue; + response["executionTimeMs"] = JToken.FromObject(0); + + return CreateSuccessResponse(response); + } + catch (Exception ex) + { + this.Context.Logger?.LogError(ex, $"Error executing type operation: {pathInfo.Operation}"); + return CreateErrorResponse($"Type operation error: {ex.Message}", HttpStatusCode.InternalServerError); + } + } + + private FunctionResult ExecuteMathFunction(string operation, JObject requestData) + { + try + { + var args = requestData["arguments"]?.ToObject() ?? new double[0]; + + double result = 0; + switch (operation.ToLower()) + { + case "abs": + result = args.Length >= 1 ? Math.Abs(args[0]) : 0; + break; + case "power": + result = args.Length >= 2 ? Math.Pow(args[0], args[1]) : 0; + break; + case "sqrt": + result = args.Length >= 1 ? Math.Sqrt(args[0]) : 0; + break; + case "mod": + result = args.Length >= 2 ? args[0] % args[1] : 0; + break; + case "round": + result = args.Length >= 1 ? Math.Round(args[0]) : 0; + break; + case "sin": + result = args.Length >= 1 ? Math.Sin(args[0]) : 0; + break; + case "cos": + result = args.Length >= 1 ? Math.Cos(args[0]) : 0; + break; + case "tan": + result = args.Length >= 1 ? Math.Tan(args[0]) : 0; + break; + case "ln": + result = args.Length >= 1 ? Math.Log(args[0]) : 0; + break; + case "log": + result = args.Length >= 1 ? Math.Log10(args[0]) : 0; + break; + case "exp": + result = args.Length >= 1 ? Math.Exp(args[0]) : 0; + break; + case "pi": + result = Math.PI; + break; + case "int": + result = args.Length >= 1 ? Math.Truncate(args[0]) : 0; + break; + case "roundup": + result = args.Length >= 1 ? Math.Ceiling(args[0]) : 0; + break; + case "rounddown": + result = args.Length >= 1 ? Math.Floor(args[0]) : 0; + break; + case "trunc": + result = args.Length >= 1 ? Math.Truncate(args[0]) : 0; + break; + case "asin": + result = args.Length >= 1 ? Math.Asin(args[0]) : 0; + break; + case "acos": + result = args.Length >= 1 ? Math.Acos(args[0]) : 0; + break; + case "atan": + result = args.Length >= 1 ? Math.Atan(args[0]) : 0; + break; + case "atan2": + result = args.Length >= 2 ? Math.Atan2(args[0], args[1]) : 0; + break; + case "ceiling": + result = args.Length >= 1 ? Math.Ceiling(args[0]) : 0; + break; + case "floor": + result = args.Length >= 1 ? Math.Floor(args[0]) : 0; + break; + case "max": + result = args.Length >= 1 ? args.Max() : 0; + break; + case "min": + result = args.Length >= 1 ? args.Min() : 0; + break; + case "sum": + result = args.Sum(); + break; + case "average": + result = args.Length > 0 ? args.Average() : 0; + break; + default: + throw new NotSupportedException($"Math operation '{operation}' is not supported"); + } + + return CreateFunctionResult(result, true); + } + catch (Exception ex) + { + return CreateFunctionResult($"Math error: {ex.Message}", false); + } + } + + private FunctionResult ExecuteTextFunction(string operation, JObject requestData) + { + try + { + var args = requestData["arguments"]?.ToObject() ?? new string[0]; + + object result = ""; + switch (operation.ToLower()) + { + case "upper": + result = args.Length >= 1 ? args[0]?.ToUpper() ?? "" : ""; + break; + case "lower": + result = args.Length >= 1 ? args[0]?.ToLower() ?? "" : ""; + break; + case "len": + result = args.Length >= 1 ? args[0]?.Length ?? 0 : 0; + break; + case "trim": + result = args.Length >= 1 ? args[0]?.Trim() ?? "" : ""; + break; + case "left": + if (args.Length >= 2 && int.TryParse(args[1], out int leftCount) && args[0] != null) + result = args[0].Length >= leftCount ? args[0].Substring(0, leftCount) : args[0]; + else + result = ""; + break; + case "right": + if (args.Length >= 2 && int.TryParse(args[1], out int rightCount) && args[0] != null) + result = args[0].Length >= rightCount ? args[0].Substring(args[0].Length - rightCount) : args[0]; + else + result = ""; + break; + case "concatenate": + result = string.Join("", args); + break; + default: + result = $"Text operation '{operation}' not implemented"; + break; + } + + return CreateFunctionResult(result, true); + } + catch (Exception ex) + { + return CreateFunctionResult($"Text error: {ex.Message}", false); + } + } + + private FunctionResult ExecuteLogicalFunction(string operation, JObject requestData) + { + try + { + var args = requestData["arguments"]?.ToObject() ?? new bool[0]; + + bool result = false; + switch (operation.ToLower()) + { + case "and": + result = args.Length > 0 ? args.All(x => x) : true; + break; + case "or": + result = args.Length > 0 ? args.Any(x => x) : false; + break; + case "not": + result = args.Length >= 1 ? !args[0] : true; + break; + default: + throw new NotSupportedException($"Logical operation '{operation}' is not supported"); + } + + return CreateFunctionResult(result, true); + } + catch (Exception ex) + { + return CreateFunctionResult($"Logical error: {ex.Message}", false); + } + } + + private FunctionResult ExecuteDateTimeFunction(string operation, JObject requestData) + { + try + { + object result = null; + switch (operation.ToLower()) + { + case "now": + result = DateTime.Now; + break; + case "today": + result = DateTime.Today; + break; + case "utcnow": + result = DateTime.UtcNow; + break; + case "utctoday": + result = DateTime.UtcNow.Date; + break; + default: + result = $"DateTime operation '{operation}' not implemented"; + break; + } + + return CreateFunctionResult(result, true); + } + catch (Exception ex) + { + return CreateFunctionResult($"DateTime error: {ex.Message}", false); + } + } + + private FunctionResult ExecuteConversionFunction(string operation, JObject requestData) + { + return CreateFunctionResult($"Conversion operation '{operation}' not implemented", false); + } + + private FunctionResult ExecuteTableFunction(string operation, JObject requestData) + { + return CreateFunctionResult($"Table operation '{operation}' not implemented", false); + } + + private FunctionResult ExecuteUtilityFunction(string operation, JObject requestData) + { + return CreateFunctionResult($"Utility operation '{operation}' not implemented", false); + } + + private FunctionResult ExecuteJSONFunction(string operation, JObject requestData) + { + return CreateFunctionResult($"JSON operation '{operation}' not implemented", false); + } + + private FunctionResult ExecuteColorFunction(string operation, JObject requestData) + { + return CreateFunctionResult($"Color operation '{operation}' not implemented", false); + } + + private FunctionResult ExecuteEncodingFunction(string operation, JObject requestData) + { + return CreateFunctionResult($"Encoding operation '{operation}' not implemented", false); + } + + private FunctionResult ExecuteStatisticsFunction(string operation, JObject requestData) + { + return CreateFunctionResult($"Statistics operation '{operation}' not implemented", false); + } + + private FunctionResult ExecuteTypeCheck(JObject requestData) + { + return CreateFunctionResult("Type check not implemented", false); + } + + private FunctionResult ExecuteTypeCoerce(JObject requestData) + { + return CreateFunctionResult("Type coerce not implemented", false); + } + + private FunctionResult CreateFunctionResult(object value, bool success) + { + return new FunctionResult + { + Value = value, + Success = success, + Type = GetPowerFxType(value) + }; + } + + private string GetPowerFxType(object value) + { + if (value == null) + return "Blank"; + + if (value is bool) + return "Boolean"; + + if (value is int || value is long || value is float || value is double || value is decimal) + return "Number"; + + if (value is string) + return "Text"; + + if (value is DateTime) + return "DateTime"; + + return "Text"; + } + + private List> TokenizeFormula(string formula) + { + var tokens = new List>(); + tokens.Add(new Dictionary + { + ["type"] = "Formula", + ["value"] = formula, + ["start"] = 0, + ["end"] = formula.Length + }); + return tokens; + } + + private PathInfo ExtractPathInfo() + { + var segments = this.Context.Request.RequestUri.Segments + .Where(s => !string.IsNullOrWhiteSpace(s) && s != "/") + .Select(s => s.TrimEnd('/')) + .ToArray(); + + if (segments.Length == 0) + return new PathInfo { Operation = "unknown", Category = "", FunctionType = "" }; + + // Handle simple operations like /evaluate, /parse, /validate + if (segments.Length == 1) + { + return new PathInfo + { + Operation = segments[0], + Category = "", + FunctionType = "" + }; + } + + // Handle /functions/math/power, /functions/text/upper, etc. + if (segments.Length >= 3 && segments[0] == "functions") + { + return new PathInfo + { + Operation = segments[2], + Category = segments[0], + FunctionType = segments[1] + }; + } + + // Handle /types/check, /types/coerce + if (segments.Length >= 2 && segments[0] == "types") + { + return new PathInfo + { + Operation = segments[1], + Category = segments[0], + FunctionType = "" + }; + } + + // Default case + return new PathInfo + { + Operation = segments.LastOrDefault() ?? "unknown", + Category = segments.Length > 1 ? segments[0] : "", + FunctionType = segments.Length > 2 ? segments[1] : "" + }; + } + + private class PathInfo + { + public string Operation { get; set; } = ""; + public string Category { get; set; } = ""; + public string FunctionType { get; set; } = ""; + } + + private class FunctionResult + { + public object Value { get; set; } + public bool Success { get; set; } + public string Type { get; set; } = ""; + } + + private HttpResponseMessage CreateSuccessResponse(JObject responseData) + { + var response = new HttpResponseMessage(HttpStatusCode.OK); + response.Content = CreateJsonContent(responseData.ToString()); + return response; + } + + private HttpResponseMessage CreateErrorResponse(string errorMessage, HttpStatusCode statusCode = HttpStatusCode.BadRequest) + { + var errorResponse = new JObject(); + var errorObj = new JObject(); + errorObj["code"] = JToken.FromObject(statusCode.ToString()); + errorObj["message"] = JToken.FromObject(errorMessage); + errorResponse["error"] = errorObj; + + var response = new HttpResponseMessage(statusCode); + response.Content = CreateJsonContent(errorResponse.ToString()); + return response; + } + + private StringContent CreateJsonContent(string json) + { + return new StringContent(json, Encoding.UTF8, "application/json"); + } +}