guard.ts 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. import { ComponentType } from 'react';
  2. import { Observable } from 'rxjs';
  3. import {
  4. CustomVariableSupport,
  5. DataQuery,
  6. DataQueryRequest,
  7. DataQueryResponse,
  8. DataSourceApi,
  9. DataSourceJsonData,
  10. DataSourceRef,
  11. MetricFindValue,
  12. StandardVariableQuery,
  13. StandardVariableSupport,
  14. VariableModel,
  15. VariableSupportType,
  16. } from '@grafana/data';
  17. import { LEGACY_VARIABLE_QUERY_EDITOR_NAME } from './editor/LegacyVariableQueryEditor';
  18. import {
  19. AdHocVariableModel,
  20. ConstantVariableModel,
  21. QueryVariableModel,
  22. VariableQueryEditorType,
  23. VariableQueryEditorProps,
  24. VariableWithMultiSupport,
  25. VariableWithOptions,
  26. } from './types';
  27. export const isQuery = (model: VariableModel): model is QueryVariableModel => {
  28. return model.type === 'query';
  29. };
  30. export const isAdHoc = (model: VariableModel): model is AdHocVariableModel => {
  31. return model.type === 'adhoc';
  32. };
  33. export const isConstant = (model: VariableModel): model is ConstantVariableModel => {
  34. return model.type === 'constant';
  35. };
  36. export const isMulti = (model: VariableModel): model is VariableWithMultiSupport => {
  37. const withMulti = model as VariableWithMultiSupport;
  38. return withMulti.hasOwnProperty('multi') && typeof withMulti.multi === 'boolean';
  39. };
  40. export const hasOptions = (model: VariableModel): model is VariableWithOptions => {
  41. return hasObjectProperty(model, 'options');
  42. };
  43. export const hasCurrent = (model: VariableModel): model is VariableWithOptions => {
  44. return hasObjectProperty(model, 'current');
  45. };
  46. function hasObjectProperty(model: VariableModel, property: string): model is VariableWithOptions {
  47. if (!model) {
  48. return false;
  49. }
  50. const withProperty = model as Record<string, any>;
  51. return withProperty.hasOwnProperty(property) && typeof withProperty[property] === 'object';
  52. }
  53. export function isLegacyAdHocDataSource(datasource: null | DataSourceRef | string): datasource is string {
  54. if (datasource === null) {
  55. return false;
  56. }
  57. return typeof datasource === 'string';
  58. }
  59. interface DataSourceWithLegacyVariableSupport<
  60. TQuery extends DataQuery = DataQuery,
  61. TOptions extends DataSourceJsonData = DataSourceJsonData
  62. > extends DataSourceApi<TQuery, TOptions> {
  63. metricFindQuery(query: any, options?: any): Promise<MetricFindValue[]>;
  64. variables: undefined;
  65. }
  66. interface DataSourceWithStandardVariableSupport<
  67. TQuery extends DataQuery = DataQuery,
  68. TOptions extends DataSourceJsonData = DataSourceJsonData
  69. > extends DataSourceApi<TQuery, TOptions> {
  70. variables: {
  71. getType(): VariableSupportType;
  72. toDataQuery(query: StandardVariableQuery): TQuery;
  73. query(request: DataQueryRequest<TQuery>): Observable<DataQueryResponse>;
  74. };
  75. }
  76. interface DataSourceWithCustomVariableSupport<
  77. VariableQuery extends DataQuery = any,
  78. TQuery extends DataQuery = DataQuery,
  79. TOptions extends DataSourceJsonData = DataSourceJsonData
  80. > extends DataSourceApi<TQuery, TOptions> {
  81. variables: {
  82. getType(): VariableSupportType;
  83. editor: VariableQueryEditorType;
  84. query(request: DataQueryRequest<TQuery>): Observable<DataQueryResponse>;
  85. };
  86. }
  87. interface DataSourceWithDatasourceVariableSupport<
  88. TQuery extends DataQuery = DataQuery,
  89. TOptions extends DataSourceJsonData = DataSourceJsonData
  90. > extends DataSourceApi<TQuery, TOptions> {
  91. variables: {
  92. getType(): VariableSupportType;
  93. };
  94. }
  95. /*
  96. * The following guard function are both TypeScript type guards.
  97. * They also make the basis for the logic used by variableQueryRunner and determining which QueryEditor to use
  98. * */
  99. export const hasLegacyVariableSupport = <
  100. TQuery extends DataQuery = DataQuery,
  101. TOptions extends DataSourceJsonData = DataSourceJsonData
  102. >(
  103. datasource: DataSourceApi<TQuery, TOptions>
  104. ): datasource is DataSourceWithLegacyVariableSupport<TQuery, TOptions> => {
  105. return Boolean(datasource.metricFindQuery) && !Boolean(datasource.variables);
  106. };
  107. export const hasStandardVariableSupport = <
  108. TQuery extends DataQuery = DataQuery,
  109. TOptions extends DataSourceJsonData = DataSourceJsonData
  110. >(
  111. datasource: DataSourceApi<TQuery, TOptions>
  112. ): datasource is DataSourceWithStandardVariableSupport<TQuery, TOptions> => {
  113. if (!datasource.variables) {
  114. return false;
  115. }
  116. if (datasource.variables.getType() !== VariableSupportType.Standard) {
  117. return false;
  118. }
  119. const variableSupport = datasource.variables as StandardVariableSupport<DataSourceApi<TQuery, TOptions>>;
  120. return Boolean(variableSupport.toDataQuery);
  121. };
  122. export const hasCustomVariableSupport = <
  123. TQuery extends DataQuery = DataQuery,
  124. TOptions extends DataSourceJsonData = DataSourceJsonData
  125. >(
  126. datasource: DataSourceApi<TQuery, TOptions>
  127. ): datasource is DataSourceWithCustomVariableSupport<any, TQuery, TOptions> => {
  128. if (!datasource.variables) {
  129. return false;
  130. }
  131. if (datasource.variables.getType() !== VariableSupportType.Custom) {
  132. return false;
  133. }
  134. const variableSupport = datasource.variables as CustomVariableSupport<DataSourceApi<TQuery, TOptions>>;
  135. return Boolean(variableSupport.query) && Boolean(variableSupport.editor);
  136. };
  137. export const hasDatasourceVariableSupport = <
  138. TQuery extends DataQuery = DataQuery,
  139. TOptions extends DataSourceJsonData = DataSourceJsonData
  140. >(
  141. datasource: DataSourceApi<TQuery, TOptions>
  142. ): datasource is DataSourceWithDatasourceVariableSupport<TQuery, TOptions> => {
  143. if (!datasource.variables) {
  144. return false;
  145. }
  146. return datasource.variables.getType() === VariableSupportType.Datasource;
  147. };
  148. export function isLegacyQueryEditor<
  149. TQuery extends DataQuery = DataQuery,
  150. TOptions extends DataSourceJsonData = DataSourceJsonData
  151. >(
  152. component: VariableQueryEditorType,
  153. datasource: DataSourceApi<TQuery, TOptions>
  154. ): component is ComponentType<VariableQueryEditorProps> {
  155. if (!component) {
  156. return false;
  157. }
  158. return component.displayName === LEGACY_VARIABLE_QUERY_EDITOR_NAME || hasLegacyVariableSupport(datasource);
  159. }
  160. export function isQueryEditor<
  161. TQuery extends DataQuery = DataQuery,
  162. TOptions extends DataSourceJsonData = DataSourceJsonData
  163. >(
  164. component: VariableQueryEditorType,
  165. datasource: DataSourceApi<TQuery, TOptions>
  166. ): component is VariableQueryEditorType {
  167. if (!component) {
  168. return false;
  169. }
  170. return (
  171. component.displayName !== LEGACY_VARIABLE_QUERY_EDITOR_NAME &&
  172. (hasDatasourceVariableSupport(datasource) ||
  173. hasStandardVariableSupport(datasource) ||
  174. hasCustomVariableSupport(datasource))
  175. );
  176. }