Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18,852 changes: 18,833 additions & 19 deletions dist/module.js

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions dist/module.js.LICENSE.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
2 changes: 1 addition & 1 deletion dist/module.js.map

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion dist/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
{ "name": "GitHub Security Advisories", "path": "img/github_security_advisories.png"}
],
"version": "1.3.0",
"updated": "2021-03-16"
"updated": "2021-06-07"
},

"dependencies": {
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
"moment": "*"
},
"dependencies": {
"@types/lodash": "^4.14.144"
"@types/lodash": "^4.14.144",
"graphql": "^15.5.0"
}
}
71 changes: 51 additions & 20 deletions src/DataSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,28 +19,31 @@ import {
MyVariableQuery,
MultiValueVariable,
TextValuePair,
RequestFactory,
} from './types';
import { dateTime, MutableDataFrame, FieldType, DataFrame } from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import _ from 'lodash';
import { isEqual } from 'lodash';
import { flatten, isRFC3339_ISO6801 } from './util';
import { GraphQLObjectType, isObjectType } from 'graphql';
import { Schema } from './schema';

const supportedVariableTypes = ['constant', 'custom', 'query', 'textbox'];

export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
basicAuth: string | undefined;
withCredentials: boolean | undefined;
url: string | undefined;

constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>, private backendSrv: any) {
super(instanceSettings);
this.basicAuth = instanceSettings.basicAuth;
this.withCredentials = instanceSettings.withCredentials;
this.url = instanceSettings.url;
class _RequestFactory implements RequestFactory {
constructor(
private basicAuth: string | undefined,
private withCredentials: boolean | undefined,
private url: string,
private backendSrv: any
) {
this.basicAuth = basicAuth;
this.withCredentials = withCredentials;
this.url = url;
this.backendSrv = backendSrv;
}

private request(data: string) {
request(data: string): Promise<any> {
const options: any = {
url: this.url,
method: 'POST',
Expand All @@ -60,9 +63,26 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {

return this.backendSrv.datasourceRequest(options);
}
}

export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
private schema: Schema;
private requestFactory: RequestFactory;

constructor(instanceSettings: DataSourceInstanceSettings<MyDataSourceOptions>, backendSrv: any) {
super(instanceSettings);
this.requestFactory = new _RequestFactory(
instanceSettings.basicAuth,
instanceSettings.withCredentials,
instanceSettings.url as string,
backendSrv
);
this.schema = new Schema(this.requestFactory);
}

private postQuery(query: Partial<MyQuery>, payload: string) {
return this.request(payload)
return this.requestFactory
.request(payload)
.then((results: any) => {
return { query, results };
})
Expand Down Expand Up @@ -138,12 +158,15 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
}

async query(options: DataQueryRequest<MyQuery>): Promise<DataQueryResponse> {
return Promise.all(
options.targets.map((target) => {
return this.createQuery(defaults(target, defaultQuery), options.range, options.scopedVars);
})
).then((results: any) => {
let promises: Array<Promise<any>> = options.targets.map((target) => {
return this.createQuery(defaults(target, defaultQuery), options.range, options.scopedVars);
});
promises.push(this.schema.getQuery());

return Promise.all(promises).then((results: any[]) => {
const dataFrameArray: DataFrame[] = [];
let queryType: GraphQLObjectType = results.pop();

for (let res of results) {
const dataPathArray: string[] = DataSource.getDataPathArray(res.query.dataPath);
const { timePath, timeFormat, groupBy, aliasBy } = res.query;
Expand All @@ -157,6 +180,10 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
}
for (const dataPath of dataPathArray) {
const docs: any[] = DataSource.getDocs(res.results.data, dataPath);
let dataType = Schema.getTypeOfDescendant(queryType, dataPath);
if (!isObjectType(dataType)) {
throw `Data path ${dataPath} has type ${dataType.name}, expected object type`;
}

const dataFrameMap = new Map<string, MutableDataFrame>();
for (const doc of docs) {
Expand All @@ -180,9 +207,13 @@ export class DataSource extends DataSourceApi<MyQuery, MyDataSourceOptions> {
let t: FieldType = FieldType.string;
if (fieldName === timePath || isRFC3339_ISO6801(String(doc[fieldName]))) {
t = FieldType.time;
} else if (_.isNumber(doc[fieldName])) {
t = FieldType.number;
} else {
let fieldType = Schema.getTypeOfDescendant(dataType, fieldName);
if (Schema.isNumericType(fieldType)) {
t = FieldType.number;
}
}

let title;
if (identifiers.length !== 0) {
// if we have any identifiers
Expand Down
46 changes: 46 additions & 0 deletions src/schema.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { GraphQLFloat, GraphQLInt, GraphQLObjectType, GraphQLString } from 'graphql';
import { Schema } from './schema';

test('getTypeOfDescendant', () => {
const childType = new GraphQLObjectType({
name: 'child-type',
fields: {
grandchild1: { type: GraphQLInt },
grandchild2: { type: GraphQLFloat },
},
});
const parentType = new GraphQLObjectType({
name: 'parent-type',
fields: {
child1: { type: GraphQLString },
child2: {
type: childType,
},
},
});

expect(Schema.getTypeOfDescendant(parentType, 'child1')).toBe(GraphQLString);
expect(Schema.getTypeOfDescendant(parentType, 'child2')).toBe(childType);
expect(Schema.getTypeOfDescendant(parentType, 'child2.grandchild1')).toBe(GraphQLInt);
expect(Schema.getTypeOfDescendant(parentType, 'child2.grandchild2')).toBe(GraphQLFloat);
expect(Schema.getTypeOfDescendant(childType, 'grandchild1')).toBe(GraphQLInt);
});

describe('isNumericType', () => {
test('object', () => {
const type = new GraphQLObjectType({ name: 'Address', fields: { street: { type: GraphQLString } } });
expect(Schema.isNumericType(type)).not.toBeTruthy();
});

test('string', () => {
expect(Schema.isNumericType(GraphQLString)).not.toBeTruthy();
});

test('int', () => {
expect(Schema.isNumericType(GraphQLInt)).toBeTruthy();
});

test('float', () => {
expect(Schema.isNumericType(GraphQLFloat)).toBeTruthy();
});
});
55 changes: 55 additions & 0 deletions src/schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
import {
buildClientSchema,
getIntrospectionQuery,
getNamedType,
GraphQLNamedType,
GraphQLObjectType,
isObjectType,
isScalarType,
printSchema,
} from 'graphql';
import { RequestFactory } from './types';

export class Schema {
private query: Promise<GraphQLObjectType> | undefined;

constructor(private requestFactory: RequestFactory) {
this.requestFactory = requestFactory;
}

getQuery(): Promise<GraphQLObjectType> {
if (!this.query) {
this.query = this.requestFactory.request(getIntrospectionQuery()).then((results: any) => {
let schema = buildClientSchema(results.data.data);
let queryType = schema.getQueryType();
if (!queryType) {
throw `No query type in schema: ${printSchema(schema)}`;
}
return queryType;
});
}
// @ts-ignore (it's defined now)
return this.query;
}

static getTypeOfDescendant(nodeType: GraphQLObjectType, path: string): GraphQLNamedType {
let descendantType = nodeType;
let pathComponents = path.split('.');
for (let i = 0; i < pathComponents.length; i++) {
let type = getNamedType(descendantType.getFields()[pathComponents[i]].type);
if (i === pathComponents.length - 1) {
return type;
} else {
if (!isObjectType(type)) {
throw `Found type ${type.name} for component ${pathComponents[i]} of ${path}, expected object type`;
}
descendantType = type as GraphQLObjectType;
}
}
return descendantType;
}

static isNumericType(fieldType: GraphQLNamedType): boolean {
return isScalarType(fieldType) && (fieldType.name === 'Int' || fieldType.name === 'Float');
}
}
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,7 @@ export interface MultiValueVariable extends VariableModel {
current: TextValuePair;
options: TextValuePair[];
}

export interface RequestFactory {
request(data: string): Promise<any>;
}
11 changes: 8 additions & 3 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -1796,9 +1796,9 @@
integrity sha512-3c+yGKvVP5Y9TYBEibGNR+kLtijnj7mYrXRg+WpFb2X9xm04g/DXYkfg4hmzJQosc9snFNUPkbYIhu+KAm6jJw==

"@types/lodash@^4.14.144":
version "4.14.167"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.167.tgz#ce7d78553e3c886d4ea643c37ec7edc20f16765e"
integrity sha512-w7tQPjARrvdeBkX/Rwg95S592JwxqOjmms3zWQ0XZgSyxSLdzWaYH3vErBhdVS/lRBX7F8aBYcYJYTr5TMGOzw==
version "4.14.170"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.170.tgz#0d67711d4bf7f4ca5147e9091b847479b87925d6"
integrity sha512-bpcvu/MKHHeYX+qeEN8GE7DIravODWdACVA1ctevD8CN24RhPZIKMn9ntfAsrvLfSX3cR5RrBKAbYm9bGs0A+Q==

"@types/mime@*":
version "2.0.3"
Expand Down Expand Up @@ -5786,6 +5786,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.15, graceful-fs@^4.1.2, graceful-fs@^4.1.6
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.4.tgz#2256bde14d3632958c465ebc96dc467ca07a29fb"
integrity sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==

graphql@^15.5.0:
version "15.5.0"
resolved "https://registry.yarnpkg.com/graphql/-/graphql-15.5.0.tgz#39d19494dbe69d1ea719915b578bf920344a69d5"
integrity sha512-OmaM7y0kaK31NKG31q4YbD2beNYa6jBBKtMFT6gLYJljHLJr42IqJ8KX08u3Li/0ifzTU5HjmoOOrwa5BRLeDA==

growly@^1.3.0:
version "1.3.0"
resolved "https://registry.yarnpkg.com/growly/-/growly-1.3.0.tgz#f10748cbe76af964b7c96c93c6bcc28af120c081"
Expand Down