Skip to content

Commit

Permalink
TS of esKuery\node_types (#56857)
Browse files Browse the repository at this point in the history
* TS of node types and collector

* Code review
  • Loading branch information
Liza Katz committed Feb 7, 2020
1 parent 54add37 commit 9a79acf
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,13 @@
*/

import _ from 'lodash';
// @ts-ignore
import { functions } from '../functions';
import { IIndexPattern } from '../../..';
import { FunctionName, FunctionTypeBuildNode } from './types';
import { JsonValue } from '..';

export function buildNode(functionName, ...functionArgs) {
export function buildNode(functionName: FunctionName, ...args: any[]) {
const kueryFunction = functions[functionName];
if (_.isUndefined(kueryFunction)) {
throw new Error(`Unknown function "${functionName}"`);
Expand All @@ -29,24 +33,32 @@ export function buildNode(functionName, ...functionArgs) {
return {
type: 'function',
function: functionName,
...kueryFunction.buildNodeParams(...functionArgs),
...kueryFunction.buildNodeParams(...args),
};
}

// Mainly only useful in the grammar where we'll already have real argument nodes in hand
export function buildNodeWithArgumentNodes(functionName, argumentNodes) {
export function buildNodeWithArgumentNodes(
functionName: FunctionName,
args: any[]
): FunctionTypeBuildNode {
if (_.isUndefined(functions[functionName])) {
throw new Error(`Unknown function "${functionName}"`);
}

return {
type: 'function',
function: functionName,
arguments: argumentNodes,
arguments: args,
};
}

export function toElasticsearchQuery(node, indexPattern, config = {}, context = {}) {
export function toElasticsearchQuery(
node: any,
indexPattern?: IIndexPattern,
config?: Record<string, any>,
context?: Record<string, any>
): JsonValue {
const kueryFunction = functions[node.function];
return kueryFunction.toElasticsearchQuery(node, indexPattern, config, context);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ import * as functionType from './function';
import * as literal from './literal';
import * as namedArg from './named_arg';
import * as wildcard from './wildcard';
import { NodeTypes } from './types';

export const nodeTypes = {
export { NodeTypes };

export const nodeTypes: NodeTypes = {
function: functionType,
literal,
namedArg,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
* under the License.
*/

export function buildNode(value) {
import { LiteralTypeBuildNode } from './types';

export function buildNode(value: LiteralTypeBuildNode['value']): LiteralTypeBuildNode {
return {
type: 'literal',
value,
};
}

export function toElasticsearchQuery(node) {
export function toElasticsearchQuery(node: LiteralTypeBuildNode): LiteralTypeBuildNode['value'] {
return node.value;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,10 @@
import _ from 'lodash';
import * as ast from '../ast';
import { nodeTypes } from '../node_types';
import { NamedArgTypeBuildNode } from './types';
import { JsonObject } from '../types';

export function buildNode(name, value) {
export function buildNode(name: string, value: any): NamedArgTypeBuildNode {
const argumentNode =
_.get(value, 'type') === 'literal' ? value : nodeTypes.literal.buildNode(value);
return {
Expand All @@ -31,6 +33,6 @@ export function buildNode(name, value) {
};
}

export function toElasticsearchQuery(node) {
export function toElasticsearchQuery(node: any): JsonObject {
return ast.toElasticsearchQuery(node.value);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@
*/

import { IIndexPattern } from '../../../index_patterns';
import { KueryNode, JsonValue } from '..';
import { JsonValue, KueryNode } from '..';

type FunctionName =
export type FunctionName =
| 'is'
| 'and'
| 'or'
Expand All @@ -37,7 +37,7 @@ type FunctionName =

interface FunctionType {
buildNode: (functionName: FunctionName, ...args: any[]) => FunctionTypeBuildNode;
buildNodeWithArgumentNodes: (functionName: FunctionName, ...args: any[]) => FunctionTypeBuildNode;
buildNodeWithArgumentNodes: (functionName: FunctionName, args: any[]) => FunctionTypeBuildNode;
toElasticsearchQuery: (
node: any,
indexPattern?: IIndexPattern,
Expand All @@ -46,7 +46,7 @@ interface FunctionType {
) => JsonValue;
}

interface FunctionTypeBuildNode {
export interface FunctionTypeBuildNode {
type: 'function';
function: FunctionName;
// TODO -> Need to define a better type for DSL query
Expand All @@ -58,40 +58,38 @@ interface LiteralType {
toElasticsearchQuery: (node: any) => null | boolean | number | string;
}

interface LiteralTypeBuildNode {
export interface LiteralTypeBuildNode {
type: 'literal';
value: null | boolean | number | string;
}

interface NamedArgType {
buildNode: (name: string, value: any) => NamedArgTypeBuildNode;
toElasticsearchQuery: (node: any) => string;
toElasticsearchQuery: (node: any) => JsonValue;
}

interface NamedArgTypeBuildNode {
export interface NamedArgTypeBuildNode {
type: 'namedArg';
name: string;
value: any;
}

interface WildcardType {
buildNode: (value: string) => WildcardTypeBuildNode;
buildNode: (value: string) => WildcardTypeBuildNode | KueryNode;
test: (node: any, string: string) => boolean;
toElasticsearchQuery: (node: any) => string;
toQueryStringQuery: (node: any) => string;
hasLeadingWildcard: (node: any) => boolean;
}

interface WildcardTypeBuildNode {
export interface WildcardTypeBuildNode {
type: 'wildcard';
value: string;
}

interface NodeTypes {
export interface NodeTypes {
function: FunctionType;
literal: LiteralType;
namedArg: NamedArgType;
wildcard: WildcardType;
}

export const nodeTypes: NodeTypes;
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,22 @@
*/

import { fromLiteralExpression } from '../ast/ast';
import { WildcardTypeBuildNode } from './types';
import { KueryNode } from '..';

export const wildcardSymbol = '@kuery-wildcard@';

// Copied from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions
function escapeRegExp(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
function escapeRegExp(str: string) {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
}

// See https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html#_reserved_characters
function escapeQueryString(string) {
return string.replace(/[+-=&|><!(){}[\]^"~*?:\\/]/g, '\\$&'); // $& means the whole matched string
function escapeQueryString(str: string) {
return str.replace(/[+-=&|><!(){}[\]^"~*?:\\/]/g, '\\$&'); // $& means the whole matched string
}

export function buildNode(value) {
export function buildNode(value: string): WildcardTypeBuildNode | KueryNode {
if (!value.includes(wildcardSymbol)) {
return fromLiteralExpression(value);
}
Expand All @@ -42,30 +44,30 @@ export function buildNode(value) {
};
}

export function test(node, string) {
export function test(node: any, str: string): boolean {
const { value } = node;
const regex = value
.split(wildcardSymbol)
.map(escapeRegExp)
.join('[\\s\\S]*');
const regexp = new RegExp(`^${regex}$`);
return regexp.test(string);
return regexp.test(str);
}

export function toElasticsearchQuery(node) {
export function toElasticsearchQuery(node: any): string {
const { value } = node;
return value.split(wildcardSymbol).join('*');
}

export function toQueryStringQuery(node) {
export function toQueryStringQuery(node: any): string {
const { value } = node;
return value
.split(wildcardSymbol)
.map(escapeQueryString)
.join('*');
}

export function hasLeadingWildcard(node) {
export function hasLeadingWildcard(node: any): boolean {
const { value } = node;
// A lone wildcard turns into an `exists` query, so we're only concerned with
// leading wildcards followed by additional characters.
Expand Down

0 comments on commit 9a79acf

Please sign in to comment.