@octaviaflow/flow-rules 0.18.0 → 0.19.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,24 +1,47 @@
1
1
  /**
2
- * Build Query Configuration
2
+ * Query step configuration — defaults, validation and the contract (DEV-533).
3
3
  *
4
- * Configuration utilities and validation for the Build Query action
5
- * Supports dual modes: Visual Builder (no-code) and SQL Editor (advanced)
4
+ * The Query step is built with the visual builder only. `visualConfig` is what
5
+ * a person or an agent writes; `sqlConfig.sql` is compiled from it by the
6
+ * editor or the server and is never written by hand.
7
+ *
8
+ * Contract: Octaviaflow-Docs/Engine/query/visual-query-v2-dev-533.md.
6
9
  */
7
- import { BuildQueryConfig, QueryMode, QueryType, QueryValidationResult, VisualQueryConfig, SQLQueryConfig } from './types';
10
+ import { type BuildQueryConfig, type VisualConfigV2, type QueryValidationError, type QueryValidationResult, QueryMode, QueryType } from './types';
8
11
  export declare const BuildQueryConfigDefaults: {
9
12
  mode: QueryMode;
10
13
  queryType: QueryType;
11
14
  timeout: number;
12
15
  maxRows: number;
13
- visualConfig: VisualQueryConfig;
14
- sqlConfig: SQLQueryConfig;
16
+ visualConfig: VisualConfigV2;
15
17
  };
18
+ /** Shown when `mode` is anything but `'visual'` (legacy `'sql'` included). */
19
+ export declare const QUERY_VISUAL_ONLY_MESSAGE: string;
20
+ /** Shown when `sqlConfig.sql` is present without a `visualConfig` to compile it from. */
21
+ export declare const QUERY_AUTHORED_SQL_MESSAGE: string;
22
+ type Issue = QueryValidationError;
23
+ /**
24
+ * True when the step names what to read without a plain field list: every
25
+ * table and column (`selectAll`), an aggregate-only or GROUP BY query, or a
26
+ * query the editor already compiled (Google Sheets reads every column, so it
27
+ * saves a runnable query with no field selection). Shared by `validate` and
28
+ * the node status badge so the two cannot disagree.
29
+ */
30
+ export declare function queryFieldsSatisfied(config: Record<string, unknown> | undefined): boolean;
31
+ /** True when `selectAll` stands in for the table list. */
32
+ export declare function queryTablesSatisfied(config: Record<string, unknown> | undefined): boolean;
33
+ /**
34
+ * Validate the visual builder's config — the full v2 shape.
35
+ * `config` is the whole step config, so the compiled query can be consulted.
36
+ */
37
+ export declare function validateVisualConfig(config: Record<string, unknown>): Issue[];
16
38
  /**
17
- * Validate Build Query configuration
39
+ * Validate a Query step's config. Errors mean the step cannot run as written.
18
40
  */
19
- export declare const validateBuildQueryConfig: (config: Partial<BuildQueryConfig>) => QueryValidationResult;
41
+ export declare const validateBuildQueryConfig: (config: Partial<BuildQueryConfig> | Record<string, unknown>) => QueryValidationResult;
20
42
  /**
21
- * Merge user config with defaults
43
+ * Merge user config with defaults. Always a visual-builder config; a compiled
44
+ * `sqlConfig` already on the step is carried through untouched.
22
45
  */
23
46
  export declare const mergeBuildQueryConfig: (userConfig: Partial<BuildQueryConfig>) => BuildQueryConfig;
24
47
  /**
@@ -36,9 +59,9 @@ export declare function isQueryableConnector(connector: {
36
59
  }): boolean;
37
60
  /**
38
61
  * The contract for `configContracts.ts`. Mirrors `BuildQueryConfig` in
39
- * ./types — the two keys an agent most needs, `visualConfig` and `sqlConfig`,
40
- * were absent from `inputSchema` entirely, so `describe_action_type` never
41
- * mentioned them and the fence called them undeclared.
62
+ * ./types. `mode` and `queryType` list exactly what may be authored
63
+ * (`QUERY_MODES`, `QUERY_TYPES`); the legacy enum members stay in ./types for
64
+ * reading old steps only.
42
65
  */
