@backstage-community/plugin-splunk-on-call 0.18.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @backstage-community/plugin-splunk-on-call
2
2
 
3
+ ## 0.20.0
4
+
5
+ ### Minor Changes
6
+
7
+ - bb7860e: Backstage version bump to v1.48.2
8
+
9
+ ### Patch Changes
10
+
11
+ - 4dfd773: Use Backstage Frontend Fetch API
12
+
13
+ ## 0.19.0
14
+
15
+ ### Minor Changes
16
+
17
+ - 08de926: Migrate splunk plugin to the new frontend system
18
+
3
19
  ## 0.18.0
4
20
 
5
21
  ### Minor Changes
package/README.md CHANGED
@@ -44,6 +44,12 @@ const overviewContent = (
44
44
  </EntitySwitch>
45
45
  ```
46
46
 
47
+ ### New frontend system
48
+
49
+ If you are using the new frontend system, import the plugin from
50
+ `@backstage-community/plugin-splunk-on-call/alpha` and add the
51
+ `splunkOnCallPage` and `entitySplunkOnCallCard` extensions to your app.
52
+
47
53
  ### `readOnly` mode
48
54
 
49
55
  To suppress the rendering of the actionable create-acknowledge-resolve incident buttons and UI controls, the `EntitySplunkOnCallCard` can also be instantiated in `readOnly` mode:
@@ -66,6 +72,20 @@ splunkOnCall:
66
72
  eventsRestEndpoint: <SPLUNK_ON_CALL_REST_ENDPOINT>
67
73
  ```
68
74
 
75
+ You can also point `eventsRestEndpoint` at the Backstage proxy by using a relative path. This keeps the REST endpoint off the frontend and allows the proxy to enforce auth policies:
76
+
77
+ ```yaml
78
+ splunkOnCall:
79
+ eventsRestEndpoint: /splunk-on-call-events
80
+ ```
81
+
82
+ ```yaml
83
+ proxy:
84
+ '/splunk-on-call-events':
85
+ target: https://alert.victorops.com/integrations/generic/20131114/alert
86
+ allowedMethods: ['POST']
87
+ ```
88
+
69
89
  In order to make the API calls, you need to provide a new proxy config which will redirect to the Splunk On-Call API endpoint and add authentication information in the headers:
70
90
 
71
91
  ```yaml
@@ -81,7 +101,7 @@ proxy:
81
101
 
82
102
  In addition, to make certain API calls (trigger-resolve-acknowledge an incident) you need to add the `PATCH` method to the backend `cors` methods list: `[GET, POST, PUT, DELETE, PATCH]`.
83
103
 
84
- **WARNING**: In current implementation, the Splunk OnCall plugin requires the `/splunk-on-call` proxy endpoint be exposed by the Backstage backend as an unprotected endpoint, in effect enabling Splunk OnCall API access using the configured `SPLUNK_ON_CALL_API_KEY` for any user or process with access to the `/splunk-on-call` Backstage backend endpoint. See below for further configuration options enabling protection of this endpoint. If you regard this as problematic, consider using the plugin in `readOnly` mode (`<EntitySplunkOnCallCard readOnly />`) using the following proxy configuration:
104
+ **NOTE**: The Splunk On-Call frontend uses Backstage's authenticated fetch, so you can keep the `/splunk-on-call` proxy endpoint protected by your backend auth policy. If you only want read-only access, you can also restrict the proxy to `GET` using the following configuration:
85
105
 
86
106
  ```yaml
87
107
  proxy:
package/config.d.ts CHANGED
@@ -19,6 +19,9 @@ export interface Config {
19
19
  */
20
20
  splunkOnCall?: {
21
21
  /**
22
+ * Base REST endpoint used for incident actions. Can be an absolute URL or
23
+ * a proxy path (for example, `/splunk-on-call-events`).
24
+ *
22
25
  * @visibility frontend
23
26
  */
24
27
  eventsRestEndpoint?: string;
@@ -0,0 +1,18 @@
1
+ import { ApiBlueprint, discoveryApiRef, configApiRef, fetchApiRef } from '@backstage/frontend-plugin-api';
2
+ import { splunkOnCallApiRef, SplunkOnCallClient } from '../api/client.esm.js';
3
+
4
+ const splunkOnCallApi = ApiBlueprint.make({
5
+ name: "splunk-on-call",
6
+ params: (defineParams) => defineParams({
7
+ api: splunkOnCallApiRef,
8
+ deps: {
9
+ discoveryApi: discoveryApiRef,
10
+ configApi: configApiRef,
11
+ fetchApi: fetchApiRef
12
+ },
13
+ factory: ({ configApi, discoveryApi, fetchApi }) => SplunkOnCallClient.fromConfig(configApi, discoveryApi, fetchApi)
14
+ })
15
+ });
16
+
17
+ export { splunkOnCallApi };
18
+ //# sourceMappingURL=apis.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"apis.esm.js","sources":["../../src/alpha/apis.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n ApiBlueprint,\n configApiRef,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { SplunkOnCallClient, splunkOnCallApiRef } from '../api';\n\n/**\n * @alpha\n */\nexport const splunkOnCallApi = ApiBlueprint.make({\n name: 'splunk-on-call',\n params: defineParams =>\n defineParams({\n api: splunkOnCallApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n configApi: configApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n SplunkOnCallClient.fromConfig(configApi, discoveryApi, fetchApi),\n }),\n});\n"],"names":[],"mappings":";;;AA0Ba,MAAA,eAAA,GAAkB,aAAa,IAAK,CAAA;AAAA,EAC/C,IAAM,EAAA,gBAAA;AAAA,EACN,MAAA,EAAQ,kBACN,YAAa,CAAA;AAAA,IACX,GAAK,EAAA,kBAAA;AAAA,IACL,IAAM,EAAA;AAAA,MACJ,YAAc,EAAA,eAAA;AAAA,MACd,SAAW,EAAA,YAAA;AAAA,MACX,QAAU,EAAA;AAAA,KACZ;AAAA,IACA,OAAA,EAAS,CAAC,EAAE,SAAW,EAAA,YAAA,EAAc,QAAS,EAAA,KAC5C,kBAAmB,CAAA,UAAA,CAAW,SAAW,EAAA,YAAA,EAAc,QAAQ;AAAA,GAClE;AACL,CAAC;;;;"}
@@ -0,0 +1,17 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { compatWrapper } from '@backstage/core-compat-api';
3
+ import { EntityCardBlueprint } from '@backstage/plugin-catalog-react/alpha';
4
+ import { isSplunkOnCallAvailable } from '../components/EntitySplunkOnCallCard.esm.js';
5
+
6
+ const entitySplunkOnCallCard = EntityCardBlueprint.make({
7
+ name: "splunk-on-call",
8
+ params: {
9
+ filter: isSplunkOnCallAvailable,
10
+ loader: () => import('../components/EntitySplunkOnCallCard.esm.js').then(
11
+ (m) => compatWrapper(/* @__PURE__ */ jsx(m.EntitySplunkOnCallCard, {}))
12
+ )
13
+ }
14
+ });
15
+
16
+ export { entitySplunkOnCallCard };
17
+ //# sourceMappingURL=entityCard.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"entityCard.esm.js","sources":["../../src/alpha/entityCard.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { compatWrapper } from '@backstage/core-compat-api';\nimport { EntityCardBlueprint } from '@backstage/plugin-catalog-react/alpha';\nimport { isSplunkOnCallAvailable } from '../components';\n\n/**\n * @alpha\n */\nexport const entitySplunkOnCallCard = EntityCardBlueprint.make({\n name: 'splunk-on-call',\n params: {\n filter: isSplunkOnCallAvailable,\n loader: () =>\n import('../components/EntitySplunkOnCallCard').then(m =>\n compatWrapper(<m.EntitySplunkOnCallCard />),\n ),\n },\n});\n"],"names":[],"mappings":";;;;;AAsBa,MAAA,sBAAA,GAAyB,oBAAoB,IAAK,CAAA;AAAA,EAC7D,IAAM,EAAA,gBAAA;AAAA,EACN,MAAQ,EAAA;AAAA,IACN,MAAQ,EAAA,uBAAA;AAAA,IACR,MAAQ,EAAA,MACN,OAAO,6CAAsC,CAAE,CAAA,IAAA;AAAA,MAAK,OAClD,aAAc,iBAAA,GAAA,CAAC,CAAE,CAAA,sBAAA,EAAF,EAAyB,CAAE;AAAA;AAC5C;AAEN,CAAC;;;;"}
@@ -0,0 +1,17 @@
1
+ import { jsx } from 'react/jsx-runtime';
2
+ import { convertLegacyRouteRef, compatWrapper } from '@backstage/core-compat-api';
3
+ import { PageBlueprint } from '@backstage/frontend-plugin-api';
4
+ import { rootRouteRef } from '../plugin.esm.js';
5
+
6
+ const splunkOnCallPage = PageBlueprint.make({
7
+ params: {
8
+ path: "/splunk-on-call",
9
+ routeRef: convertLegacyRouteRef(rootRouteRef),
10
+ loader: () => import('../components/SplunkOnCallPage.esm.js').then(
11
+ (m) => compatWrapper(/* @__PURE__ */ jsx(m.SplunkOnCallPage, {}))
12
+ )
13
+ }
14
+ });
15
+
16
+ export { splunkOnCallPage };
17
+ //# sourceMappingURL=page.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page.esm.js","sources":["../../src/alpha/page.tsx"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n compatWrapper,\n convertLegacyRouteRef,\n} from '@backstage/core-compat-api';\nimport { PageBlueprint } from '@backstage/frontend-plugin-api';\nimport { rootRouteRef } from '../plugin';\n\n/**\n * @alpha\n */\nexport const splunkOnCallPage = PageBlueprint.make({\n params: {\n path: '/splunk-on-call',\n routeRef: convertLegacyRouteRef(rootRouteRef),\n loader: () =>\n import('../components/SplunkOnCallPage').then(m =>\n compatWrapper(<m.SplunkOnCallPage />),\n ),\n },\n});\n"],"names":[],"mappings":";;;;;AAyBa,MAAA,gBAAA,GAAmB,cAAc,IAAK,CAAA;AAAA,EACjD,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA,iBAAA;AAAA,IACN,QAAA,EAAU,sBAAsB,YAAY,CAAA;AAAA,IAC5C,MAAQ,EAAA,MACN,OAAO,uCAAgC,CAAE,CAAA,IAAA;AAAA,MAAK,OAC5C,aAAc,iBAAA,GAAA,CAAC,CAAE,CAAA,gBAAA,EAAF,EAAmB,CAAE;AAAA;AACtC;AAEN,CAAC;;;;"}
@@ -0,0 +1,93 @@
1
+ /// <reference types="react" />
2
+ import * as _backstage_plugin_catalog_react_alpha from '@backstage/plugin-catalog-react/alpha';
3
+ import * as _backstage_catalog_model from '@backstage/catalog-model';
4
+ import * as react from 'react';
5
+ import * as _backstage_filter_predicates from '@backstage/filter-predicates';
6
+ import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
7
+
8
+ /**
9
+ * @alpha
10
+ */
11
+ declare const _default: _backstage_frontend_plugin_api.OverridableFrontendPlugin<{
12
+ root: _backstage_frontend_plugin_api.RouteRef<undefined>;
13
+ }, {}, {
14
+ "api:splunk-on-call/splunk-on-call": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
15
+ kind: "api";
16
+ name: "splunk-on-call";
17
+ config: {};
18
+ configInput: {};
19
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.AnyApiFactory, "core.api.factory", {}>;
20
+ inputs: {};
21
+ params: <TApi, TImpl extends TApi, TDeps extends {
22
+ [x: string]: unknown;
23
+ }>(params: _backstage_frontend_plugin_api.ApiFactory<TApi, TImpl, TDeps>) => _backstage_frontend_plugin_api.ExtensionBlueprintParams<_backstage_frontend_plugin_api.AnyApiFactory>;
24
+ }>;
25
+ "entity-card:splunk-on-call/splunk-on-call": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
26
+ kind: "entity-card";
27
+ name: "splunk-on-call";
28
+ config: {
29
+ filter: _backstage_filter_predicates.FilterPredicate | undefined;
30
+ type: "content" | "info" | undefined;
31
+ };
32
+ configInput: {
33
+ filter?: _backstage_filter_predicates.FilterPredicate | undefined;
34
+ type?: "content" | "info" | undefined;
35
+ };
36
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<(entity: _backstage_catalog_model.Entity) => boolean, "catalog.entity-filter-function", {
37
+ optional: true;
38
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "catalog.entity-filter-expression", {
39
+ optional: true;
40
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_plugin_catalog_react_alpha.EntityCardType, "catalog.entity-card-type", {
41
+ optional: true;
42
+ }>;
43
+ inputs: {};
44
+ params: {
45
+ loader: () => Promise<JSX.Element>;
46
+ filter?: _backstage_filter_predicates.FilterPredicate | ((entity: _backstage_catalog_model.Entity) => boolean) | undefined;
47
+ type?: _backstage_plugin_catalog_react_alpha.EntityCardType | undefined;
48
+ };
49
+ }>;
50
+ "page:splunk-on-call": _backstage_frontend_plugin_api.OverridableExtensionDefinition<{
51
+ kind: "page";
52
+ name: undefined;
53
+ config: {
54
+ path: string | undefined;
55
+ title: string | undefined;
56
+ };
57
+ configInput: {
58
+ title?: string | undefined;
59
+ path?: string | undefined;
60
+ };
61
+ output: _backstage_frontend_plugin_api.ExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
62
+ optional: true;
63
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<string, "core.title", {
64
+ optional: true;
65
+ }> | _backstage_frontend_plugin_api.ExtensionDataRef<_backstage_frontend_plugin_api.IconElement, "core.icon", {
66
+ optional: true;
67
+ }>;
68
+ inputs: {
69
+ pages: _backstage_frontend_plugin_api.ExtensionInput<_backstage_frontend_plugin_api.ConfigurableExtensionDataRef<react.JSX.Element, "core.reactElement", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.routing.path", {}> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams>, "core.routing.ref", {
70
+ optional: true;
71
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<string, "core.title", {
72
+ optional: true;
73
+ }> | _backstage_frontend_plugin_api.ConfigurableExtensionDataRef<_backstage_frontend_plugin_api.IconElement, "core.icon", {
74
+ optional: true;
75
+ }>, {
76
+ singleton: false;
77
+ optional: false;
78
+ internal: false;
79
+ }>;
80
+ };
81
+ params: {
82
+ defaultPath?: [Error: "Use the 'path' param instead"] | undefined;
83
+ path: string;
84
+ title?: string | undefined;
85
+ icon?: _backstage_frontend_plugin_api.IconElement | undefined;
86
+ loader?: (() => Promise<react.JSX.Element>) | undefined;
87
+ routeRef?: _backstage_frontend_plugin_api.RouteRef<_backstage_frontend_plugin_api.AnyRouteRefParams> | undefined;
88
+ noHeader?: boolean | undefined;
89
+ };
90
+ }>;
91
+ }>;
92
+
93
+ export { _default as default };
@@ -0,0 +1,17 @@
1
+ import { convertLegacyRouteRefs } from '@backstage/core-compat-api';
2
+ import { createFrontendPlugin } from '@backstage/frontend-plugin-api';
3
+ import { splunkOnCallApi } from './alpha/apis.esm.js';
4
+ import { entitySplunkOnCallCard } from './alpha/entityCard.esm.js';
5
+ import { splunkOnCallPage } from './alpha/page.esm.js';
6
+ import { rootRouteRef } from './plugin.esm.js';
7
+
8
+ var alpha = createFrontendPlugin({
9
+ pluginId: "splunk-on-call",
10
+ routes: convertLegacyRouteRefs({
11
+ root: rootRouteRef
12
+ }),
13
+ extensions: [splunkOnCallApi, splunkOnCallPage, entitySplunkOnCallCard]
14
+ });
15
+
16
+ export { alpha as default };
17
+ //# sourceMappingURL=alpha.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alpha.esm.js","sources":["../src/alpha.ts"],"sourcesContent":["/*\n * Copyright 2025 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { convertLegacyRouteRefs } from '@backstage/core-compat-api';\nimport { createFrontendPlugin } from '@backstage/frontend-plugin-api';\nimport {\n entitySplunkOnCallCard,\n splunkOnCallApi,\n splunkOnCallPage,\n} from './alpha/index';\nimport { rootRouteRef } from './plugin';\n\n/**\n * @alpha\n */\nexport default createFrontendPlugin({\n pluginId: 'splunk-on-call',\n routes: convertLegacyRouteRefs({\n root: rootRouteRef,\n }),\n extensions: [splunkOnCallApi, splunkOnCallPage, entitySplunkOnCallCard],\n});\n"],"names":[],"mappings":";;;;;;;AA2BA,YAAe,oBAAqB,CAAA;AAAA,EAClC,QAAU,EAAA,gBAAA;AAAA,EACV,QAAQ,sBAAuB,CAAA;AAAA,IAC7B,IAAM,EAAA;AAAA,GACP,CAAA;AAAA,EACD,UAAY,EAAA,CAAC,eAAiB,EAAA,gBAAA,EAAkB,sBAAsB;AACxE,CAAC,CAAA;;;;"}
@@ -2,6 +2,8 @@ import { createApiRef } from '@backstage/core-plugin-api';
2
2
 
3
3
  class UnauthorizedError extends Error {
4
4
  }
5
+ class MissingEventsRestEndpointError extends Error {
6
+ }
5
7
  const splunkOnCallApiRef = createApiRef({
6
8
  id: "plugin.splunk-on-call.api"
7
9
  });
@@ -9,11 +11,12 @@ class SplunkOnCallClient {
9
11
  constructor(config) {
10
12
  this.config = config;
11
13
  }
12
- static fromConfig(configApi, discoveryApi) {
14
+ static fromConfig(configApi, discoveryApi, fetchApi) {
13
15
  const eventsRestEndpoint = configApi.getOptionalString("splunkOnCall.eventsRestEndpoint") || null;
14
16
  return new SplunkOnCallClient({
15
17
  eventsRestEndpoint,
16
- discoveryApi
18
+ discoveryApi,
19
+ fetchApi
17
20
  });
18
21
  }
19
22
  async getIncidents() {
@@ -82,7 +85,13 @@ class SplunkOnCallClient {
82
85
  },
83
86
  body
84
87
  };
85
- const url = `${this.config.eventsRestEndpoint}/${routingKey}`;
88
+ const eventsRestEndpoint = await this.getEventsRestEndpoint();
89
+ if (!eventsRestEndpoint) {
90
+ throw new MissingEventsRestEndpointError(
91
+ "Splunk On-Call REST endpoint is not configured."
92
+ );
93
+ }
94
+ const url = `${eventsRestEndpoint}/${routingKey}`;
86
95
  return this.request(url, request);
87
96
  }
88
97
  async findByUrl(url) {
@@ -96,7 +105,7 @@ class SplunkOnCallClient {
96
105
  return response.json();
97
106
  }
98
107
  async request(url, options) {
99
- const response = await fetch(url, options);
108
+ const response = await this.config.fetchApi.fetch(url, options);
100
109
  if (response.status === 403) {
101
110
  throw new UnauthorizedError();
102
111
  }
@@ -108,7 +117,17 @@ class SplunkOnCallClient {
108
117
  }
109
118
  return response;
110
119
  }
120
+ async getEventsRestEndpoint() {
121
+ if (!this.config.eventsRestEndpoint) {
122
+ return null;
123
+ }
124
+ if (this.config.eventsRestEndpoint.startsWith("/")) {
125
+ const proxyBase = await this.config.discoveryApi.getBaseUrl("proxy");
126
+ return `${proxyBase}${this.config.eventsRestEndpoint}`;
127
+ }
128
+ return this.config.eventsRestEndpoint;
129
+ }
111
130
  }
112
131
 
113
- export { SplunkOnCallClient, UnauthorizedError, splunkOnCallApiRef };
132
+ export { MissingEventsRestEndpointError, SplunkOnCallClient, UnauthorizedError, splunkOnCallApiRef };
114
133
  //# sourceMappingURL=client.esm.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.esm.js","sources":["../../src/api/client.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Incident,\n OnCall,\n User,\n EscalationPolicyInfo,\n RoutingKey,\n Team,\n} from '../components/types';\nimport {\n SplunkOnCallApi,\n TriggerAlarmRequest,\n IncidentsResponse,\n OnCallsResponse,\n ClientApiConfig,\n RequestOptions,\n ListUserResponse,\n EscalationPolicyResponse,\n ListRoutingKeyResponse,\n} from './types';\nimport {\n createApiRef,\n DiscoveryApi,\n ConfigApi,\n} from '@backstage/core-plugin-api';\n\n/** @public */\nexport class UnauthorizedError extends Error {}\n\n/** @public */\nexport const splunkOnCallApiRef = createApiRef<SplunkOnCallApi>({\n id: 'plugin.splunk-on-call.api',\n});\n\n/** @public */\nexport class SplunkOnCallClient implements SplunkOnCallApi {\n static fromConfig(configApi: ConfigApi, discoveryApi: DiscoveryApi) {\n const eventsRestEndpoint: string | null =\n configApi.getOptionalString('splunkOnCall.eventsRestEndpoint') || null;\n return new SplunkOnCallClient({\n eventsRestEndpoint,\n discoveryApi,\n });\n }\n constructor(private readonly config: ClientApiConfig) {}\n\n async getIncidents(): Promise<Incident[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/incidents`;\n\n const { incidents } = await this.findByUrl<IncidentsResponse>(url);\n\n return incidents;\n }\n\n async getOnCallUsers(): Promise<OnCall[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/oncall/current`;\n const { teamsOnCall } = await this.findByUrl<OnCallsResponse>(url);\n\n return teamsOnCall;\n }\n\n async getTeams(): Promise<Team[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/team`;\n const teams = await this.findByUrl<Team[]>(url);\n\n return teams;\n }\n\n async getRoutingKeys(): Promise<RoutingKey[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/org/routing-keys`;\n const { routingKeys } = await this.findByUrl<ListRoutingKeyResponse>(url);\n\n return routingKeys;\n }\n\n async getUsers(): Promise<User[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v2/user`;\n const { users } = await this.findByUrl<ListUserResponse>(url);\n\n return users;\n }\n\n async getEscalationPolicies(): Promise<EscalationPolicyInfo[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/policies`;\n const { policies } = await this.findByUrl<EscalationPolicyResponse>(url);\n\n return policies;\n }\n\n async incidentAction(options: TriggerAlarmRequest): Promise<Response> {\n const {\n routingKey,\n incidentType,\n incidentId,\n incidentDisplayName,\n incidentMessage,\n incidentStartTime,\n } = options;\n\n const body = JSON.stringify({\n message_type: incidentType,\n ...(incidentId ? { entity_id: incidentId } : {}),\n ...(incidentDisplayName\n ? { entity_display_name: incidentDisplayName }\n : {}),\n ...(incidentMessage ? { state_message: incidentMessage } : {}),\n ...(incidentStartTime ? { state_start_time: incidentStartTime } : {}),\n });\n\n const request = {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body,\n };\n\n const url = `${this.config.eventsRestEndpoint}/${routingKey}`;\n\n return this.request(url, request);\n }\n\n private async findByUrl<T>(url: string): Promise<T> {\n const options = {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n const response = await this.request(url, options);\n\n return response.json();\n }\n\n private async request(\n url: string,\n options: RequestOptions,\n ): Promise<Response> {\n const response = await fetch(url, options);\n if (response.status === 403) {\n throw new UnauthorizedError();\n }\n if (!response.ok) {\n const payload = await response.json();\n const errors = payload.errors.map((error: string) => error).join(' ');\n const message = `Request failed with ${response.status}, ${errors}`;\n throw new Error(message);\n }\n return response;\n }\n}\n"],"names":[],"mappings":";;AA0CO,MAAM,0BAA0B,KAAM,CAAA;AAAC;AAGvC,MAAM,qBAAqB,YAA8B,CAAA;AAAA,EAC9D,EAAI,EAAA;AACN,CAAC;AAGM,MAAM,kBAA8C,CAAA;AAAA,EASzD,YAA6B,MAAyB,EAAA;AAAzB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA;AAA0B,EARvD,OAAO,UAAW,CAAA,SAAA,EAAsB,YAA4B,EAAA;AAClE,IAAA,MAAM,kBACJ,GAAA,SAAA,CAAU,iBAAkB,CAAA,iCAAiC,CAAK,IAAA,IAAA;AACpE,IAAA,OAAO,IAAI,kBAAmB,CAAA;AAAA,MAC5B,kBAAA;AAAA,MACA;AAAA,KACD,CAAA;AAAA;AACH,EAGA,MAAM,YAAoC,GAAA;AACxC,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAa,CAAA,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,4BAAA,CAAA;AAED,IAAA,MAAM,EAAE,SAAU,EAAA,GAAI,MAAM,IAAA,CAAK,UAA6B,GAAG,CAAA;AAEjE,IAAO,OAAA,SAAA;AAAA;AACT,EAEA,MAAM,cAAoC,GAAA;AACxC,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAa,CAAA,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,iCAAA,CAAA;AACD,IAAA,MAAM,EAAE,WAAY,EAAA,GAAI,MAAM,IAAA,CAAK,UAA2B,GAAG,CAAA;AAEjE,IAAO,OAAA,WAAA;AAAA;AACT,EAEA,MAAM,QAA4B,GAAA;AAChC,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAa,CAAA,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,uBAAA,CAAA;AACD,IAAA,MAAM,KAAQ,GAAA,MAAM,IAAK,CAAA,SAAA,CAAkB,GAAG,CAAA;AAE9C,IAAO,OAAA,KAAA;AAAA;AACT,EAEA,MAAM,cAAwC,GAAA;AAC5C,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAa,CAAA,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,mCAAA,CAAA;AACD,IAAA,MAAM,EAAE,WAAY,EAAA,GAAI,MAAM,IAAA,CAAK,UAAkC,GAAG,CAAA;AAExE,IAAO,OAAA,WAAA;AAAA;AACT,EAEA,MAAM,QAA4B,GAAA;AAChC,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAa,CAAA,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,uBAAA,CAAA;AACD,IAAA,MAAM,EAAE,KAAM,EAAA,GAAI,MAAM,IAAA,CAAK,UAA4B,GAAG,CAAA;AAE5D,IAAO,OAAA,KAAA;AAAA;AACT,EAEA,MAAM,qBAAyD,GAAA;AAC7D,IAAA,MAAM,GAAM,GAAA,CAAA,EAAG,MAAM,IAAA,CAAK,OAAO,YAAa,CAAA,UAAA;AAAA,MAC5C;AAAA,KACD,CAAA,2BAAA,CAAA;AACD,IAAA,MAAM,EAAE,QAAS,EAAA,GAAI,MAAM,IAAA,CAAK,UAAoC,GAAG,CAAA;AAEvE,IAAO,OAAA,QAAA;AAAA;AACT,EAEA,MAAM,eAAe,OAAiD,EAAA;AACpE,IAAM,MAAA;AAAA,MACJ,UAAA;AAAA,MACA,YAAA;AAAA,MACA,UAAA;AAAA,MACA,mBAAA;AAAA,MACA,eAAA;AAAA,MACA;AAAA,KACE,GAAA,OAAA;AAEJ,IAAM,MAAA,IAAA,GAAO,KAAK,SAAU,CAAA;AAAA,MAC1B,YAAc,EAAA,YAAA;AAAA,MACd,GAAI,UAAa,GAAA,EAAE,SAAW,EAAA,UAAA,KAAe,EAAC;AAAA,MAC9C,GAAI,mBACA,GAAA,EAAE,mBAAqB,EAAA,mBAAA,KACvB,EAAC;AAAA,MACL,GAAI,eAAkB,GAAA,EAAE,aAAe,EAAA,eAAA,KAAoB,EAAC;AAAA,MAC5D,GAAI,iBAAoB,GAAA,EAAE,gBAAkB,EAAA,iBAAA,KAAsB;AAAC,KACpE,CAAA;AAED,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,MAAQ,EAAA,MAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,MAAQ,EAAA,kBAAA;AAAA,QACR,cAAgB,EAAA;AAAA,OAClB;AAAA,MACA;AAAA,KACF;AAEA,IAAA,MAAM,MAAM,CAAG,EAAA,IAAA,CAAK,MAAO,CAAA,kBAAkB,IAAI,UAAU,CAAA,CAAA;AAE3D,IAAO,OAAA,IAAA,CAAK,OAAQ,CAAA,GAAA,EAAK,OAAO,CAAA;AAAA;AAClC,EAEA,MAAc,UAAa,GAAyB,EAAA;AAClD,IAAA,MAAM,OAAU,GAAA;AAAA,MACd,MAAQ,EAAA,KAAA;AAAA,MACR,OAAS,EAAA;AAAA,QACP,cAAgB,EAAA;AAAA;AAClB,KACF;AACA,IAAA,MAAM,QAAW,GAAA,MAAM,IAAK,CAAA,OAAA,CAAQ,KAAK,OAAO,CAAA;AAEhD,IAAA,OAAO,SAAS,IAAK,EAAA;AAAA;AACvB,EAEA,MAAc,OACZ,CAAA,GAAA,EACA,OACmB,EAAA;AACnB,IAAA,MAAM,QAAW,GAAA,MAAM,KAAM,CAAA,GAAA,EAAK,OAAO,CAAA;AACzC,IAAI,IAAA,QAAA,CAAS,WAAW,GAAK,EAAA;AAC3B,MAAA,MAAM,IAAI,iBAAkB,EAAA;AAAA;AAE9B,IAAI,IAAA,CAAC,SAAS,EAAI,EAAA;AAChB,MAAM,MAAA,OAAA,GAAU,MAAM,QAAA,CAAS,IAAK,EAAA;AACpC,MAAM,MAAA,MAAA,GAAS,QAAQ,MAAO,CAAA,GAAA,CAAI,CAAC,KAAkB,KAAA,KAAK,CAAE,CAAA,IAAA,CAAK,GAAG,CAAA;AACpE,MAAA,MAAM,OAAU,GAAA,CAAA,oBAAA,EAAuB,QAAS,CAAA,MAAM,KAAK,MAAM,CAAA,CAAA;AACjE,MAAM,MAAA,IAAI,MAAM,OAAO,CAAA;AAAA;AAEzB,IAAO,OAAA,QAAA;AAAA;AAEX;;;;"}
1
+ {"version":3,"file":"client.esm.js","sources":["../../src/api/client.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n Incident,\n OnCall,\n User,\n EscalationPolicyInfo,\n RoutingKey,\n Team,\n} from '../components/types';\nimport {\n SplunkOnCallApi,\n TriggerAlarmRequest,\n IncidentsResponse,\n OnCallsResponse,\n ClientApiConfig,\n RequestOptions,\n ListUserResponse,\n EscalationPolicyResponse,\n ListRoutingKeyResponse,\n} from './types';\nimport {\n ConfigApi,\n DiscoveryApi,\n FetchApi,\n createApiRef,\n} from '@backstage/core-plugin-api';\n\n/** @public */\nexport class UnauthorizedError extends Error {}\n\n/** @public */\nexport class MissingEventsRestEndpointError extends Error {}\n\n/** @public */\nexport const splunkOnCallApiRef = createApiRef<SplunkOnCallApi>({\n id: 'plugin.splunk-on-call.api',\n});\n\n/** @public */\nexport class SplunkOnCallClient implements SplunkOnCallApi {\n static fromConfig(\n configApi: ConfigApi,\n discoveryApi: DiscoveryApi,\n fetchApi: FetchApi,\n ) {\n const eventsRestEndpoint: string | null =\n configApi.getOptionalString('splunkOnCall.eventsRestEndpoint') || null;\n return new SplunkOnCallClient({\n eventsRestEndpoint,\n discoveryApi,\n fetchApi,\n });\n }\n constructor(private readonly config: ClientApiConfig) {}\n\n async getIncidents(): Promise<Incident[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/incidents`;\n\n const { incidents } = await this.findByUrl<IncidentsResponse>(url);\n\n return incidents;\n }\n\n async getOnCallUsers(): Promise<OnCall[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/oncall/current`;\n const { teamsOnCall } = await this.findByUrl<OnCallsResponse>(url);\n\n return teamsOnCall;\n }\n\n async getTeams(): Promise<Team[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/team`;\n const teams = await this.findByUrl<Team[]>(url);\n\n return teams;\n }\n\n async getRoutingKeys(): Promise<RoutingKey[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/org/routing-keys`;\n const { routingKeys } = await this.findByUrl<ListRoutingKeyResponse>(url);\n\n return routingKeys;\n }\n\n async getUsers(): Promise<User[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v2/user`;\n const { users } = await this.findByUrl<ListUserResponse>(url);\n\n return users;\n }\n\n async getEscalationPolicies(): Promise<EscalationPolicyInfo[]> {\n const url = `${await this.config.discoveryApi.getBaseUrl(\n 'proxy',\n )}/splunk-on-call/v1/policies`;\n const { policies } = await this.findByUrl<EscalationPolicyResponse>(url);\n\n return policies;\n }\n\n async incidentAction(options: TriggerAlarmRequest): Promise<Response> {\n const {\n routingKey,\n incidentType,\n incidentId,\n incidentDisplayName,\n incidentMessage,\n incidentStartTime,\n } = options;\n\n const body = JSON.stringify({\n message_type: incidentType,\n ...(incidentId ? { entity_id: incidentId } : {}),\n ...(incidentDisplayName\n ? { entity_display_name: incidentDisplayName }\n : {}),\n ...(incidentMessage ? { state_message: incidentMessage } : {}),\n ...(incidentStartTime ? { state_start_time: incidentStartTime } : {}),\n });\n\n const request = {\n method: 'POST',\n headers: {\n Accept: 'application/json',\n 'Content-Type': 'application/json',\n },\n body,\n };\n\n const eventsRestEndpoint = await this.getEventsRestEndpoint();\n if (!eventsRestEndpoint) {\n throw new MissingEventsRestEndpointError(\n 'Splunk On-Call REST endpoint is not configured.',\n );\n }\n const url = `${eventsRestEndpoint}/${routingKey}`;\n\n return this.request(url, request);\n }\n\n private async findByUrl<T>(url: string): Promise<T> {\n const options = {\n method: 'GET',\n headers: {\n 'Content-Type': 'application/json',\n },\n };\n const response = await this.request(url, options);\n\n return response.json();\n }\n\n private async request(\n url: string,\n options: RequestOptions,\n ): Promise<Response> {\n const response = await this.config.fetchApi.fetch(url, options);\n if (response.status === 403) {\n throw new UnauthorizedError();\n }\n if (!response.ok) {\n const payload = await response.json();\n const errors = payload.errors.map((error: string) => error).join(' ');\n const message = `Request failed with ${response.status}, ${errors}`;\n throw new Error(message);\n }\n return response;\n }\n\n private async getEventsRestEndpoint(): Promise<string | null> {\n if (!this.config.eventsRestEndpoint) {\n return null;\n }\n\n if (this.config.eventsRestEndpoint.startsWith('/')) {\n const proxyBase = await this.config.discoveryApi.getBaseUrl('proxy');\n return `${proxyBase}${this.config.eventsRestEndpoint}`;\n }\n\n return this.config.eventsRestEndpoint;\n }\n}\n"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import * as react_jsx_runtime from 'react/jsx-runtime';
3
3
  import { Entity } from '@backstage/catalog-model';
4
4
  import * as react from 'react';
5
5
  import * as _backstage_core_plugin_api from '@backstage/core-plugin-api';
6
- import { DiscoveryApi, ConfigApi } from '@backstage/core-plugin-api';
6
+ import { DiscoveryApi, FetchApi, ConfigApi } from '@backstage/core-plugin-api';
7
7
  import * as _backstage_frontend_plugin_api from '@backstage/frontend-plugin-api';
8
8
 
9
9
  /** @public */
@@ -221,6 +221,7 @@ type OnCallsResponse = {
221
221
  type ClientApiConfig = {
222
222
  eventsRestEndpoint: string | null;
223
223
  discoveryApi: DiscoveryApi;
224
+ fetchApi: FetchApi;
224
225
  };
225
226
  /** @public */
226
227
  type RequestOptions = {
@@ -233,11 +234,14 @@ type RequestOptions = {
233
234
  declare class UnauthorizedError extends Error {
234
235
  }
235
236
  /** @public */
237
+ declare class MissingEventsRestEndpointError extends Error {
238
+ }
239
+ /** @public */
236
240
  declare const splunkOnCallApiRef: _backstage_frontend_plugin_api.ApiRef<SplunkOnCallApi>;
237
241
  /** @public */
238
242
  declare class SplunkOnCallClient implements SplunkOnCallApi {
239
243
  private readonly config;
240
- static fromConfig(configApi: ConfigApi, discoveryApi: DiscoveryApi): SplunkOnCallClient;
244
+ static fromConfig(configApi: ConfigApi, discoveryApi: DiscoveryApi, fetchApi: FetchApi): SplunkOnCallClient;
241
245
  constructor(config: ClientApiConfig);
242
246
  getIncidents(): Promise<Incident[]>;
243
247
  getOnCallUsers(): Promise<OnCall[]>;
@@ -248,6 +252,7 @@ declare class SplunkOnCallClient implements SplunkOnCallApi {
248
252
  incidentAction(options: TriggerAlarmRequest): Promise<Response>;
249
253
  private findByUrl;
250
254
  private request;
255
+ private getEventsRestEndpoint;
251
256
  }
252
257
 
253
- export { type ClientApiConfig, EntitySplunkOnCallCard, type EntitySplunkOnCallCardProps, type EscalationPolicyInfo, type EscalationPolicyResponse, type EscalationPolicySummary, type EscalationPolicyTeam, type Incident, type IncidentPhase, type IncidentTransition, type IncidentsResponse, type ListRoutingKeyResponse, type ListUserResponse, type MessageType, type OnCall, type OnCallEscalationPolicyResource, type OnCallNowResource, type OnCallTeamResource, type OnCallUser, type OnCallUsersResource, type OnCallsResponse, type RequestOptions, type RoutingKey, type RoutingKeyTarget, type SplunkOnCallApi, SplunkOnCallClient, SplunkOnCallPage, type SplunkOnCallPageProps, type Team, type TriggerAlarmRequest, UnauthorizedError, type User, isSplunkOnCallAvailable, splunkOnCallPlugin as plugin, splunkOnCallApiRef, splunkOnCallPlugin };
258
+ export { type ClientApiConfig, EntitySplunkOnCallCard, type EntitySplunkOnCallCardProps, type EscalationPolicyInfo, type EscalationPolicyResponse, type EscalationPolicySummary, type EscalationPolicyTeam, type Incident, type IncidentPhase, type IncidentTransition, type IncidentsResponse, type ListRoutingKeyResponse, type ListUserResponse, type MessageType, MissingEventsRestEndpointError, type OnCall, type OnCallEscalationPolicyResource, type OnCallNowResource, type OnCallTeamResource, type OnCallUser, type OnCallUsersResource, type OnCallsResponse, type RequestOptions, type RoutingKey, type RoutingKeyTarget, type SplunkOnCallApi, SplunkOnCallClient, SplunkOnCallPage, type SplunkOnCallPageProps, type Team, type TriggerAlarmRequest, UnauthorizedError, type User, isSplunkOnCallAvailable, splunkOnCallPlugin as plugin, splunkOnCallApiRef, splunkOnCallPlugin };
package/dist/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
1
  export { EntitySplunkOnCallCard, SplunkOnCallPage, splunkOnCallPlugin as plugin, splunkOnCallPlugin } from './plugin.esm.js';
2
2
  export { isSplunkOnCallAvailable } from './components/EntitySplunkOnCallCard.esm.js';
3
- export { SplunkOnCallClient, UnauthorizedError, splunkOnCallApiRef } from './api/client.esm.js';
3
+ export { MissingEventsRestEndpointError, SplunkOnCallClient, UnauthorizedError, splunkOnCallApiRef } from './api/client.esm.js';
4
4
  //# sourceMappingURL=index.esm.js.map
@@ -1,5 +1,5 @@
1
1
  import { splunkOnCallApiRef, SplunkOnCallClient } from './api/client.esm.js';
2
- import { createRouteRef, createPlugin, createApiFactory, discoveryApiRef, configApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
2
+ import { createRouteRef, createPlugin, createApiFactory, discoveryApiRef, configApiRef, fetchApiRef, createRoutableExtension, createComponentExtension } from '@backstage/core-plugin-api';
3
3
 
4
4
  const rootRouteRef = createRouteRef({ id: "splunk-on-call" });
5
5
  const splunkOnCallPlugin = createPlugin({
@@ -7,8 +7,12 @@ const splunkOnCallPlugin = createPlugin({
7
7
  apis: [
8
8
  createApiFactory({
9
9
  api: splunkOnCallApiRef,
10
- deps: { discoveryApi: discoveryApiRef, configApi: configApiRef },
11
- factory: ({ configApi, discoveryApi }) => SplunkOnCallClient.fromConfig(configApi, discoveryApi)
10
+ deps: {
11
+ discoveryApi: discoveryApiRef,
12
+ configApi: configApiRef,
13
+ fetchApi: fetchApiRef
14
+ },
15
+ factory: ({ configApi, discoveryApi, fetchApi }) => SplunkOnCallClient.fromConfig(configApi, discoveryApi, fetchApi)
12
16
  })
13
17
  ],
14
18
  routes: {
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { splunkOnCallApiRef, SplunkOnCallClient } from './api';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n discoveryApiRef,\n configApiRef,\n createRoutableExtension,\n createComponentExtension,\n} from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({ id: 'splunk-on-call' });\n\n/** @public */\nexport const splunkOnCallPlugin = createPlugin({\n id: 'splunk-on-call',\n apis: [\n createApiFactory({\n api: splunkOnCallApiRef,\n deps: { discoveryApi: discoveryApiRef, configApi: configApiRef },\n factory: ({ configApi, discoveryApi }) =>\n SplunkOnCallClient.fromConfig(configApi, discoveryApi),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\n/** @public */\nexport const SplunkOnCallPage = splunkOnCallPlugin.provide(\n createRoutableExtension({\n name: 'SplunkOnCallPage',\n component: () =>\n import('./components/SplunkOnCallPage').then(m => m.SplunkOnCallPage),\n mountPoint: rootRouteRef,\n }),\n);\n\n/** @public */\nexport const EntitySplunkOnCallCard = splunkOnCallPlugin.provide(\n createComponentExtension({\n name: 'EntitySplunkOnCallCard',\n component: {\n lazy: () =>\n import('./components/EntitySplunkOnCallCard').then(\n m => m.EntitySplunkOnCallCard,\n ),\n },\n }),\n);\n"],"names":[],"mappings":";;;AA0BO,MAAM,YAAe,GAAA,cAAA,CAAe,EAAE,EAAA,EAAI,kBAAkB;AAG5D,MAAM,qBAAqB,YAAa,CAAA;AAAA,EAC7C,EAAI,EAAA,gBAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,kBAAA;AAAA,MACL,IAAM,EAAA,EAAE,YAAc,EAAA,eAAA,EAAiB,WAAW,YAAa,EAAA;AAAA,MAC/D,OAAA,EAAS,CAAC,EAAE,SAAA,EAAW,cACrB,KAAA,kBAAA,CAAmB,UAAW,CAAA,SAAA,EAAW,YAAY;AAAA,KACxD;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA;AAAA;AAEV,CAAC;AAGM,MAAM,mBAAmB,kBAAmB,CAAA,OAAA;AAAA,EACjD,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,kBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,sCAA+B,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,gBAAgB,CAAA;AAAA,IACtE,UAAY,EAAA;AAAA,GACb;AACH;AAGO,MAAM,yBAAyB,kBAAmB,CAAA,OAAA;AAAA,EACvD,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,wBAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAM,EAAA,MACJ,OAAO,4CAAqC,CAAE,CAAA,IAAA;AAAA,QAC5C,OAAK,CAAE,CAAA;AAAA;AACT;AACJ,GACD;AACH;;;;"}
1
+ {"version":3,"file":"plugin.esm.js","sources":["../src/plugin.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport { splunkOnCallApiRef, SplunkOnCallClient } from './api';\nimport {\n createApiFactory,\n createPlugin,\n createRouteRef,\n discoveryApiRef,\n configApiRef,\n fetchApiRef,\n createRoutableExtension,\n createComponentExtension,\n} from '@backstage/core-plugin-api';\n\nexport const rootRouteRef = createRouteRef({ id: 'splunk-on-call' });\n\n/** @public */\nexport const splunkOnCallPlugin = createPlugin({\n id: 'splunk-on-call',\n apis: [\n createApiFactory({\n api: splunkOnCallApiRef,\n deps: {\n discoveryApi: discoveryApiRef,\n configApi: configApiRef,\n fetchApi: fetchApiRef,\n },\n factory: ({ configApi, discoveryApi, fetchApi }) =>\n SplunkOnCallClient.fromConfig(configApi, discoveryApi, fetchApi),\n }),\n ],\n routes: {\n root: rootRouteRef,\n },\n});\n\n/** @public */\nexport const SplunkOnCallPage = splunkOnCallPlugin.provide(\n createRoutableExtension({\n name: 'SplunkOnCallPage',\n component: () =>\n import('./components/SplunkOnCallPage').then(m => m.SplunkOnCallPage),\n mountPoint: rootRouteRef,\n }),\n);\n\n/** @public */\nexport const EntitySplunkOnCallCard = splunkOnCallPlugin.provide(\n createComponentExtension({\n name: 'EntitySplunkOnCallCard',\n component: {\n lazy: () =>\n import('./components/EntitySplunkOnCallCard').then(\n m => m.EntitySplunkOnCallCard,\n ),\n },\n }),\n);\n"],"names":[],"mappings":";;;AA2BO,MAAM,YAAe,GAAA,cAAA,CAAe,EAAE,EAAA,EAAI,kBAAkB;AAG5D,MAAM,qBAAqB,YAAa,CAAA;AAAA,EAC7C,EAAI,EAAA,gBAAA;AAAA,EACJ,IAAM,EAAA;AAAA,IACJ,gBAAiB,CAAA;AAAA,MACf,GAAK,EAAA,kBAAA;AAAA,MACL,IAAM,EAAA;AAAA,QACJ,YAAc,EAAA,eAAA;AAAA,QACd,SAAW,EAAA,YAAA;AAAA,QACX,QAAU,EAAA;AAAA,OACZ;AAAA,MACA,OAAA,EAAS,CAAC,EAAE,SAAW,EAAA,YAAA,EAAc,QAAS,EAAA,KAC5C,kBAAmB,CAAA,UAAA,CAAW,SAAW,EAAA,YAAA,EAAc,QAAQ;AAAA,KAClE;AAAA,GACH;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,IAAM,EAAA;AAAA;AAEV,CAAC;AAGM,MAAM,mBAAmB,kBAAmB,CAAA,OAAA;AAAA,EACjD,uBAAwB,CAAA;AAAA,IACtB,IAAM,EAAA,kBAAA;AAAA,IACN,SAAA,EAAW,MACT,OAAO,sCAA+B,EAAE,IAAK,CAAA,CAAA,CAAA,KAAK,EAAE,gBAAgB,CAAA;AAAA,IACtE,UAAY,EAAA;AAAA,GACb;AACH;AAGO,MAAM,yBAAyB,kBAAmB,CAAA,OAAA;AAAA,EACvD,wBAAyB,CAAA;AAAA,IACvB,IAAM,EAAA,wBAAA;AAAA,IACN,SAAW,EAAA;AAAA,MACT,IAAM,EAAA,MACJ,OAAO,4CAAqC,CAAE,CAAA,IAAA;AAAA,QAC5C,OAAK,CAAE,CAAA;AAAA;AACT;AACJ,GACD;AACH;;;;"}
package/package.json CHANGED
@@ -1,18 +1,43 @@
1
1
  {
2
2
  "name": "@backstage-community/plugin-splunk-on-call",
3
- "version": "0.18.0",
3
+ "version": "0.20.0",
4
4
  "description": "A Backstage plugin that integrates towards Splunk On-Call",
5
5
  "backstage": {
6
6
  "role": "frontend-plugin",
7
7
  "pluginId": "splunk-on-call",
8
8
  "pluginPackages": [
9
9
  "@backstage-community/plugin-splunk-on-call"
10
- ]
10
+ ],
11
+ "features": {
12
+ "./alpha": "@backstage/FrontendPlugin"
13
+ }
14
+ },
15
+ "exports": {
16
+ ".": {
17
+ "import": "./dist/index.esm.js",
18
+ "types": "./dist/index.d.ts",
19
+ "default": "./dist/index.esm.js"
20
+ },
21
+ "./alpha": {
22
+ "backstage": "@backstage/FrontendPlugin",
23
+ "import": "./dist/alpha.esm.js",
24
+ "types": "./dist/alpha.d.ts",
25
+ "default": "./dist/alpha.esm.js"
26
+ },
27
+ "./package.json": "./package.json"
28
+ },
29
+ "typesVersions": {
30
+ "*": {
31
+ "alpha": [
32
+ "dist/alpha.d.ts"
33
+ ],
34
+ "package.json": [
35
+ "package.json"
36
+ ]
37
+ }
11
38
  },
12
39
  "publishConfig": {
13
- "access": "public",
14
- "main": "dist/index.esm.js",
15
- "types": "dist/index.d.ts"
40
+ "access": "public"
16
41
  },
17
42
  "keywords": [
18
43
  "backstage",
@@ -26,8 +51,8 @@
26
51
  },
27
52
  "license": "Apache-2.0",
28
53
  "sideEffects": false,
29
- "main": "dist/index.esm.js",
30
- "types": "dist/index.d.ts",
54
+ "main": "./dist/index.esm.js",
55
+ "types": "./dist/index.d.ts",
31
56
  "files": [
32
57
  "dist",
33
58
  "config.d.ts"
@@ -43,9 +68,11 @@
43
68
  },
44
69
  "dependencies": {
45
70
  "@backstage/catalog-model": "^1.7.6",
46
- "@backstage/core-components": "^0.18.6",
47
- "@backstage/core-plugin-api": "^1.12.2",
48
- "@backstage/plugin-catalog-react": "^1.21.6",
71
+ "@backstage/core-compat-api": "^0.5.8",
72
+ "@backstage/core-components": "^0.18.7",
73
+ "@backstage/core-plugin-api": "^1.12.3",
74
+ "@backstage/frontend-plugin-api": "^0.14.1",
75
+ "@backstage/plugin-catalog-react": "^2.0.0",
49
76
  "@material-ui/core": "^4.12.2",
50
77
  "@material-ui/icons": "^4.9.1",
51
78
  "@material-ui/lab": "4.0.0-alpha.61",
@@ -54,10 +81,10 @@
54
81
  "react-use": "^17.2.4"
55
82
  },
56
83
  "devDependencies": {
57
- "@backstage/cli": "^0.35.3",
58
- "@backstage/core-app-api": "^1.19.4",
59
- "@backstage/dev-utils": "^1.1.19",
60
- "@backstage/test-utils": "^1.7.14",
84
+ "@backstage/cli": "^0.35.4",
85
+ "@backstage/core-app-api": "^1.19.5",
86
+ "@backstage/dev-utils": "^1.1.20",
87
+ "@backstage/test-utils": "^1.7.15",
61
88
  "@testing-library/dom": "^10.0.0",
62
89
  "@testing-library/jest-dom": "^6.0.0",
63
90
  "@testing-library/react": "^15.0.0",
@@ -73,12 +100,5 @@
73
100
  "react-router-dom": "6.0.0-beta.0 || ^6.3.0"
74
101
  },
75
102
  "configSchema": "config.d.ts",
76
- "typesVersions": {
77
- "*": {
78
- "package.json": [
79
- "package.json"
80
- ]
81
- }
82
- },
83
103
  "module": "./dist/index.esm.js"
84
104
  }