Skip to content

Commit d264710

Browse files
committed
Define schemas for simple filter interface
1 parent 57c5acb commit d264710

File tree

5 files changed

+295
-3
lines changed

5 files changed

+295
-3
lines changed

src/platform/packages/shared/kbn-es-query-server/index.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99

1010
export { timeRangeSchema } from './src/time_range';
1111
export { querySchema } from './src/query';
12-
export { filterSchema } from './src/filter';
12+
export { appStateSchema, globalStateSchema, filterSchema } from './src/filter/stored_filter';
13+
export { simplifiedFilterSchema } from './src/filter/simplified_filter';
1314

1415
export type {
1516
TimeRange,
@@ -19,4 +20,12 @@ export type {
1920
FilterMeta,
2021
AggregateQuery,
2122
Query,
23+
SimplifiedFilter,
24+
SimpleFilterCondition,
25+
FilterGroup,
26+
RawDSLFilter,
27+
FilterOperator,
28+
FilterValue,
29+
RangeValue,
30+
StoredFilterState,
2231
} from './src/types';
Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,194 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
/**
11+
* Validation Schemas for Simplified Filter Interface
12+
*
13+
* This module provides @kbn/config-schema validation schemas that correspond
14+
* to the TypeScript types defined in simplified_filter_types.ts.
15+
*
16+
* These schemas are used for runtime validation of API requests and responses
17+
* in * as Code APIs.
18+
*/
19+
20+
import { schema } from '@kbn/config-schema';
21+
22+
// ====================================================================
23+
// CORE FILTER OPERATOR AND VALUE SCHEMAS
24+
// ====================================================================
25+
26+
/**
27+
* Schema for supported filter operators
28+
*/
29+
export const filterOperatorSchema = schema.oneOf([
30+
schema.literal('is'),
31+
schema.literal('is_not'),
32+
schema.literal('is_one_of'),
33+
schema.literal('is_not_one_of'),
34+
schema.literal('exists'),
35+
schema.literal('not_exists'),
36+
schema.literal('range'),
37+
]);
38+
39+
/**
40+
* Schema for range values used in numeric and date filters
41+
*/
42+
export const rangeValueSchema = schema.object({
43+
gte: schema.maybe(schema.oneOf([schema.number(), schema.string()])),
44+
lte: schema.maybe(schema.oneOf([schema.number(), schema.string()])),
45+
gt: schema.maybe(schema.oneOf([schema.number(), schema.string()])),
46+
lt: schema.maybe(schema.oneOf([schema.number(), schema.string()])),
47+
});
48+
49+
/**
50+
* Schema for all possible filter values
51+
* Supports single values, arrays, and range objects
52+
*/
53+
export const filterValueSchema = schema.oneOf([
54+
schema.string(),
55+
schema.number(),
56+
schema.boolean(),
57+
schema.arrayOf(schema.oneOf([schema.string(), schema.number(), schema.boolean()])),
58+
rangeValueSchema,
59+
]);
60+
61+
// ====================================================================
62+
// BASE FILTER PROPERTIES (SHARED BY ALL SIMPLIFIED FILTERS)
63+
// ====================================================================
64+
65+
/**
66+
* Base properties shared by all simplified filters
67+
*/
68+
const baseFilterPropertiesSchema = {
69+
id: schema.maybe(schema.string()),
70+
pinned: schema.maybe(schema.boolean()),
71+
disabled: schema.maybe(schema.boolean()),
72+
controlledBy: schema.maybe(schema.string()),
73+
indexPattern: schema.maybe(schema.string()),
74+
negate: schema.maybe(schema.boolean()),
75+
label: schema.maybe(schema.string()),
76+
};
77+
78+
// ====================================================================
79+
// SIMPLE FILTER CONDITION SCHEMAS
80+
// ====================================================================
81+
82+
/**
83+
* Base schema for simple filter conditions
84+
*/
85+
const baseFilterConditionSchema = {
86+
field: schema.string(),
87+
};
88+
89+
// ====================================================================
90+
// DISCRIMINATED FILTER CONDITION SCHEMAS
91+
// ====================================================================
92+
93+
/**
94+
* Schema for filter conditions that require a value
95+
*/
96+
export const filterConditionWithValueSchema = schema.object({
97+
...baseFilterConditionSchema,
98+
operator: schema.oneOf([
99+
schema.literal('is'),
100+
schema.literal('is_not'),
101+
schema.literal('is_one_of'),
102+
schema.literal('is_not_one_of'),
103+
schema.literal('range'),
104+
]),
105+
value: filterValueSchema,
106+
});
107+
108+
/**
109+
* Schema for filter conditions that check existence only
110+
*/
111+
export const filterConditionExistsSchema = schema.object({
112+
...baseFilterConditionSchema,
113+
operator: schema.oneOf([schema.literal('exists'), schema.literal('not_exists')]),
114+
// value is intentionally omitted for exists/not_exists operators
115+
});
116+
117+
/**
118+
* Discriminated union schema for simple filter conditions
119+
*/
120+
export const simpleFilterConditionSchema = schema.oneOf([
121+
filterConditionWithValueSchema,
122+
filterConditionExistsSchema,
123+
]);
124+
125+
// ====================================================================
126+
// FILTER GROUP SCHEMA (RECURSIVE)
127+
// ====================================================================
128+
129+
/**
130+
* Schema for logical filter groups with recursive structure
131+
* Uses lazy schema to handle recursive references
132+
* Note: Groups only contain logical structure (type, conditions) - no metadata properties
133+
*/
134+
export const filterGroupSchema = schema.object(
135+
{
136+
type: schema.oneOf([schema.literal('AND'), schema.literal('OR')]),
137+
conditions: schema.arrayOf(
138+
schema.oneOf([
139+
simpleFilterConditionSchema,
140+
schema.lazy('filterGroup'), // Recursive reference
141+
])
142+
),
143+
},
144+
{ meta: { id: 'filterGroup' } }
145+
);
146+
147+
// ====================================================================
148+
// RAW DSL FILTER SCHEMA
149+
// ====================================================================
150+
151+
/**
152+
* Schema for raw Elasticsearch Query DSL filters
153+
*/
154+
export const rawDSLFilterSchema = schema.object({
155+
query: schema.recordOf(schema.string(), schema.any()),
156+
});
157+
158+
// ====================================================================
159+
// SIMPLIFIED FILTER DISCRIMINATED UNION SCHEMA
160+
// ====================================================================
161+
162+
/**
163+
* Schema for simple condition filters (Tier 1)
164+
*/
165+
export const simplifiedConditionFilterSchema = schema.object({
166+
...baseFilterPropertiesSchema,
167+
condition: simpleFilterConditionSchema,
168+
});
169+
170+
/**
171+
* Schema for grouped condition filters (Tier 2-3)
172+
*/
173+
export const simplifiedGroupFilterSchema = schema.object({
174+
...baseFilterPropertiesSchema,
175+
group: filterGroupSchema,
176+
});
177+
178+
/**
179+
* Schema for raw DSL filters (Tier 4)
180+
*/
181+
export const simplifiedDSLFilterSchema = schema.object({
182+
...baseFilterPropertiesSchema,
183+
dsl: rawDSLFilterSchema,
184+
});
185+
186+
/**
187+
* Main discriminated union schema for SimplifiedFilter
188+
* Ensures exactly one of: condition, group, or dsl is present
189+
*/
190+
export const simplifiedFilterSchema = schema.oneOf([
191+
simplifiedConditionFilterSchema,
192+
simplifiedGroupFilterSchema,
193+
simplifiedDSLFilterSchema,
194+
]);
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
3+
* or more contributor license agreements. Licensed under the "Elastic License
4+
* 2.0", the "GNU Affero General Public License v3.0 only", and the "Server Side
5+
* Public License v 1"; you may not use this file except in compliance with, at
6+
* your election, the "Elastic License 2.0", the "GNU Affero General Public
7+
* License v3.0 only", or the "Server Side Public License, v 1".
8+
*/
9+
10+
import { schema } from '@kbn/config-schema';
11+
12+
export const appStateSchema = schema.literal('appState');
13+
export const globalStateSchema = schema.literal('globalState');
14+
15+
const filterStateStoreSchema = schema.oneOf([appStateSchema, globalStateSchema], {
16+
meta: {
17+
description:
18+
"Denote whether a filter is specific to an application's context (e.g. 'appState') or whether it should be applied globally (e.g. 'globalState').",
19+
},
20+
});
21+
22+
export const filterMetaSchema = schema.object(
23+
{
24+
alias: schema.maybe(schema.nullable(schema.string())),
25+
disabled: schema.maybe(schema.boolean()),
26+
negate: schema.maybe(schema.boolean()),
27+
controlledBy: schema.maybe(
28+
schema.string({ meta: { description: 'Identifies the owner the filter.' } })
29+
),
30+
group: schema.maybe(
31+
schema.string({ meta: { description: 'The group to which this filter belongs.' } })
32+
),
33+
relation: schema.maybe(schema.string()),
34+
// field is missing from the Filter type, but is stored in SerializedSearchSourceFields
35+
// see the todo in src/platform/packages/shared/kbn-es-query/src/filters/helpers/update_filter.ts
36+
field: schema.maybe(schema.string()),
37+
index: schema.maybe(schema.string()),
38+
isMultiIndex: schema.maybe(schema.boolean()),
39+
type: schema.maybe(schema.string()),
40+
key: schema.maybe(schema.string()),
41+
// We could consider creating FilterMetaParams as a schema to match the concrete Filter type.
42+
// However, this is difficult because FilterMetaParams can be a `filterSchema` which is defined below.
43+
// This would require a more complex schema definition that can handle recursive types.
44+
// For now, we use `schema.any()` to allow flexibility in the params field.
45+
params: schema.maybe(schema.any()),
46+
value: schema.maybe(schema.string()),
47+
},
48+
{ unknowns: 'allow' }
49+
);
50+
51+
export const filterSchema = schema.object(
52+
{
53+
meta: filterMetaSchema,
54+
query: schema.maybe(schema.recordOf(schema.string(), schema.any())),
55+
$state: schema.maybe(
56+
schema.object({
57+
store: filterStateStoreSchema,
58+
})
59+
),
60+
},
61+
{ meta: { id: 'kbn-es-query-server-filterSchema' } }
62+
);

src/platform/packages/shared/kbn-es-query-server/src/types.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,21 @@ import type {
1515
relativeTimeRangeSchema,
1616
} from './time_range';
1717
import type { aggregateQuerySchema, querySchema } from './query';
18-
import type { filterSchema, filterMetaSchema } from './filter';
18+
import type {
19+
filterSchema,
20+
filterMetaSchema,
21+
globalStateSchema,
22+
appStateSchema,
23+
} from './filter/stored_filter';
24+
import type {
25+
simplifiedFilterSchema,
26+
simpleFilterConditionSchema,
27+
filterGroupSchema,
28+
rawDSLFilterSchema,
29+
filterOperatorSchema,
30+
filterValueSchema,
31+
rangeValueSchema,
32+
} from './filter/simplified_filter';
1933

2034
export type TimeRange = Writable<TypeOf<typeof timeRangeSchema>>;
2135
export type AbsoluteTimeRange = TypeOf<typeof absoluteTimeRangeSchema>;
@@ -26,3 +40,17 @@ export type AggregateQuery = Writable<TypeOf<typeof aggregateQuerySchema>>;
2640

2741
export type Filter = Writable<TypeOf<typeof filterSchema>>;
2842
export type FilterMeta = Writable<TypeOf<typeof filterMetaSchema>>;
43+
44+
/**
45+
* Schema-inferred types for Simplified Filter API
46+
*
47+
* These types are inferred from validation schemas and provide runtime validation compatibility.
48+
*/
49+
export type SimplifiedFilter = Writable<TypeOf<typeof simplifiedFilterSchema>>;
50+
export type SimpleFilterCondition = Writable<TypeOf<typeof simpleFilterConditionSchema>>;
51+
export type FilterGroup = Writable<TypeOf<typeof filterGroupSchema>>;
52+
export type RawDSLFilter = Writable<TypeOf<typeof rawDSLFilterSchema>>;
53+
export type FilterOperator = Writable<TypeOf<typeof filterOperatorSchema>>;
54+
export type FilterValue = Writable<TypeOf<typeof filterValueSchema>>;
55+
export type RangeValue = Writable<TypeOf<typeof rangeValueSchema>>;
56+
export type StoredFilterState = TypeOf<typeof appStateSchema> | TypeOf<typeof globalStateSchema>;

src/platform/packages/shared/kbn-es-query-server/tsconfig.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,5 @@
99
"kbn_references": [
1010
"@kbn/config-schema",
1111
"@kbn/utility-types",
12-
"@kbn/es-query",
1312
],
1413
}

0 commit comments

Comments
 (0)