@spectric/ui 0.0.4
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/.gitlab-ci.yml +28 -0
- package/.nvmrc +1 -0
- package/.storybook/analyze.sh +4 -0
- package/.storybook/main.ts +55 -0
- package/.storybook/preview.ts +42 -0
- package/.vscode/extensions.json +5 -0
- package/.vscode/settings.json +41 -0
- package/README.MD +50 -0
- package/html-include.png +0 -0
- package/package.json +33 -0
- package/src/classes/BitArray.ts +48 -0
- package/src/classes/DisposibleElement.ts +108 -0
- package/src/components/Banner.ts +102 -0
- package/src/components/Bitdisplay.ts +383 -0
- package/src/components/Button.ts +121 -0
- package/src/components/Header.ts +125 -0
- package/src/components/Page.ts +157 -0
- package/src/components/Panel.ts +56 -0
- package/src/components/ThemeProvider.ts +251 -0
- package/src/components/button.css.ts +160 -0
- package/src/components/configurations/classifications.ts +194 -0
- package/src/components/dialog/dialog.css.ts +50 -0
- package/src/components/dialog/dialog.ts +163 -0
- package/src/components/dialog/index.ts +1 -0
- package/src/components/header.css.ts +38 -0
- package/src/components/index.ts +10 -0
- package/src/components/input.css +75 -0
- package/src/components/input.ts +312 -0
- package/src/components/page.css.ts +158 -0
- package/src/components/panel.css.ts +44 -0
- package/src/components/query_bar/QueryBar.css +48 -0
- package/src/components/query_bar/QueryBar.ts +378 -0
- package/src/components/query_bar/index.ts +2 -0
- package/src/components/query_bar/querylanguage/kuery/ast/_generated_/kuery.js +3186 -0
- package/src/components/query_bar/querylanguage/kuery/ast/ast.ts +113 -0
- package/src/components/query_bar/querylanguage/kuery/ast/index.ts +31 -0
- package/src/components/query_bar/querylanguage/kuery/ast/kuery.peg +417 -0
- package/src/components/query_bar/querylanguage/kuery/functions/and.ts +55 -0
- package/src/components/query_bar/querylanguage/kuery/functions/exists.ts +62 -0
- package/src/components/query_bar/querylanguage/kuery/functions/index.ts +47 -0
- package/src/components/query_bar/querylanguage/kuery/functions/is.ts +211 -0
- package/src/components/query_bar/querylanguage/kuery/functions/nested.ts +63 -0
- package/src/components/query_bar/querylanguage/kuery/functions/not.ts +53 -0
- package/src/components/query_bar/querylanguage/kuery/functions/or.ts +56 -0
- package/src/components/query_bar/querylanguage/kuery/functions/range.ts +163 -0
- package/src/components/query_bar/querylanguage/kuery/functions/utils/get_fields.ts +49 -0
- package/src/components/query_bar/querylanguage/kuery/functions/utils/get_full_field_name_node.ts +87 -0
- package/src/components/query_bar/querylanguage/kuery/index.ts +38 -0
- package/src/components/query_bar/querylanguage/kuery/kuery_syntax_error.ts +76 -0
- package/src/components/query_bar/querylanguage/kuery/node_types/function.ts +75 -0
- package/src/components/query_bar/querylanguage/kuery/node_types/index.ts +46 -0
- package/src/components/query_bar/querylanguage/kuery/node_types/literal.ts +42 -0
- package/src/components/query_bar/querylanguage/kuery/node_types/named_arg.ts +47 -0
- package/src/components/query_bar/querylanguage/kuery/node_types/types.ts +108 -0
- package/src/components/query_bar/querylanguage/kuery/node_types/wildcard.ts +80 -0
- package/src/components/query_bar/querylanguage/kuery/types.ts +52 -0
- package/src/components/query_bar/querylanguage/outputTypes/toCQL.ts +122 -0
- package/src/components/query_bar/querylanguage/outputTypes/toMongo.ts +103 -0
- package/src/components/query_bar/querylanguage/utils.ts +35 -0
- package/src/components/query_bar/types.ts +59 -0
- package/src/components/splitview/index.ts +1 -0
- package/src/components/splitview/splitview.css.ts +66 -0
- package/src/components/splitview/splitview.ts +183 -0
- package/src/components/types.ts +35 -0
- package/src/index.ts +1 -0
- package/src/stories/Banner.stories.ts +46 -0
- package/src/stories/BitDisplay.stories.ts +68 -0
- package/src/stories/Button.stories.ts +138 -0
- package/src/stories/Header.stories.ts +55 -0
- package/src/stories/Page.stories.ts +108 -0
- package/src/stories/QueryBar.stories.ts +63 -0
- package/src/stories/Splitview.stories.ts +52 -0
- package/src/stories/fixtures/Bits.ts +15 -0
- package/src/stories/fixtures/ExampleContent.ts +102 -0
- package/src/stories/fixtures/data.ts +30 -0
- package/src/stories/fixtures/lorumipsum.ts +19 -0
- package/src/stories/input.stories.ts +77 -0
- package/src/stories/tsconfig.json +35 -0
- package/src/utils/debounce.ts +18 -0
- package/src/utils/spread.ts +71 -0
- package/src/vite-env.d.ts +1 -0
- package/test/__init__.py +9 -0
- package/test/elastic.py +9 -0
- package/test/interface.py +16 -0
- package/tsconfig.json +29 -0
- package/vite.config.js +34 -0
- package/vue-example.png +0 -0
- package/vue-include.png +0 -0
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* The OpenSearch Contributors require contributions made to
|
|
5
|
+
* this file be licensed under the Apache-2.0 license or a
|
|
6
|
+
* compatible open source license.
|
|
7
|
+
*
|
|
8
|
+
* Any modifications Copyright OpenSearch Contributors. See
|
|
9
|
+
* GitHub history for details.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* Licensed to Elasticsearch B.V. under one or more contributor
|
|
14
|
+
* license agreements. See the NOTICE file distributed with
|
|
15
|
+
* this work for additional information regarding copyright
|
|
16
|
+
* ownership. Elasticsearch B.V. licenses this file to you under
|
|
17
|
+
* the Apache License, Version 2.0 (the "License"); you may
|
|
18
|
+
* not use this file except in compliance with the License.
|
|
19
|
+
* You may obtain a copy of the License at
|
|
20
|
+
*
|
|
21
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
+
*
|
|
23
|
+
* Unless required by applicable law or agreed to in writing,
|
|
24
|
+
* software distributed under the License is distributed on an
|
|
25
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
26
|
+
* KIND, either express or implied. See the License for the
|
|
27
|
+
* specific language governing permissions and limitations
|
|
28
|
+
* under the License.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import * as is from './is';
|
|
32
|
+
import * as and from './and';
|
|
33
|
+
import * as or from './or';
|
|
34
|
+
import * as not from './not';
|
|
35
|
+
import * as range from './range';
|
|
36
|
+
import * as exists from './exists';
|
|
37
|
+
import * as nested from './nested';
|
|
38
|
+
|
|
39
|
+
export const functions: any = {
|
|
40
|
+
is,
|
|
41
|
+
and,
|
|
42
|
+
or,
|
|
43
|
+
not,
|
|
44
|
+
range,
|
|
45
|
+
exists,
|
|
46
|
+
nested,
|
|
47
|
+
};
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* The OpenSearch Contributors require contributions made to
|
|
5
|
+
* this file be licensed under the Apache-2.0 license or a
|
|
6
|
+
* compatible open source license.
|
|
7
|
+
*
|
|
8
|
+
* Any modifications Copyright OpenSearch Contributors. See
|
|
9
|
+
* GitHub history for details.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* Licensed to Elasticsearch B.V. under one or more contributor
|
|
14
|
+
* license agreements. See the NOTICE file distributed with
|
|
15
|
+
* this work for additional information regarding copyright
|
|
16
|
+
* ownership. Elasticsearch B.V. licenses this file to you under
|
|
17
|
+
* the Apache License, Version 2.0 (the "License"); you may
|
|
18
|
+
* not use this file except in compliance with the License.
|
|
19
|
+
* You may obtain a copy of the License at
|
|
20
|
+
*
|
|
21
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
+
*
|
|
23
|
+
* Unless required by applicable law or agreed to in writing,
|
|
24
|
+
* software distributed under the License is distributed on an
|
|
25
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
26
|
+
* KIND, either express or implied. See the License for the
|
|
27
|
+
* specific language governing permissions and limitations
|
|
28
|
+
* under the License.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import { getFields } from './utils/get_fields';
|
|
32
|
+
import { getTimeZoneFromSettings } from '../../utils';
|
|
33
|
+
import { getFullFieldNameNode } from './utils/get_full_field_name_node';
|
|
34
|
+
import { IIndexPattern, KueryNode, IFieldType } from '../../..';
|
|
35
|
+
|
|
36
|
+
import * as ast from '../ast';
|
|
37
|
+
|
|
38
|
+
import * as literal from '../node_types/literal';
|
|
39
|
+
import * as wildcard from '../node_types/wildcard';
|
|
40
|
+
|
|
41
|
+
export function buildNodeParams(fieldName: string, value: any, isPhrase: boolean = false) {
|
|
42
|
+
if (fieldName === undefined) {
|
|
43
|
+
throw new Error('fieldName is a required argument');
|
|
44
|
+
}
|
|
45
|
+
if (value === undefined) {
|
|
46
|
+
throw new Error('value is a required argument');
|
|
47
|
+
}
|
|
48
|
+
const fieldNode =
|
|
49
|
+
typeof fieldName === 'string'
|
|
50
|
+
? ast.fromLiteralExpression(fieldName)
|
|
51
|
+
: literal.buildNode(fieldName);
|
|
52
|
+
const valueNode =
|
|
53
|
+
typeof value === 'string' ? ast.fromLiteralExpression(value) : literal.buildNode(value);
|
|
54
|
+
const isPhraseNode = literal.buildNode(isPhrase);
|
|
55
|
+
return {
|
|
56
|
+
arguments: [fieldNode, valueNode, isPhraseNode],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function toOpenSearchQuery(
|
|
61
|
+
node: KueryNode,
|
|
62
|
+
indexPattern?: IIndexPattern,
|
|
63
|
+
config: Record<string, any> = {},
|
|
64
|
+
context: Record<string, any> = {}
|
|
65
|
+
) {
|
|
66
|
+
const {
|
|
67
|
+
arguments: [fieldNameArg, valueArg, isPhraseArg],
|
|
68
|
+
} = node;
|
|
69
|
+
const fullFieldNameArg = getFullFieldNameNode(
|
|
70
|
+
fieldNameArg,
|
|
71
|
+
indexPattern,
|
|
72
|
+
context?.nested ? context.nested.path : undefined
|
|
73
|
+
);
|
|
74
|
+
const fieldName = ast.toOpenSearchQuery(fullFieldNameArg);
|
|
75
|
+
const value = !(valueArg === undefined) ? ast.toOpenSearchQuery(valueArg) : valueArg;
|
|
76
|
+
const type = isPhraseArg.value ? 'phrase' : 'best_fields';
|
|
77
|
+
if (fullFieldNameArg.value === null) {
|
|
78
|
+
if (valueArg.type === 'wildcard') {
|
|
79
|
+
return {
|
|
80
|
+
query_string: {
|
|
81
|
+
query: wildcard.toQueryStringQuery(valueArg),
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
multi_match: {
|
|
88
|
+
type,
|
|
89
|
+
query: value,
|
|
90
|
+
lenient: true,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const fields = indexPattern ? getFields(fullFieldNameArg, indexPattern) : [];
|
|
96
|
+
// If no fields are found in the index pattern we send through the given field name as-is. We do this to preserve
|
|
97
|
+
// the behaviour of lucene on dashboards where there are panels based on different index patterns that have different
|
|
98
|
+
// fields. If a user queries on a field that exists in one pattern but not the other, the index pattern without the
|
|
99
|
+
// field should return no results. It's debatable whether this is desirable, but it's been that way forever, so we'll
|
|
100
|
+
// keep things familiar for now.
|
|
101
|
+
if (fields && fields.length === 0) {
|
|
102
|
+
fields.push({
|
|
103
|
+
name: (ast.toOpenSearchQuery(fullFieldNameArg) as unknown) as string,
|
|
104
|
+
scripted: false,
|
|
105
|
+
type: '',
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const isExistsQuery = valueArg.type === 'wildcard' && (value as any) === '*';
|
|
110
|
+
const isAllFieldsQuery =
|
|
111
|
+
(fullFieldNameArg.type === 'wildcard' && ((fieldName as unknown) as string) === '*') ||
|
|
112
|
+
(fields && indexPattern && fields.length === indexPattern.fields.length);
|
|
113
|
+
const isMatchAllQuery = isExistsQuery && isAllFieldsQuery;
|
|
114
|
+
|
|
115
|
+
if (isMatchAllQuery) {
|
|
116
|
+
return { match_all: {} };
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const queries = fields!.reduce((accumulator: any, field: IFieldType) => {
|
|
120
|
+
const wrapWithNestedQuery = (query: any) => {
|
|
121
|
+
// Wildcards can easily include nested and non-nested fields. There isn't a good way to let
|
|
122
|
+
// users handle this themselves so we automatically add nested queries in this scenario.
|
|
123
|
+
if (
|
|
124
|
+
!(fullFieldNameArg.type === 'wildcard') ||
|
|
125
|
+
!field.subType?.nested ||
|
|
126
|
+
context?.nested
|
|
127
|
+
) {
|
|
128
|
+
return query;
|
|
129
|
+
} else {
|
|
130
|
+
return {
|
|
131
|
+
nested: {
|
|
132
|
+
path: field.subType!.nested!.path,
|
|
133
|
+
query,
|
|
134
|
+
score_mode: 'none',
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
|
|
140
|
+
if (field.scripted) {
|
|
141
|
+
return [] //don't support
|
|
142
|
+
// // Exists queries don't make sense for scripted fields
|
|
143
|
+
// if (!isExistsQuery) {
|
|
144
|
+
// return [
|
|
145
|
+
// ...accumulator,
|
|
146
|
+
// {
|
|
147
|
+
// script: {
|
|
148
|
+
// ...getPhraseScript(field, value as any),
|
|
149
|
+
// },
|
|
150
|
+
// },
|
|
151
|
+
// ];
|
|
152
|
+
// }
|
|
153
|
+
} else if (isExistsQuery) {
|
|
154
|
+
return [
|
|
155
|
+
...accumulator,
|
|
156
|
+
wrapWithNestedQuery({
|
|
157
|
+
exists: {
|
|
158
|
+
field: field.name,
|
|
159
|
+
},
|
|
160
|
+
}),
|
|
161
|
+
];
|
|
162
|
+
} else if (valueArg.type === 'wildcard') {
|
|
163
|
+
return [
|
|
164
|
+
...accumulator,
|
|
165
|
+
wrapWithNestedQuery({
|
|
166
|
+
query_string: {
|
|
167
|
+
fields: [field.name],
|
|
168
|
+
query: wildcard.toQueryStringQuery(valueArg),
|
|
169
|
+
},
|
|
170
|
+
}),
|
|
171
|
+
];
|
|
172
|
+
} else if (field.type === 'date') {
|
|
173
|
+
/*
|
|
174
|
+
If we detect that it's a date field and the user wants an exact date, we need to convert the query to both >= and <= the value provided to force a range query. This is because match and match_phrase queries do not accept a timezone parameter.
|
|
175
|
+
dateFormatTZ can have the value of 'Browser', in which case we guess the timezone using moment.tz.guess.
|
|
176
|
+
*/
|
|
177
|
+
const timeZoneParam = config.dateFormatTZ
|
|
178
|
+
? { time_zone: getTimeZoneFromSettings(config!.dateFormatTZ) }
|
|
179
|
+
: {};
|
|
180
|
+
return [
|
|
181
|
+
...accumulator,
|
|
182
|
+
wrapWithNestedQuery({
|
|
183
|
+
range: {
|
|
184
|
+
[field.name]: {
|
|
185
|
+
gte: value,
|
|
186
|
+
lte: value,
|
|
187
|
+
...timeZoneParam,
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
}),
|
|
191
|
+
];
|
|
192
|
+
} else {
|
|
193
|
+
const queryType = type === 'phrase' ? 'match_phrase' : 'match';
|
|
194
|
+
return [
|
|
195
|
+
...accumulator,
|
|
196
|
+
wrapWithNestedQuery({
|
|
197
|
+
[queryType]: {
|
|
198
|
+
[field.name]: value,
|
|
199
|
+
},
|
|
200
|
+
}),
|
|
201
|
+
];
|
|
202
|
+
}
|
|
203
|
+
}, []);
|
|
204
|
+
|
|
205
|
+
return {
|
|
206
|
+
bool: {
|
|
207
|
+
should: queries || [],
|
|
208
|
+
minimum_should_match: 1,
|
|
209
|
+
},
|
|
210
|
+
};
|
|
211
|
+
}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* The OpenSearch Contributors require contributions made to
|
|
5
|
+
* this file be licensed under the Apache-2.0 license or a
|
|
6
|
+
* compatible open source license.
|
|
7
|
+
*
|
|
8
|
+
* Any modifications Copyright OpenSearch Contributors. See
|
|
9
|
+
* GitHub history for details.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* Licensed to Elasticsearch B.V. under one or more contributor
|
|
14
|
+
* license agreements. See the NOTICE file distributed with
|
|
15
|
+
* this work for additional information regarding copyright
|
|
16
|
+
* ownership. Elasticsearch B.V. licenses this file to you under
|
|
17
|
+
* the Apache License, Version 2.0 (the "License"); you may
|
|
18
|
+
* not use this file except in compliance with the License.
|
|
19
|
+
* You may obtain a copy of the License at
|
|
20
|
+
*
|
|
21
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
+
*
|
|
23
|
+
* Unless required by applicable law or agreed to in writing,
|
|
24
|
+
* software distributed under the License is distributed on an
|
|
25
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
26
|
+
* KIND, either express or implied. See the License for the
|
|
27
|
+
* specific language governing permissions and limitations
|
|
28
|
+
* under the License.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import * as ast from '../ast';
|
|
32
|
+
import * as literal from '../node_types/literal';
|
|
33
|
+
import { IIndexPattern, KueryNode } from '../../..';
|
|
34
|
+
|
|
35
|
+
export function buildNodeParams(path: any, child: any) {
|
|
36
|
+
const pathNode =
|
|
37
|
+
typeof path === 'string' ? ast.fromLiteralExpression(path) : literal.buildNode(path);
|
|
38
|
+
return {
|
|
39
|
+
arguments: [pathNode, child],
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function toOpenSearchQuery(
|
|
44
|
+
node: KueryNode,
|
|
45
|
+
indexPattern?: IIndexPattern,
|
|
46
|
+
config: Record<string, any> = {},
|
|
47
|
+
context: Record<string, any> = {}
|
|
48
|
+
) {
|
|
49
|
+
const [path, child] = node.arguments;
|
|
50
|
+
const stringPath = ast.toOpenSearchQuery(path);
|
|
51
|
+
const fullPath = context?.nested?.path ? `${context.nested.path}.${stringPath}` : stringPath;
|
|
52
|
+
|
|
53
|
+
return {
|
|
54
|
+
nested: {
|
|
55
|
+
path: fullPath,
|
|
56
|
+
query: ast.toOpenSearchQuery(child, indexPattern, config, {
|
|
57
|
+
...context,
|
|
58
|
+
nested: { path: fullPath },
|
|
59
|
+
}),
|
|
60
|
+
score_mode: 'none',
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* The OpenSearch Contributors require contributions made to
|
|
5
|
+
* this file be licensed under the Apache-2.0 license or a
|
|
6
|
+
* compatible open source license.
|
|
7
|
+
*
|
|
8
|
+
* Any modifications Copyright OpenSearch Contributors. See
|
|
9
|
+
* GitHub history for details.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* Licensed to Elasticsearch B.V. under one or more contributor
|
|
14
|
+
* license agreements. See the NOTICE file distributed with
|
|
15
|
+
* this work for additional information regarding copyright
|
|
16
|
+
* ownership. Elasticsearch B.V. licenses this file to you under
|
|
17
|
+
* the Apache License, Version 2.0 (the "License"); you may
|
|
18
|
+
* not use this file except in compliance with the License.
|
|
19
|
+
* You may obtain a copy of the License at
|
|
20
|
+
*
|
|
21
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
+
*
|
|
23
|
+
* Unless required by applicable law or agreed to in writing,
|
|
24
|
+
* software distributed under the License is distributed on an
|
|
25
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
26
|
+
* KIND, either express or implied. See the License for the
|
|
27
|
+
* specific language governing permissions and limitations
|
|
28
|
+
* under the License.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import * as ast from '../ast';
|
|
32
|
+
import { IIndexPattern, KueryNode } from '../../..';
|
|
33
|
+
|
|
34
|
+
export function buildNodeParams(child: KueryNode) {
|
|
35
|
+
return {
|
|
36
|
+
arguments: [child],
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function toOpenSearchQuery(
|
|
41
|
+
node: KueryNode,
|
|
42
|
+
indexPattern?: IIndexPattern,
|
|
43
|
+
config: Record<string, any> = {},
|
|
44
|
+
context: Record<string, any> = {}
|
|
45
|
+
) {
|
|
46
|
+
const [argument] = node.arguments;
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
bool: {
|
|
50
|
+
must_not: ast.toOpenSearchQuery(argument, indexPattern, config, context),
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* The OpenSearch Contributors require contributions made to
|
|
5
|
+
* this file be licensed under the Apache-2.0 license or a
|
|
6
|
+
* compatible open source license.
|
|
7
|
+
*
|
|
8
|
+
* Any modifications Copyright OpenSearch Contributors. See
|
|
9
|
+
* GitHub history for details.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* Licensed to Elasticsearch B.V. under one or more contributor
|
|
14
|
+
* license agreements. See the NOTICE file distributed with
|
|
15
|
+
* this work for additional information regarding copyright
|
|
16
|
+
* ownership. Elasticsearch B.V. licenses this file to you under
|
|
17
|
+
* the Apache License, Version 2.0 (the "License"); you may
|
|
18
|
+
* not use this file except in compliance with the License.
|
|
19
|
+
* You may obtain a copy of the License at
|
|
20
|
+
*
|
|
21
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
+
*
|
|
23
|
+
* Unless required by applicable law or agreed to in writing,
|
|
24
|
+
* software distributed under the License is distributed on an
|
|
25
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
26
|
+
* KIND, either express or implied. See the License for the
|
|
27
|
+
* specific language governing permissions and limitations
|
|
28
|
+
* under the License.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import * as ast from '../ast';
|
|
32
|
+
import { IIndexPattern, KueryNode } from '../../..';
|
|
33
|
+
|
|
34
|
+
export function buildNodeParams(children: KueryNode[]) {
|
|
35
|
+
return {
|
|
36
|
+
arguments: children,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function toOpenSearchQuery(
|
|
41
|
+
node: KueryNode,
|
|
42
|
+
indexPattern?: IIndexPattern,
|
|
43
|
+
config: Record<string, any> = {},
|
|
44
|
+
context: Record<string, any> = {}
|
|
45
|
+
) {
|
|
46
|
+
const children = node.arguments || [];
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
bool: {
|
|
50
|
+
should: children.map((child: KueryNode) => {
|
|
51
|
+
return ast.toOpenSearchQuery(child, indexPattern, config, context);
|
|
52
|
+
}),
|
|
53
|
+
minimum_should_match: 1,
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* The OpenSearch Contributors require contributions made to
|
|
5
|
+
* this file be licensed under the Apache-2.0 license or a
|
|
6
|
+
* compatible open source license.
|
|
7
|
+
*
|
|
8
|
+
* Any modifications Copyright OpenSearch Contributors. See
|
|
9
|
+
* GitHub history for details.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* Licensed to Elasticsearch B.V. under one or more contributor
|
|
14
|
+
* license agreements. See the NOTICE file distributed with
|
|
15
|
+
* this work for additional information regarding copyright
|
|
16
|
+
* ownership. Elasticsearch B.V. licenses this file to you under
|
|
17
|
+
* the Apache License, Version 2.0 (the "License"); you may
|
|
18
|
+
* not use this file except in compliance with the License.
|
|
19
|
+
* You may obtain a copy of the License at
|
|
20
|
+
*
|
|
21
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
+
*
|
|
23
|
+
* Unless required by applicable law or agreed to in writing,
|
|
24
|
+
* software distributed under the License is distributed on an
|
|
25
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
26
|
+
* KIND, either express or implied. See the License for the
|
|
27
|
+
* specific language governing permissions and limitations
|
|
28
|
+
* under the License.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
import { nodeTypes } from '../node_types';
|
|
33
|
+
import * as ast from '../ast';
|
|
34
|
+
|
|
35
|
+
import { getFields } from './utils/get_fields';
|
|
36
|
+
import { getTimeZoneFromSettings } from '../../utils';
|
|
37
|
+
import { getFullFieldNameNode } from './utils/get_full_field_name_node';
|
|
38
|
+
import { IIndexPattern, KueryNode, IFieldType } from '../../..';
|
|
39
|
+
|
|
40
|
+
function pick(object: Record<string, any>, ...options: string[]) {
|
|
41
|
+
let out: Record<string, any> = {}
|
|
42
|
+
for (let op of options) {
|
|
43
|
+
out[op] = object[op]
|
|
44
|
+
}
|
|
45
|
+
return out
|
|
46
|
+
}
|
|
47
|
+
export function buildNodeParams(fieldName: string, params: any) {
|
|
48
|
+
const paramsToMap = pick(params, 'gt', 'lt', 'gte', 'lte', 'format');
|
|
49
|
+
const fieldNameArg =
|
|
50
|
+
typeof fieldName === 'string'
|
|
51
|
+
? ast.fromLiteralExpression(fieldName)
|
|
52
|
+
: nodeTypes.literal.buildNode(fieldName);
|
|
53
|
+
|
|
54
|
+
const args = Object.entries(paramsToMap).map((input) => {
|
|
55
|
+
let [key, value]: [string, number | string] = input
|
|
56
|
+
return nodeTypes.namedArg.buildNode(key, value);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
arguments: [fieldNameArg, ...args],
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function toOpenSearchQuery(
|
|
65
|
+
node: KueryNode,
|
|
66
|
+
indexPattern?: IIndexPattern,
|
|
67
|
+
config: Record<string, any> = {},
|
|
68
|
+
context: Record<string, any> = {}
|
|
69
|
+
) {
|
|
70
|
+
const [fieldNameArg, ...args] = node.arguments;
|
|
71
|
+
const fullFieldNameArg = getFullFieldNameNode(
|
|
72
|
+
fieldNameArg,
|
|
73
|
+
indexPattern,
|
|
74
|
+
context?.nested ? context.nested.path : undefined
|
|
75
|
+
);
|
|
76
|
+
const fields = indexPattern ? getFields(fullFieldNameArg, indexPattern) : [];
|
|
77
|
+
const namedArgs = extractArguments(args);
|
|
78
|
+
const queryParams = Object.fromEntries(Object.entries(namedArgs).map(([key, arg]) => {
|
|
79
|
+
return [key, ast.toOpenSearchQuery(arg as KueryNode)];
|
|
80
|
+
}));
|
|
81
|
+
|
|
82
|
+
// If no fields are found in the index pattern we send through the given field name as-is. We do this to preserve
|
|
83
|
+
// the behaviour of lucene on dashboards where there are panels based on different index patterns that have different
|
|
84
|
+
// fields. If a user queries on a field that exists in one pattern but not the other, the index pattern without the
|
|
85
|
+
// field should return no results. It's debatable whether this is desirable, but it's been that way forever, so we'll
|
|
86
|
+
// keep things familiar for now.
|
|
87
|
+
if (fields && fields.length === 0) {
|
|
88
|
+
fields.push({
|
|
89
|
+
name: (ast.toOpenSearchQuery(fullFieldNameArg) as unknown) as string,
|
|
90
|
+
scripted: false,
|
|
91
|
+
type: '',
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const queries = fields!.map((field: IFieldType) => {
|
|
96
|
+
const wrapWithNestedQuery = (query: any) => {
|
|
97
|
+
// Wildcards can easily include nested and non-nested fields. There isn't a good way to let
|
|
98
|
+
// users handle this themselves so we automatically add nested queries in this scenario.
|
|
99
|
+
if (
|
|
100
|
+
!(fullFieldNameArg.type === 'wildcard') ||
|
|
101
|
+
!field.subType?.nested ||
|
|
102
|
+
context!.nested
|
|
103
|
+
) {
|
|
104
|
+
return query;
|
|
105
|
+
} else {
|
|
106
|
+
return {
|
|
107
|
+
nested: {
|
|
108
|
+
path: field.subType!.nested!.path,
|
|
109
|
+
query,
|
|
110
|
+
score_mode: 'none',
|
|
111
|
+
},
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
if (field.scripted) {
|
|
117
|
+
return {} //Don't support this
|
|
118
|
+
|
|
119
|
+
} else if (field.type === 'date') {
|
|
120
|
+
const timeZoneParam = config.dateFormatTZ
|
|
121
|
+
? { time_zone: getTimeZoneFromSettings(config!.dateFormatTZ) }
|
|
122
|
+
: {};
|
|
123
|
+
return wrapWithNestedQuery({
|
|
124
|
+
range: {
|
|
125
|
+
[field.name]: {
|
|
126
|
+
...queryParams,
|
|
127
|
+
...timeZoneParam,
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
return wrapWithNestedQuery({
|
|
133
|
+
range: {
|
|
134
|
+
[field.name]: queryParams,
|
|
135
|
+
},
|
|
136
|
+
});
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
return {
|
|
140
|
+
bool: {
|
|
141
|
+
should: queries,
|
|
142
|
+
minimum_should_match: 1,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function extractArguments(args: any) {
|
|
148
|
+
if ((args.gt && args.gte) || (args.lt && args.lte)) {
|
|
149
|
+
throw new Error('range ends cannot be both inclusive and exclusive');
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
const unnamedArgOrder = ['gte', 'lte', 'format'];
|
|
153
|
+
|
|
154
|
+
return args.reduce((acc: any, arg: any, index: number) => {
|
|
155
|
+
if (arg.type === 'namedArg') {
|
|
156
|
+
acc[arg.name] = arg.value;
|
|
157
|
+
} else {
|
|
158
|
+
acc[unnamedArgOrder[index]] = arg;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return acc;
|
|
162
|
+
}, {});
|
|
163
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
*
|
|
4
|
+
* The OpenSearch Contributors require contributions made to
|
|
5
|
+
* this file be licensed under the Apache-2.0 license or a
|
|
6
|
+
* compatible open source license.
|
|
7
|
+
*
|
|
8
|
+
* Any modifications Copyright OpenSearch Contributors. See
|
|
9
|
+
* GitHub history for details.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/*
|
|
13
|
+
* Licensed to Elasticsearch B.V. under one or more contributor
|
|
14
|
+
* license agreements. See the NOTICE file distributed with
|
|
15
|
+
* this work for additional information regarding copyright
|
|
16
|
+
* ownership. Elasticsearch B.V. licenses this file to you under
|
|
17
|
+
* the Apache License, Version 2.0 (the "License"); you may
|
|
18
|
+
* not use this file except in compliance with the License.
|
|
19
|
+
* You may obtain a copy of the License at
|
|
20
|
+
*
|
|
21
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
22
|
+
*
|
|
23
|
+
* Unless required by applicable law or agreed to in writing,
|
|
24
|
+
* software distributed under the License is distributed on an
|
|
25
|
+
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
|
26
|
+
* KIND, either express or implied. See the License for the
|
|
27
|
+
* specific language governing permissions and limitations
|
|
28
|
+
* under the License.
|
|
29
|
+
*/
|
|
30
|
+
|
|
31
|
+
import * as literal from '../../node_types/literal';
|
|
32
|
+
import * as wildcard from '../../node_types/wildcard';
|
|
33
|
+
import { KueryNode, IIndexPattern } from '../../../..';
|
|
34
|
+
import { LiteralTypeBuildNode } from '../../node_types/types';
|
|
35
|
+
|
|
36
|
+
export function getFields(node: KueryNode, indexPattern?: IIndexPattern) {
|
|
37
|
+
if (!indexPattern) return [];
|
|
38
|
+
if (node.type === 'literal') {
|
|
39
|
+
const fieldName = literal.toOpenSearchQuery(node as LiteralTypeBuildNode);
|
|
40
|
+
const field = indexPattern.fields.find((fld) => fld.name === fieldName);
|
|
41
|
+
if (!field) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
return [field];
|
|
45
|
+
} else if (node.type === 'wildcard') {
|
|
46
|
+
const fields = indexPattern.fields.filter((fld) => wildcard.test(node, fld.name));
|
|
47
|
+
return fields;
|
|
48
|
+
}
|
|
49
|
+
}
|