@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.
- package/dist/catalog/general/query/config.d.ts +43 -16
- package/dist/catalog/general/query/index.d.ts +4 -4
- package/dist/catalog/general/query/types.d.ts +157 -79
- package/dist/catalog/logic/condition/config.d.ts +6 -1
- package/dist/index.cjs +323 -219
- package/dist/index.d.ts +2 -2
- package/dist/index.js +323 -219
- package/package.json +1 -1
|
@@ -1,24 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Query step configuration — defaults, validation and the contract (DEV-533).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
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,
|
|
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:
|
|
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
|
|
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
|
|
40
|
-
*
|
|
41
|
-
*
|
|
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 [
|
|
52
|
-
readonly description: "visual: the
|
|
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 [
|
|
58
|
-
readonly description: "
|
|
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
|
-
*
|
|
2
|
+
* Query Action
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
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
|
-
*
|
|
2
|
+
* Query step types — the shape the editor actually saves (DEV-533).
|
|
3
3
|
*
|
|
4
|
-
*
|
|
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
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
export
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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
|
|
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:
|
|
84
|
+
operator: QueryConditionOperator;
|
|
85
|
+
/** A literal or a run-time value; for `between`, `[a, b]` (or `"a,b"`). */
|
|
67
86
|
value?: unknown;
|
|
68
|
-
|
|
69
|
-
|
|
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
|
-
|
|
92
|
+
/** A parenthesised group of conditions. Nesting depth ≤ `MAX_CONDITION_DEPTH`. */
|
|
93
|
+
export interface ConditionGroup {
|
|
72
94
|
id: string;
|
|
73
|
-
|
|
74
|
-
|
|
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
|
|
118
|
+
id?: string;
|
|
78
119
|
field: string;
|
|
79
|
-
direction:
|
|
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
|
-
|
|
86
|
-
|
|
126
|
+
type: 'INNER' | 'LEFT' | 'RIGHT' | 'FULL';
|
|
127
|
+
onField: string;
|
|
128
|
+
targetField: string;
|
|
87
129
|
}
|
|
88
|
-
export interface
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
95
|
-
|
|
135
|
+
/** `table.column` names. Empty when the query is aggregate-only. */
|
|
136
|
+
fields: string[];
|
|
137
|
+
conditions?: Condition[];
|
|
96
138
|
joins?: QueryJoin[];
|
|
97
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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 {
|