43
66
  export declare const BuildQueryContractSchema: {
44
67
  readonly connectorId: {
@@ -48,22 +71,25 @@ export declare const BuildQueryContractSchema: {
48
71
  readonly mode: {
49
72
  readonly type: "select";
50
73
  readonly required: true;
51
- readonly options: readonly ["visual", "sql"];
52
- readonly description: "visual: the query is built from visualConfig; sql: the query is the text in sqlConfig.sql";
74
+ readonly options: readonly [QueryMode.Visual];
75
+ readonly description: "Always 'visual': the Query step is built with the visual builder and described in visualConfig. Hand-written SQL is not accepted.";
53
76
  };
54
77
  readonly queryType: {
55
78
  readonly type: "select";
56
79
  readonly required: true;
57
- readonly options: readonly ["select", "insert", "update", "delete", "custom"];
58
- readonly description: "Only select is a read; the write types exist for the SQL mode of database connectors";
80
+ readonly options: readonly [QueryType.Select];
81
+ readonly description: "Always 'select': the Query step reads data. Use a Transform step to write.";
59
82
  };
60
83
  readonly visualConfig: {
61
84
  readonly type: "object";
62
85
  readonly required: false;
86
+ readonly description: string;
63
87
  };
64
88
  readonly sqlConfig: {
65
89
  readonly type: "object";
66
90
  readonly required: false;
91
+ readonly derived: true;
92
+ readonly description: "Compiled from visualConfig by the editor or the server. Never write it — describe the query in visualConfig.";
67
93
  };
68
94
  readonly timeout: {
69
95
  readonly type: "number";
@@ -74,3 +100,4 @@ export declare const BuildQueryContractSchema: {
74
100
  readonly required: false;
75
101
  };
76
102
  };
103
+ export {};
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Build Query Action
2
+ * Query Action
3
3
  *
4
- * Execute queries against connected databases, APIs, CRMs with dual mode support:
5
- * - Visual Builder: No-code/low-code query construction
6
- * - SQL Editor: Advanced SQL query writing with syntax highlighting
4
+ * Reads data from a connected database, app or CRM. The query is built with
5
+ * the visual builder only (DEV-533): `visualConfig` is what is authored, and
6
+ * `sqlConfig.sql` is compiled from it — see ./types and ./config.
7
7
  */
8
8
  import { ActionDefinition } from '../../types';
9
9
  export declare const queryDefinition: ActionDefinition;
@@ -1,107 +1,195 @@
1
1
  /**
2
- * Build Query Action Types
2
+ * Query step types — the shape the editor actually saves (DEV-533).
3
3
  *
4
- * Type definitions for the Build Query action supporting both visual builder and SQL editor modes
4
+ * The Query step is built with the visual builder only. `visualConfig` is the
5
+ * one authoring format; `sqlConfig.sql` is the compiled output the editor (or
6
+ * the server's compiler) writes from it, and is never written by hand.
7
+ *
8
+ * Contract: Octaviaflow-Docs/Engine/query/visual-query-v2-dev-533.md.
9
+ *
10
+ * Until 0.19.0 this file described a builder that was never shipped (filter
11
+ * groups keyed `filters`, `QueryField` objects, lowercase join types). Nothing
12
+ * outside the retired `components/BuildQuery/*` in octaviaflow-ui read those
13
+ * shapes; the editor saved the one below all along.
14
+ */
15
+ /**
16
+ * `SQL` is LEGACY. It is kept so code reading an old saved step can name it;
17
+ * the contract refuses it (`QUERY_MODES` is `['visual']`), and the Backend's
18
+ * migration converts the remaining SQL steps to the visual builder.
5
19
  */
6
20
  export declare enum QueryMode {
7
21
  Visual = "visual",
22
+ /** @deprecated Legacy hand-written SQL. Refused by the contract since 0.19.0. */
8
23
  SQL = "sql"
9
24
  }
25
+ /**
26
+ * Only `Select` is authorable — the Query step reads; writes go through
27
+ * Transform. The other members are kept for reading legacy saved steps.
28
+ */
10
29
  export declare enum QueryType {
11
30
  Select = "select",
31
+ /** @deprecated never authorable — use Transform to write. */
12
32
  Insert = "insert",
33
+ /** @deprecated never authorable — use Transform to write. */
13
34
  Update = "update",
35
+ /** @deprecated never authorable — use Transform to write. */
14
36
  Delete = "delete",
37
+ /** @deprecated never authorable. */
15
38
  Custom = "custom"
16
39
  }
17
- export declare enum FilterOperator {
18
- Equals = "equals",
19
- NotEquals = "not_equals",
20
- GreaterThan = "greater_than",
21
- LessThan = "less_than",
22
- GreaterThanOrEqual = "greater_than_or_equal",
23
- LessThanOrEqual = "less_than_or_equal",
24
- Contains = "contains",
25
- NotContains = "not_contains",
26
- StartsWith = "starts_with",
27
- EndsWith = "ends_with",
28
- In = "in",
29
- NotIn = "not_in",
30
- IsNull = "is_null",
31
- IsNotNull = "is_not_null",
32
- Between = "between"
33
- }
34
- export declare enum LogicalOperator {
35
- And = "and",
36
- Or = "or"
37
- }
38
- export declare enum SortDirection {
39
- Ascending = "asc",
40
- Descending = "desc"
41
- }
42
- export declare enum JoinType {
43
- Inner = "inner",
44
- Left = "left",
45
- Right = "right",
46
- Full = "full"
47
- }
48
- export declare enum AggregateFunction {
49
- Count = "count",
50
- Sum = "sum",
51
- Average = "avg",
52
- Min = "min",
53
- Max = "max",
54
- CountDistinct = "count_distinct"
55
- }
56
- export interface QueryField {
57
- id: string;
58
- table: string;
59
- column: string;
60
- alias?: string;
61
- aggregate?: AggregateFunction;
40
+ /** The modes the contract accepts. */
41
+ export declare const QUERY_MODES: readonly [QueryMode.Visual];
42
+ /** The query types the contract accepts. */
43
+ export declare const QUERY_TYPES: readonly [QueryType.Select];
44
+ /**
45
+ * Condition operators.
46
+ *
47
+ * Two spellings are accepted. The design contract writes the comparisons as
48
+ * symbols (`=`, `!=`, `>`, `<`, `>=`, `<=`); the editor has always stored them
49
+ * by name (`equals`, `notEquals`, `greaterThan`, `lessThan`, `greaterOrEqual`,
50
+ * `lessOrEqual`), and every saved step on beta and prod uses the names. Both
51
+ * mean the same thing, and both compilers (editor and server) must treat them
52
+ * the same.
53
+ */
54
+ export declare const QUERY_COMPARISON_OPERATORS: readonly ["=", "!=", ">", "<", ">=", "<=", "equals", "notEquals", "greaterThan", "lessThan", "greaterOrEqual", "lessOrEqual"];
55
+ export declare const QUERY_RELATIVE_DATE_OPERATORS: readonly ["inRelative", "notInRelative"];
56
+ export declare const QUERY_CONDITION_OPERATORS: readonly ["=", "!=", ">", "<", ">=", "<=", "equals", "notEquals", "greaterThan", "lessThan", "greaterOrEqual", "lessOrEqual", "contains", "startsWith", "endsWith", "like", "notLike", "in", "notIn", "between", "isNull", "isNotNull", "inRelative", "notInRelative"];
57
+ export type QueryComparisonOperator = (typeof QUERY_COMPARISON_OPERATORS)[number];
58
+ export type QueryConditionOperator = (typeof QUERY_CONDITION_OPERATORS)[number];
59
+ export declare const RELATIVE_DATE_DIRECTIONS: readonly ["last", "next", "this"];
60
+ export declare const RELATIVE_DATE_UNITS: readonly ["day", "week", "month", "quarter", "year"];
61
+ /** `amount` bounds for `last` / `next`. */
62
+ export declare const RELATIVE_DATE_MAX_AMOUNT = 3650;
63
+ export type RelativeDateDirection = (typeof RELATIVE_DATE_DIRECTIONS)[number];
64
+ export type RelativeDateUnit = (typeof RELATIVE_DATE_UNITS)[number];
65
+ /**
66
+ * A date window relative to the moment the step runs ("last 30 days", "next
67
+ * 2 weeks", "this month"). Resolved at run time in UTC — never fixed at save.
68
+ */
69
+ export interface RelativeDate {
70
+ direction: RelativeDateDirection;
71
+ /** Required for `last` / `next`: a whole number, 1..3650. */
72
+ amount?: number;
73
+ unit: RelativeDateUnit;
74
+ /** For `last` / `next`: include the current day/week/… (default true). */
75
+ includeCurrent?: boolean;
62
76
  }
63
- export interface QueryFilter {
77
+ export type QueryJoinOperator = 'AND' | 'OR';
78
+ /** One comparison: `field <operator> value` (or `<operator> valueField`). */
79
+ export interface ConditionRow {
64
80
  id: string;
81
+ /** Joins this item to the previous sibling. Ignored on the first. Default AND. */
82
+ joinOperator?: QueryJoinOperator;
65
83
  field: string;
66
- operator: FilterOperator;
84
+ operator: QueryConditionOperator;
85
+ /** A literal or a run-time value; for `between`, `[a, b]` (or `"a,b"`). */
67
86
  value?: unknown;
68
- values?: unknown[];
69
- logicalOperator?: LogicalOperator;
87
+ /** Compare with another field instead of a value. Exclusive with `value`. */
88
+ valueField?: string;
89
+ /** Only with `inRelative` / `notInRelative`. */
90
+ relative?: RelativeDate;
70
91
  }
71
- export interface QueryFilterGroup {
92
+ /** A parenthesised group of conditions. Nesting depth ≤ `MAX_CONDITION_DEPTH`. */
93
+ export interface ConditionGroup {
72
94
  id: string;
73
- filters: (QueryFilter | QueryFilterGroup)[];
74
- logicalOperator: LogicalOperator;
95
+ type: 'group';
96
+ joinOperator?: QueryJoinOperator;
97
+ conditions: Condition[];
98
+ }
99
+ export type Condition = ConditionRow | ConditionGroup;
100
+ /** How deep groups may nest: a top-level group is depth 1. */
101
+ export declare const MAX_CONDITION_DEPTH = 3;
102
+ export declare const isConditionGroup: (c: unknown) => c is ConditionGroup;
103
+ export declare const QUERY_AGGREGATE_FUNCTIONS: readonly ["COUNT", "COUNT_DISTINCT", "SUM", "AVG", "MIN", "MAX"];
104
+ /** The editor stores the function lowercase (`count`); both cases are accepted. */
105
+ export type QueryAggregateFn = (typeof QUERY_AGGREGATE_FUNCTIONS)[number] | Lowercase<(typeof QUERY_AGGREGATE_FUNCTIONS)[number]>;
106
+ export interface QueryAggregate {
107
+ fn: QueryAggregateFn;
108
+ /** The column to aggregate. `*` (or empty) is "all rows", for COUNT only. */
109
+ field: string;
110
+ /** The output column name. Needed to refer to the aggregate in `having`. */
111
+ alias?: string;
112
+ }
113
+ export declare enum SortDirection {
114
+ Ascending = "asc",
115
+ Descending = "desc"
75
116
  }
76
117
  export interface QuerySort {
77
- id: string;
118
+ id?: string;
78
119
  field: string;
79
- direction: SortDirection;
120
+ direction: 'asc' | 'desc';
80
121
  }
122
+ /** SQL databases only. */
81
123
  export interface QueryJoin {
82
124
  id: string;
83
- type: JoinType;
84
125
  table: string;
85
- leftField: string;
86
- rightField: string;
126
+ type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
127
+ onField: string;
128
+ targetField: string;
87
129
  }
88
- export interface QueryGroupBy {
89
- id: string;
90
- field: string;
91
- }
92
- export interface VisualQueryConfig {
130
+ export interface VisualConfigV2 {
131
+ /** Every table with every column (SQL databases). Tables/fields are then empty. */
132
+ selectAll?: boolean;
133
+ /** The table or object to read. The builder reads one; joins add more. */
93
134
  tables: string[];
94
- fields: QueryField[];
95
- filters?: QueryFilterGroup;
135
+ /** `table.column` names. Empty when the query is aggregate-only. */
136
+ fields: string[];
137
+ conditions?: Condition[];
96
138
  joins?: QueryJoin[];
97
- groupBy?: QueryGroupBy[];
139
+ /** Related objects whose fields may be read through a lookup (Salesforce, QuickBooks). */
140
+ relatedObjects?: string[];
141
+ /** `SELECT DISTINCT`. */
142
+ distinct?: boolean;
143
+ groupBy?: string[];
144
+ aggregates?: QueryAggregate[];
145
+ /** Filters on the grouped result, by aggregate alias or group column. Needs aggregates or groupBy. */
146
+ having?: ConditionRow[];
98
147
  sort?: QuerySort[];
148
+ /** Legacy single sort, still written as the first `sort` entry. */
149
+ orderBy?: {
150
+ field: string;
151
+ direction: string;
152
+ } | null;
153
+ /** The most rows a run reads (1..10,000; unset = 10,000). */
154
+ maxRows?: number;
155
+ /** Rows the preview shows. A run never reads it. */
99
156
  limit?: number;
100
- offset?: number;
157
+ /** Only rows whose `watermarkField` advanced since the last successful run. */
158
+ incremental?: boolean;
159
+ watermarkField?: string;
160
+ /** One page per run, for a ForEach cursor loop. */
161
+ paged?: boolean;
162
+ pageSize?: number;
163
+ /** Google Sheets whose header is not in row 1. */
164
+ sheetCustomLayout?: boolean;
165
+ sheetHeaderRow?: number;
166
+ sheetColumns?: string;
101
167
  }
102
- export interface SQLQueryConfig {
168
+ /** The name consumers already import. Same shape as `VisualConfigV2`. */
169
+ export type VisualQueryConfig = VisualConfigV2;
170
+ /**
171
+ * Compiled output — written by the editor or the server's compiler from
172
+ * `visualConfig`. Never authored.
173
+ */
174
+ export interface CompiledQuery {
103
175
  sql: string;
176
+ }
177
+ /** @deprecated use `CompiledQuery`; kept for legacy reads. */
178
+ export type SQLQueryConfig = CompiledQuery & {
104
179
  parameters?: Record<string, unknown>;
180
+ };
181
+ export interface BuildQueryConfig {
182
+ connectorId: string;
183
+ mode: QueryMode.Visual;
184
+ queryType: QueryType.Select;
185
+ visualConfig?: VisualConfigV2;
186
+ /** Derived. See `CompiledQuery`. */
187
+ sqlConfig?: CompiledQuery;
188
+ timeout?: number;
189
+ /** Legacy step-level field — not read at run; use `visualConfig.maxRows`. */
190
+ maxRows?: number;
191
+ /** MongoDB database / Google Sheets spreadsheet id. */
192
+ database?: string;
105
193
  }
106
194
  export interface TableSchema {
107
195
  name: string;
@@ -138,15 +226,6 @@ export interface ConnectorSchema {
138
226
  procedures?: string[];
139
227
  functions?: string[];
140
228
  }
141
- export interface BuildQueryConfig {
142
- connectorId: string;
143
- mode: QueryMode;
144
- queryType: QueryType;
145
- visualConfig?: VisualQueryConfig;
146
- sqlConfig?: SQLQueryConfig;
147
- timeout?: number;
148
- maxRows?: number;
149
- }
150
229
  export interface QueryExecutionResult {
151
230
  success: boolean;
152
231
  data?: unknown[];
@@ -189,7 +268,6 @@ export interface QueryableConnector {
189
268
  id: string;
190
269
  name: string;
191
270
  type: ConnectorType;
192
- supportsSQL: boolean;
193
271
  supportsVisualBuilder: boolean;
194
272
  schema?: ConnectorSchema;
195
273
  }
@@ -16,7 +16,12 @@ export interface ConditionFilter {
16
16
  id: string;
17
17
  field: string;
18
18
  operator: ConditionOperator;
19
- value: string;
19
+ /**
20
+ * The right-hand side: a literal, a field path, or a `$` system variable.
21
+ * Numbers and booleans are literals in their own right — `0` and `false`
22
+ * are real values, not "missing" (DEV-540).
23
+ */
24
+ value: string | number | boolean;
20
25
  logicalOperator?: 'and' | 'or';
21
26
  }
22
27
  export interface ConditionConfigType {