import { TypeaheadInput , TypeaheadOutput } from '@grafana/ui' ; import { JSONPath } from 'jsonpath-plus' ; /**
 * onSuggest returns suggestions for the current JSON Path and cursor position.
 *
 * Normally you'd have to parse the query language here. This function
 * simplifies this by instead using JSON Path for getting the actual values.
 *
 * The onData provides the source data used when generating the suggestions.
 * This makes it easier to test the suggestions logic.
 */ export const onSuggest = async ( input , onData ) : Promise < TypeaheadOutput > => { const { value } = input ; const emptyResult = { suggestions : [ ] } ; if ( ! value ) { return emptyResult ; } const selectedLines = value . document . getTextsAtRange ( value . selection ) ; const currentLine = selectedLines . size === 1 ? selectedLines . first ( ) . getText ( ) : null ; if ( ! currentLine ) { return emptyResult ; } const toCursor = currentLine . slice ( 0 , value . selection . anchor . offset ) ; const currIdentifier = /[a-zA-Z0-9]$/ ; const nextIdentifier = /[\$\]a-zA-Z0-9]\.$/ ; const enterBrackets = /\[$/ ; const currentNodeIdentifier = /@\.$/ ; const shouldSuggest = currIdentifier . test ( toCursor ) || nextIdentifier . test ( toCursor ) || currentNodeIdentifier . test ( toCursor ) || enterBrackets . test ( toCursor ) ; if ( ! shouldSuggest ) { return emptyResult ; } if ( enterBrackets . test ( toCursor ) ) { return { suggestions : [ { label : 'Operators' , items : [ { label : '*' , documentation : 'Returns all elements.' } , { label : ':' , documentation : 'Returns a slice of the array.' } , { label : '?' , insertText : '?()' , move : - 1 , documentation : 'Returns elements based on a filter expression.' , } , ] , } , ] , } ; } const insideBrackets = toCursor . lastIndexOf ( '[' ) > toCursor . lastIndexOf ( ']' ) ; const path = insideBrackets ? toCursor . slice ( 0 , toCursor . lastIndexOf ( '[' ) + 1 ) + ':]' : currentLine . slice ( 0 , currentLine . lastIndexOf ( '.' ) ) ; const response = await onData ( ) ; const values = JSONPath ( { path , json : response } ) ; if ( typeof values [ 0 ] !== 'object' ) { return emptyResult ; } return { suggestions : [ { label : 'Elements' , items : Object . entries ( values [ 0 ] ) . map ( ( [ key , value ] ) => { return Array . isArray ( value ) ? { label : key , insertText : key + '[]' , move : - 1 , documentation : `_array (${ value . length })_` , } : { label : key , documentation : `_${ typeof value }_\n\n**Preview:**\n\n\`${ value }\`` , } ; } ) , } , ] , } ; } ;