1
1
import _ from 'lodash' ;
2
- import { isValid , parseISO } from 'date-fns' ;
3
2
import { JSONPath } from 'jsonpath-plus' ;
4
3
5
4
import {
@@ -9,13 +8,14 @@ import {
9
8
DataSourceInstanceSettings ,
10
9
toDataFrame ,
11
10
MetricFindValue ,
12
- FieldType ,
13
11
ScopedVars ,
14
12
TimeRange ,
15
13
} from '@grafana/data' ;
16
14
import { getTemplateSrv } from '@grafana/runtime' ;
17
15
18
16
import API from './api' ;
17
+ import { detectFieldType } from './detectFieldType' ;
18
+ import { parseValues } from './parseValues' ;
19
19
import { JsonApiQuery , JsonApiDataSourceOptions , Pair } from './types' ;
20
20
21
21
export class JsonDataSource extends DataSourceApi < JsonApiQuery , JsonApiDataSourceOptions > {
@@ -176,104 +176,3 @@ const replaceMacros = (str: string, range?: TimeRange) => {
176
176
. replace ( / \$ _ _ u n i x E p o c h T o \( \) / g, range . to . unix ( ) . toString ( ) )
177
177
: str ;
178
178
} ;
179
-
180
- /**
181
- * Detects the field type from an array of values.
182
- */
183
- export const detectFieldType = ( values : any [ ] ) : FieldType => {
184
- // If all values are null, default to strings.
185
- if ( values . every ( ( _ ) => _ === null ) ) {
186
- return FieldType . string ;
187
- }
188
-
189
- // If all values are valid ISO 8601, then assume that it's a time field.
190
- const isValidISO = values
191
- . filter ( ( value ) => value !== null )
192
- . every ( ( value ) => value . length >= 10 && isValid ( parseISO ( value ) ) ) ;
193
- if ( isValidISO ) {
194
- return FieldType . time ;
195
- }
196
-
197
- if ( values . every ( ( value ) => typeof value === 'number' ) ) {
198
- const uniqueLengths = Array . from ( new Set ( values . map ( ( value ) => Math . round ( value ) . toString ( ) . length ) ) ) ;
199
- const hasSameLength = uniqueLengths . length === 1 ;
200
-
201
- // If all the values have the same length of either 10 (seconds) or 13
202
- // (milliseconds), assume it's a time field. This is not always true, so we
203
- // might need to add an option to disable detection of time fields.
204
- if ( hasSameLength ) {
205
- if ( uniqueLengths [ 0 ] === 13 ) {
206
- return FieldType . time ;
207
- }
208
- if ( uniqueLengths [ 0 ] === 10 ) {
209
- return FieldType . time ;
210
- }
211
- }
212
-
213
- return FieldType . number ;
214
- }
215
-
216
- if ( values . every ( ( value ) => typeof value === 'boolean' ) ) {
217
- return FieldType . boolean ;
218
- }
219
-
220
- return FieldType . string ;
221
- } ;
222
-
223
- /**
224
- * parseValues converts values to the given field type.
225
- */
226
- export const parseValues = ( values : any [ ] , type : FieldType ) : any [ ] => {
227
- switch ( type ) {
228
- case FieldType . time :
229
- // For time field, values are expected to be numbers representing a Unix
230
- // epoch in milliseconds.
231
-
232
- if ( values . filter ( ( _ ) => _ ) . every ( ( value ) => typeof value === 'string' ) ) {
233
- return values . map ( ( _ ) => ( _ !== null ? parseISO ( _ ) . valueOf ( ) : _ ) ) ;
234
- }
235
-
236
- if ( values . filter ( ( _ ) => _ ) . every ( ( value ) => typeof value === 'number' ) ) {
237
- const ms = 1_000_000_000_000 ;
238
-
239
- // If there are no "big" numbers, assume seconds.
240
- if ( values . filter ( ( _ ) => _ ) . every ( ( _ ) => _ < ms ) ) {
241
- return values . map ( ( _ ) => ( _ !== null ? _ * 1000.0 : _ ) ) ;
242
- }
243
-
244
- // ... otherwise assume milliseconds.
245
- return values ;
246
- }
247
-
248
- throw new Error ( 'Unsupported time property' ) ;
249
- case FieldType . string :
250
- return values . every ( ( _ ) => typeof _ === 'string' ) ? values : values . map ( ( _ ) => ( _ !== null ? _ . toString ( ) : _ ) ) ;
251
- case FieldType . number :
252
- return values . every ( ( _ ) => typeof _ === 'number' ) ? values : values . map ( ( _ ) => ( _ !== null ? parseFloat ( _ ) : _ ) ) ;
253
- case FieldType . boolean :
254
- return values . every ( ( _ ) => typeof _ === 'boolean' )
255
- ? values
256
- : values . map ( ( _ ) => {
257
- if ( _ === null ) {
258
- return _ ;
259
- }
260
-
261
- switch ( _ . toString ( ) ) {
262
- case '0' :
263
- case 'false' :
264
- case 'FALSE' :
265
- case 'False' :
266
- return false ;
267
- case '1' :
268
- case 'true' :
269
- case 'TRUE' :
270
- case 'True' :
271
- return true ;
272
- default :
273
- throw new Error ( 'Found non-boolean values in a field of type boolean: ' + _ . toString ( ) ) ;
274
- }
275
- } ) ;
276
- default :
277
- throw new Error ( 'Unsupported field type' ) ;
278
- }
279
- } ;
0 commit comments