@pagerduty/backstage-plugin-backend 0.12.0 → 0.13.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,24 @@
1
1
  # @pagerduty/backstage-plugin-backend
2
2
 
3
+ ## 0.13.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 9941800: Refactor the service mappings screen and add an auto-matching functionality to mass map PagerDuty service to Backstage entities
8
+ - e1f99a7: Remove deprecated @backstage/backend-common library. This is a potential breaking change for users who are still on the old backend system:
9
+
10
+ - `createPagerDutyServiceAction(...)` now requires its `config` prop.
11
+ - `createRouter(...)` now requires its `auth` prop.
12
+
13
+ Note that none of this is breaking for users of the new backend system.
14
+
15
+ ### Patch Changes
16
+
17
+ - ef0af04: Moved to a process/polling based loading of the automatic mapping matches
18
+ - Updated dependencies [9941800]
19
+ - Updated dependencies [ef0af04]
20
+ - @pagerduty/backstage-plugin-common@0.4.0
21
+
3
22
  ## 0.12.0
4
23
 
5
24
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as _backstage_backend_plugin_api from '@backstage/backend-plugin-api';
2
- import { LoggerService, RootConfigService, DiscoveryService, AuthService } from '@backstage/backend-plugin-api';
2
+ import { LoggerService, RootConfigService, DiscoveryService, AuthService, CacheService } from '@backstage/backend-plugin-api';
3
3
  import { PagerDutyEntityMapping, PagerDutySetting, PagerDutyService, PagerDutyEntityMappingsResponse } from '@pagerduty/backstage-plugin-common';
4
4
  import * as express from 'express';
5
5
  import { CatalogApi, GetEntitiesResponse } from '@backstage/catalog-client';
@@ -29,8 +29,9 @@ interface RouterOptions {
29
29
  config: RootConfigService;
30
30
  store: PagerDutyBackendStore;
31
31
  discovery: DiscoveryService;
32
- auth?: AuthService;
32
+ auth: AuthService;
33
33
  catalogApi?: CatalogApi;
34
+ cache: CacheService;
34
35
  }
35
36
  type Annotations = {
36
37
  'pagerduty.com/integration-key': string;
@@ -31,9 +31,18 @@ const pagerDutyPlugin = backendPluginApi.createBackendPlugin({
31
31
  httpRouter: backendPluginApi.coreServices.httpRouter,
32
32
  database: backendPluginApi.coreServices.database,
33
33
  discovery: backendPluginApi.coreServices.discovery,
34
- auth: backendPluginApi.coreServices.auth
34
+ auth: backendPluginApi.coreServices.auth,
35
+ cache: backendPluginApi.coreServices.cache
35
36
  },
36
- async init({ config, logger, httpRouter, database, discovery, auth }) {
37
+ async init({
38
+ config,
39
+ logger,
40
+ httpRouter,
41
+ database,
42
+ discovery,
43
+ auth,
44
+ cache
45
+ }) {
37
46
  const pagerDutyBackendStore = await PagerDutyBackendDatabase.PagerDutyBackendDatabase.create(await database.getClient(), {
38
47
  skipMigrations: false
39
48
  });
@@ -42,8 +51,7 @@ const pagerDutyPlugin = backendPluginApi.createBackendPlugin({
42
51
  config,
43
52
  logger,
44
53
  store: pagerDutyBackendStore,
45
- discovery,
46
- auth,
54
+ cache,
47
55
  catalogApi: new catalogClient.CatalogClient({
48
56
  discoveryApi: discovery,
49
57
  fetchApi: new CatalogFetchApi(logger, auth)
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n AuthService,\n LoggerService,\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\nimport { PagerDutyBackendDatabase, PagerDutyBackendStore } from './db';\nimport { CatalogClient } from '@backstage/catalog-client';\n\nclass CatalogFetchApi {\n constructor(\n private readonly logger: LoggerService,\n private readonly auth: AuthService,\n ) { }\n\n async fetch(\n input: unknown,\n init: RequestInit | undefined,\n ): Promise<Response> {\n const request = new Request(input as RequestInfo | URL, init);\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: await this.auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n\n request.headers.set('Authorization', `Bearer ${token}`);\n this.logger.debug(`Added token to outgoing request to ${request.url}`);\n return fetch(request);\n }\n}\n\n/** @public */\nexport const pagerDutyPlugin = createBackendPlugin({\n pluginId: 'pagerduty',\n register(env) {\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n httpRouter: coreServices.httpRouter,\n database: coreServices.database,\n discovery: coreServices.discovery,\n auth: coreServices.auth,\n },\n async init({ config, logger, httpRouter, database, discovery, auth }) {\n const pagerDutyBackendStore: PagerDutyBackendStore =\n await PagerDutyBackendDatabase.create(await database.getClient(), {\n skipMigrations: false,\n });\n\n httpRouter.use(\n await createRouter({\n config,\n logger,\n store: pagerDutyBackendStore,\n discovery,\n auth,\n catalogApi: new CatalogClient({\n discoveryApi: discovery,\n fetchApi: new CatalogFetchApi(logger, auth),\n }),\n }),\n );\n // The default Backstage behaviour is to require authentication on routes.\n // https://backstage.io/docs/backend-system/core-services/http-router/#using-the-service\n // Setting enableUnauthenticatedAccess to true will allow unauthenticated access to the PagerDuty plugin routes.\n const enableUnauthenticatedAccess: boolean = config.getOptionalBoolean('pagerDuty.enableUnauthenticatedAccess') ?? false;\n if (enableUnauthenticatedAccess === true) {\n httpRouter.addAuthPolicy({\n path: '/',\n allow: 'unauthenticated',\n });\n }\n },\n });\n },\n});\n"],"names":["createBackendPlugin","coreServices","PagerDutyBackendDatabase","createRouter","CatalogClient"],"mappings":";;;;;;;AAUA,MAAM,eAAA,CAAgB;AAAA,EACpB,WAAA,CACmB,QACA,IAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EACf;AAAA,EAEJ,MAAM,KAAA,CACJ,KAAA,EACA,IAAA,EACmB;AACnB,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,KAAA,EAA4B,IAAI,CAAA;AAC5D,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,KAAK,qBAAA,CAAsB;AAAA,MACtD,UAAA,EAAY,MAAM,IAAA,CAAK,IAAA,CAAK,wBAAA,EAAyB;AAAA,MACrD,cAAA,EAAgB;AAAA,KACjB,CAAA;AAED,IAAA,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,eAAA,EAAiB,CAAA,OAAA,EAAU,KAAK,CAAA,CAAE,CAAA;AACtD,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,mCAAA,EAAsC,OAAA,CAAQ,GAAG,CAAA,CAAE,CAAA;AACrE,IAAA,OAAO,MAAM,OAAO,CAAA;AAAA,EACtB;AACF;AAGO,MAAM,kBAAkBA,oCAAA,CAAoB;AAAA,EACjD,QAAA,EAAU,WAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,QAAQC,6BAAA,CAAa,MAAA;AAAA,QACrB,QAAQA,6BAAA,CAAa,UAAA;AAAA,QACrB,YAAYA,6BAAA,CAAa,UAAA;AAAA,QACzB,UAAUA,6BAAA,CAAa,QAAA;AAAA,QACvB,WAAWA,6BAAA,CAAa,SAAA;AAAA,QACxB,MAAMA,6BAAA,CAAa;AAAA,OACrB;AAAA,MACA,MAAM,KAAK,EAAE,MAAA,EAAQ,QAAQ,UAAA,EAAY,QAAA,EAAU,SAAA,EAAW,IAAA,EAAK,EAAG;AACpE,QAAA,MAAM,wBACJ,MAAMC,iDAAA,CAAyB,OAAO,MAAM,QAAA,CAAS,WAAU,EAAG;AAAA,UAChE,cAAA,EAAgB;AAAA,SACjB,CAAA;AAEH,QAAA,UAAA,CAAW,GAAA;AAAA,UACT,MAAMC,mBAAA,CAAa;AAAA,YACjB,MAAA;AAAA,YACA,MAAA;AAAA,YACA,KAAA,EAAO,qBAAA;AAAA,YACP,SAAA;AAAA,YACA,IAAA;AAAA,YACA,UAAA,EAAY,IAAIC,2BAAA,CAAc;AAAA,cAC5B,YAAA,EAAc,SAAA;AAAA,cACd,QAAA,EAAU,IAAI,eAAA,CAAgB,MAAA,EAAQ,IAAI;AAAA,aAC3C;AAAA,WACF;AAAA,SACH;AAIA,QAAA,MAAM,2BAAA,GAAuC,MAAA,CAAO,kBAAA,CAAmB,uCAAuC,CAAA,IAAK,KAAA;AACnH,QAAA,IAAI,gCAAgC,IAAA,EAAM;AACxC,UAAA,UAAA,CAAW,aAAA,CAAc;AAAA,YACvB,IAAA,EAAM,GAAA;AAAA,YACN,KAAA,EAAO;AAAA,WACR,CAAA;AAAA,QACH;AAAA,MACF;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"plugin.cjs.js","sources":["../src/plugin.ts"],"sourcesContent":["import {\n AuthService,\n LoggerService,\n coreServices,\n createBackendPlugin,\n} from '@backstage/backend-plugin-api';\nimport { createRouter } from './service/router';\nimport { PagerDutyBackendDatabase, PagerDutyBackendStore } from './db';\nimport { CatalogClient } from '@backstage/catalog-client';\n\nclass CatalogFetchApi {\n constructor(\n private readonly logger: LoggerService,\n private readonly auth: AuthService,\n ) { }\n\n async fetch(\n input: unknown,\n init: RequestInit | undefined,\n ): Promise<Response> {\n const request = new Request(input as RequestInfo | URL, init);\n const { token } = await this.auth.getPluginRequestToken({\n onBehalfOf: await this.auth.getOwnServiceCredentials(),\n targetPluginId: 'catalog',\n });\n\n request.headers.set('Authorization', `Bearer ${token}`);\n this.logger.debug(`Added token to outgoing request to ${request.url}`);\n return fetch(request);\n }\n}\n\n/** @public */\nexport const pagerDutyPlugin = createBackendPlugin({\n pluginId: 'pagerduty',\n register(env) {\n env.registerInit({\n deps: {\n logger: coreServices.logger,\n config: coreServices.rootConfig,\n httpRouter: coreServices.httpRouter,\n database: coreServices.database,\n discovery: coreServices.discovery,\n auth: coreServices.auth,\n cache: coreServices.cache,\n },\n async init({\n config,\n logger,\n httpRouter,\n database,\n discovery,\n auth,\n cache,\n }) {\n const pagerDutyBackendStore: PagerDutyBackendStore =\n await PagerDutyBackendDatabase.create(await database.getClient(), {\n skipMigrations: false,\n });\n\n httpRouter.use(\n await createRouter({\n config,\n logger,\n store: pagerDutyBackendStore,\n discovery,\n auth,\n cache,\n catalogApi: new CatalogClient({\n discoveryApi: discovery,\n fetchApi: new CatalogFetchApi(logger, auth),\n }),\n }),\n );\n // The default Backstage behaviour is to require authentication on routes.\n // https://backstage.io/docs/backend-system/core-services/http-router/#using-the-service\n // Setting enableUnauthenticatedAccess to true will allow unauthenticated access to the PagerDuty plugin routes.\n const enableUnauthenticatedAccess: boolean = config.getOptionalBoolean('pagerDuty.enableUnauthenticatedAccess') ?? false;\n if (enableUnauthenticatedAccess === true) {\n httpRouter.addAuthPolicy({\n path: '/',\n allow: 'unauthenticated',\n });\n }\n },\n });\n },\n});\n"],"names":["createBackendPlugin","coreServices","PagerDutyBackendDatabase","createRouter","CatalogClient"],"mappings":";;;;;;;AAUA,MAAM,eAAA,CAAgB;AAAA,EACpB,WAAA,CACmB,QACA,IAAA,EACjB;AAFiB,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AAAA,EACf;AAAA,EAEJ,MAAM,KAAA,CACJ,KAAA,EACA,IAAA,EACmB;AACnB,IAAA,MAAM,OAAA,GAAU,IAAI,OAAA,CAAQ,KAAA,EAA4B,IAAI,CAAA;AAC5D,IAAA,MAAM,EAAE,KAAA,EAAM,GAAI,MAAM,IAAA,CAAK,KAAK,qBAAA,CAAsB;AAAA,MACtD,UAAA,EAAY,MAAM,IAAA,CAAK,IAAA,CAAK,wBAAA,EAAyB;AAAA,MACrD,cAAA,EAAgB;AAAA,KACjB,CAAA;AAED,IAAA,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,eAAA,EAAiB,CAAA,OAAA,EAAU,KAAK,CAAA,CAAE,CAAA;AACtD,IAAA,IAAA,CAAK,MAAA,CAAO,KAAA,CAAM,CAAA,mCAAA,EAAsC,OAAA,CAAQ,GAAG,CAAA,CAAE,CAAA;AACrE,IAAA,OAAO,MAAM,OAAO,CAAA;AAAA,EACtB;AACF;AAGO,MAAM,kBAAkBA,oCAAA,CAAoB;AAAA,EACjD,QAAA,EAAU,WAAA;AAAA,EACV,SAAS,GAAA,EAAK;AACZ,IAAA,GAAA,CAAI,YAAA,CAAa;AAAA,MACf,IAAA,EAAM;AAAA,QACJ,QAAQC,6BAAA,CAAa,MAAA;AAAA,QACrB,QAAQA,6BAAA,CAAa,UAAA;AAAA,QACrB,YAAYA,6BAAA,CAAa,UAAA;AAAA,QACzB,UAAUA,6BAAA,CAAa,QAAA;AAAA,QACvB,WAAWA,6BAAA,CAAa,SAAA;AAAA,QACxB,MAAMA,6BAAA,CAAa,IAAA;AAAA,QACnB,OAAOA,6BAAA,CAAa;AAAA,OACtB;AAAA,MACA,MAAM,IAAA,CAAK;AAAA,QACT,MAAA;AAAA,QACA,MAAA;AAAA,QACA,UAAA;AAAA,QACA,QAAA;AAAA,QACA,SAAA;AAAA,QACA,IAAA;AAAA,QACA;AAAA,OACF,EAAG;AACD,QAAA,MAAM,wBACJ,MAAMC,iDAAA,CAAyB,OAAO,MAAM,QAAA,CAAS,WAAU,EAAG;AAAA,UAChE,cAAA,EAAgB;AAAA,SACjB,CAAA;AAEH,QAAA,UAAA,CAAW,GAAA;AAAA,UACT,MAAMC,mBAAA,CAAa;AAAA,YACjB,MAAA;AAAA,YACA,MAAA;AAAA,YACA,KAAA,EAAO,qBAAA;AAAA,YAGP,KAAA;AAAA,YACA,UAAA,EAAY,IAAIC,2BAAA,CAAc;AAAA,cAC5B,YAAA,EAAc,SAAA;AAAA,cACd,QAAA,EAAU,IAAI,eAAA,CAAgB,MAAA,EAAQ,IAAI;AAAA,aAC3C;AAAA,WACF;AAAA,SACH;AAIA,QAAA,MAAM,2BAAA,GAAuC,MAAA,CAAO,kBAAA,CAAmB,uCAAuC,CAAA,IAAK,KAAA;AACnH,QAAA,IAAI,gCAAgC,IAAA,EAAM;AACxC,UAAA,UAAA,CAAW,aAAA,CAAc;AAAA,YACvB,IAAA,EAAM,GAAA;AAAA,YACN,KAAA,EAAO;AAAA,WACR,CAAA;AAAA,QACH;AAAA,MACF;AAAA,KACD,CAAA;AAAA,EACH;AACF,CAAC;;;;"}
@@ -1,15 +1,15 @@
1
1
  'use strict';
2
2
 
3
- var backendCommon = require('@backstage/backend-common');
4
3
  var pagerduty = require('../apis/pagerduty.cjs.js');
5
- var dataLoader = require('../services/dataLoader.cjs.js');
6
- var matchingEngine = require('../services/matchingEngine.cjs.js');
4
+ var autoMatchRunner = require('../services/autoMatchRunner.cjs.js');
5
+ var autoMatchJobs = require('../services/autoMatchJobs.cjs.js');
7
6
  var backstagePluginCommon = require('@pagerduty/backstage-plugin-common');
8
7
  var auth = require('../auth/auth.cjs.js');
9
8
  var express = require('express');
10
9
  var Router = require('express-promise-router');
11
10
  var mappingsController = require('../controllers/mappings-controller.cjs.js');
12
11
  var catalogEntity = require('../utils/catalog-entity.cjs.js');
12
+ var rootHttpRouter = require('@backstage/backend-defaults/rootHttpRouter');
13
13
 
14
14
  function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e : { default: e }; }
15
15
 
@@ -152,18 +152,19 @@ async function buildEntityMappingsResponse(entityMappings, componentEntitiesDict
152
152
  return result;
153
153
  }
154
154
  async function createRouter(options) {
155
- const { logger, config, store, catalogApi } = options;
156
- let { auth: auth$1 } = options;
157
- if (!auth$1) {
158
- auth$1 = backendCommon.createLegacyAuthAdapters(options).auth;
159
- }
155
+ const { logger, config, store, catalogApi, cache } = options;
160
156
  if (!catalogApi) {
161
157
  throw new Error("Catalog API is required to start the PagerDuty plugin backend");
162
158
  }
159
+ if (!cache) {
160
+ throw new Error("Cache service is required to start the PagerDuty plugin backend");
161
+ }
163
162
  await auth.loadAuthConfig(config, logger);
164
163
  pagerduty.loadPagerDutyEndpointsFromConfig(config, logger);
165
164
  const router = Router__default.default();
166
165
  router.use(express__namespace.json());
166
+ const runAutoMatch = autoMatchRunner.createAutoMatchRunner(catalogApi);
167
+ const autoMatchJobs$1 = new autoMatchJobs.AutoMatchJobRegistry(cache, runAutoMatch);
167
168
  router.delete(
168
169
  "/dependencies/service/:serviceId",
169
170
  async (request, response) => {
@@ -624,93 +625,45 @@ async function createRouter(options) {
624
625
  }
625
626
  }
626
627
  );
627
- router.post("/mapping/entity/auto-match", async (request, response) => {
628
- try {
629
- const threshold = request.body.threshold ?? 100;
630
- const account = request.body.account;
631
- if (typeof threshold !== "number" || threshold < 0 || threshold > 100) {
632
- response.status(400).json({
633
- error: "Invalid threshold. Must be a number between 0 and 100."
634
- });
635
- return;
636
- }
637
- const bestOnly = request.body.bestOnly ?? false;
638
- const loadStartTime = Date.now();
639
- const { pdServices, bsComponents } = await dataLoader.loadBothSources({
640
- catalogApi
628
+ router.post("/mapping/entity/auto-match/start", async (request, response) => {
629
+ const threshold = request.body.threshold ?? 100;
630
+ if (typeof threshold !== "number" || threshold < 0 || threshold > 100) {
631
+ response.status(400).json({
632
+ error: "Invalid threshold. Must be a number between 0 and 100."
641
633
  });
642
- const filteredPdServices = account ? pdServices.filter((service) => service.account === account) : pdServices;
643
- const loadTime = Date.now() - loadStartTime;
644
- const matchStartTime = Date.now();
645
- const matchingConfig = { threshold };
646
- let matches = matchingEngine.findMatches(filteredPdServices, bsComponents, matchingConfig);
647
- if (bestOnly) {
648
- matches = matchingEngine.filterToBestMatchPerService(matches);
649
- }
650
- const matchTime = Date.now() - matchStartTime;
651
- const totalComparisons = filteredPdServices.length * bsComponents.length;
652
- const exactMatches = matches.filter((m) => m.score === 100).length;
653
- const highConfidence = matches.filter(
654
- (m) => m.score >= 90 && m.score < 100
655
- ).length;
656
- const mediumConfidence = matches.filter(
657
- (m) => m.score >= 80 && m.score < 90
658
- ).length;
659
- const getConfidenceLevel = (score) => {
660
- if (score === 100) return "exact";
661
- if (score >= 90) return "high";
662
- if (score >= 80) return "medium";
663
- return "low";
664
- };
665
- response.json({
666
- matches: matches.map((m) => ({
667
- pagerDutyService: {
668
- serviceId: m.pagerDutyService.sourceId,
669
- name: m.pagerDutyService.rawName,
670
- team: m.pagerDutyService.teamName,
671
- account: m.pagerDutyService.account
672
- },
673
- backstageComponent: {
674
- entityRef: m.backstageComponent.sourceId,
675
- name: m.backstageComponent.rawName,
676
- owner: m.backstageComponent.teamName
677
- },
678
- score: m.score,
679
- confidence: getConfidenceLevel(m.score),
680
- scoreBreakdown: m.scoreBreakdown
681
- })),
682
- statistics: {
683
- totalPagerDutyServices: filteredPdServices.length,
684
- totalBackstageComponents: bsComponents.length,
685
- totalPossibleComparisons: totalComparisons,
686
- matchesFound: matches.length,
687
- exactMatches,
688
- highConfidenceMatches: highConfidence,
689
- mediumConfidenceMatches: mediumConfidence,
690
- threshold,
691
- loadTimeMs: loadTime,
692
- matchTimeMs: matchTime,
693
- totalTimeMs: loadTime + matchTime
694
- }
634
+ return;
635
+ }
636
+ const bestOnly = request.body.bestOnly ?? false;
637
+ const team = request.body.team;
638
+ const account = request.body.account;
639
+ const job = await autoMatchJobs$1.start({
640
+ threshold,
641
+ bestOnly,
642
+ team,
643
+ account
644
+ });
645
+ response.status(202).json({
646
+ jobId: job.id,
647
+ status: job.status
648
+ });
649
+ });
650
+ router.get("/mapping/entity/auto-match/:jobId", async (request, response) => {
651
+ const jobId = request.params.jobId;
652
+ const job = await autoMatchJobs$1.get(jobId);
653
+ if (!job) {
654
+ response.status(404).json({
655
+ error: `Auto-match job ${jobId} not found.`
695
656
  });
696
- } catch (error) {
697
- logger.error(`Auto-match failed: ${error}`);
698
- if (error instanceof backstagePluginCommon.HttpError) {
699
- response.status(error.status).json({
700
- errors: [`${error.message}`]
701
- });
702
- } else if (error instanceof dataLoader.ServiceLoadError) {
703
- response.status(503).json({
704
- error: "Service temporarily unavailable",
705
- message: error.message
706
- });
707
- } else {
708
- response.status(500).json({
709
- error: "Auto-match failed",
710
- message: error instanceof Error ? error.message : String(error)
711
- });
712
- }
657
+ return;
713
658
  }
659
+ response.json({
660
+ jobId: job.id,
661
+ status: job.status,
662
+ createdAt: job.createdAt,
663
+ completedAt: job.completedAt,
664
+ result: job.result,
665
+ error: job.error
666
+ });
714
667
  });
715
668
  router.get("/escalation_policies", async (_, response) => {
716
669
  try {
@@ -970,7 +923,7 @@ async function createRouter(options) {
970
923
  router.get("/health", async (_, response) => {
971
924
  response.status(200).json({ status: "ok" });
972
925
  });
973
- router.use(backendCommon.errorHandler());
926
+ router.use(rootHttpRouter.MiddlewareFactory.create({ config, logger }).error());
974
927
  return router;
975
928
  }
976
929
 
@@ -1 +1 @@
1
- {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["import {\n AuthService,\n DiscoveryService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport {\n createLegacyAuthAdapters,\n errorHandler,\n} from '@backstage/backend-common';\nimport {\n getAllEscalationPolicies,\n getChangeEvents,\n getIncidents,\n getOncallUsers,\n getServiceById,\n getServiceByIntegrationKey,\n getServiceStandards,\n getServiceMetrics,\n getAllServices,\n getAllTeams,\n getFilteredServices,\n loadPagerDutyEndpointsFromConfig,\n createServiceIntegration,\n getServiceRelationshipsById,\n addServiceRelationsToService,\n removeServiceRelationsFromService,\n} from '../apis/pagerduty';\nimport { loadBothSources, ServiceLoadError } from '../services/dataLoader';\nimport {\n findMatches,\n filterToBestMatchPerService,\n type MatchingConfig,\n} from '../services/matchingEngine';\nimport {\n HttpError,\n PagerDutyChangeEventsResponse,\n PagerDutyIncidentsResponse,\n PagerDutyOnCallUsersResponse,\n PagerDutyServiceResponse,\n PagerDutyServiceStandardsResponse,\n PagerDutyServiceMetricsResponse,\n PagerDutyServicesResponse,\n PagerDutyEntityMapping,\n PagerDutyEntityMappingsResponse,\n PagerDutyService,\n PagerDutyServiceDependency,\n PagerDutySetting,\n} from '@pagerduty/backstage-plugin-common';\nimport { loadAuthConfig } from '../auth/auth';\nimport {\n PagerDutyBackendStore,\n RawDbEntityResultRow,\n} from '../db/PagerDutyBackendDatabase';\nimport * as express from 'express';\nimport Router from 'express-promise-router';\nimport type { CatalogApi, GetEntitiesResponse } from '@backstage/catalog-client';\n\nimport * as MappingsController from '../controllers/mappings-controller';\nimport * as CatalogEntityUtils from '../utils/catalog-entity';\n\nexport interface RouterOptions {\n logger: LoggerService;\n config: RootConfigService;\n store: PagerDutyBackendStore;\n discovery: DiscoveryService;\n auth?: AuthService;\n catalogApi?: CatalogApi;\n}\n\nexport type Annotations = {\n 'pagerduty.com/integration-key': string;\n 'pagerduty.com/service-id': string;\n 'pagerduty.com/account': string;\n};\n\nexport async function buildEntityMappingsResponse(\n entityMappings: RawDbEntityResultRow[],\n componentEntitiesDict: Record<\n string,\n {\n ref: string;\n name: string;\n }\n >,\n componentEntities: GetEntitiesResponse,\n pagerDutyServices: PagerDutyService[],\n): Promise<PagerDutyEntityMappingsResponse> {\n const result: PagerDutyEntityMappingsResponse = {\n mappings: [],\n };\n\n pagerDutyServices.forEach(service => {\n // Check for service mapping annotation in any entity config file and get the entity ref\n const entityRef = componentEntitiesDict[service.id]?.ref;\n const entityName = componentEntitiesDict[service.id]?.name;\n\n // Check if the service is mapped to an entity in the database\n const entityMapping = entityMappings.find(\n mapping => mapping.serviceId === service.id,\n );\n\n if (entityMapping) {\n if (entityRef === undefined) {\n if (\n entityMapping.entityRef === '' ||\n entityMapping.entityRef === undefined\n ) {\n result.mappings.push({\n entityRef: '',\n entityName: '',\n integrationKey: entityMapping.integrationKey,\n serviceId: entityMapping.serviceId,\n status: 'NotMapped',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n } else {\n const entityRefName =\n componentEntities.items.find(\n entity =>\n `${entity.kind}:${entity.metadata.namespace}/${entity.metadata.name}`.toLowerCase() ===\n entityMapping.entityRef,\n )?.metadata.name ?? '';\n\n result.mappings.push({\n entityRef: entityMapping.entityRef,\n entityName: entityRefName,\n serviceId: entityMapping.serviceId,\n integrationKey: entityMapping.integrationKey,\n status: 'OutOfSync',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n }\n } else if (entityRef !== entityMapping.entityRef) {\n const entityRefName =\n componentEntities.items.find(\n entity =>\n `${entity.kind}:${entity.metadata.namespace}/${entity.metadata.name}`.toLowerCase() ===\n entityMapping.entityRef,\n )?.metadata.name ?? '';\n\n result.mappings.push({\n entityRef:\n entityMapping.entityRef !== '' ? entityMapping.entityRef : '',\n entityName: entityMapping.entityRef !== '' ? entityRefName : '',\n serviceId: entityMapping.serviceId,\n integrationKey: entityMapping.integrationKey,\n status: 'OutOfSync',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n } else if (entityRef === entityMapping.entityRef) {\n result.mappings.push({\n entityRef:\n entityMapping.entityRef !== '' ? entityMapping.entityRef : '',\n entityName: entityMapping.entityRef !== '' ? entityName : '',\n serviceId: entityMapping.serviceId,\n integrationKey: entityMapping.integrationKey,\n status: 'InSync',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n }\n } else {\n const backstageVendorId = 'PRO19CT';\n const backstageIntegrationKey =\n service.integrations?.find(\n integration => integration.vendor?.id === backstageVendorId,\n )?.integration_key ?? '';\n\n if (entityRef !== undefined) {\n result.mappings.push({\n entityRef: entityRef,\n entityName: entityName,\n serviceId: service.id,\n integrationKey: backstageIntegrationKey,\n status: 'InSync',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n } else {\n result.mappings.push({\n entityRef: '',\n entityName: '',\n serviceId: service.id,\n integrationKey: backstageIntegrationKey,\n status: 'NotMapped',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n }\n }\n });\n\n const sortedResult = result.mappings.sort((a, b) => {\n if (a.serviceName! < b.serviceName!) {\n return -1;\n } else if (a.serviceName! > b.serviceName!) {\n return 1;\n }\n return 0;\n });\n\n result.mappings = sortedResult;\n\n return result;\n}\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, store, catalogApi } = options;\n let { auth } = options;\n\n if (!auth) {\n auth = createLegacyAuthAdapters(options).auth;\n }\n\n if (!catalogApi) {\n throw new Error('Catalog API is required to start the PagerDuty plugin backend');\n }\n\n // Get authentication Config\n await loadAuthConfig(config, logger);\n\n // Get optional PagerDuty custom endpoints from config\n loadPagerDutyEndpointsFromConfig(config, logger);\n\n // Create the router\n const router = Router();\n router.use(express.json());\n\n // DELETE /dependencies/service/:serviceId\n router.delete(\n '/dependencies/service/:serviceId',\n async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n if (serviceId === '') {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' must be provided as part of the path\",\n );\n return;\n }\n\n const dependencies: string[] =\n Object.keys(request.body).length === 0 ? [] : request.body;\n if (!dependencies || dependencies.length === 0) {\n response\n .status(400)\n .json(\n \"Bad Request: 'dependencies' must be provided as part of the request body\",\n );\n return;\n }\n\n const serviceRelations: PagerDutyServiceDependency[] = [];\n\n dependencies.forEach(async dependency => {\n serviceRelations.push({\n supporting_service: {\n id: dependency,\n type: 'service',\n },\n dependent_service: {\n id: serviceId,\n type: 'service',\n },\n });\n });\n\n await removeServiceRelationsFromService(serviceRelations, account);\n\n response.sendStatus(200);\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // POST /dependencies/service/:serviceId\n router.post('/dependencies/service/:serviceId', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n if (serviceId === '') {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' must be provided as part of the path\",\n );\n return;\n }\n\n const dependencies: string[] =\n Object.keys(request.body).length === 0 ? [] : request.body;\n if (!dependencies || dependencies.length === 0) {\n response\n .status(400)\n .json(\n \"Bad Request: 'dependencies' must be provided as part of the request body\",\n );\n return;\n }\n\n const serviceRelations: PagerDutyServiceDependency[] = [];\n\n dependencies.forEach(async dependency => {\n serviceRelations.push({\n supporting_service: {\n id: dependency,\n type: 'service',\n },\n dependent_service: {\n id: serviceId,\n type: 'service',\n },\n });\n });\n\n await addServiceRelationsToService(serviceRelations, account);\n\n response.sendStatus(200);\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n router.get('/dependencies/service/:serviceId', async (request, response) => {\n try {\n const serviceId = request.params.serviceId;\n const account = (request.query.account as string) || '';\n\n if (serviceId) {\n const serviceRelationships: PagerDutyServiceDependency[] =\n await getServiceRelationshipsById(serviceId, account);\n\n if (serviceRelationships) {\n response.json({\n relationships: serviceRelationships,\n });\n }\n } else {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' must be provided as part of the path\",\n );\n }\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /catalog/entity/:entityRef\n router.get(\n '/catalog/entity/:type/:namespace/:name',\n async (request, response) => {\n const type = request.params.type;\n const namespace = request.params.namespace;\n const name = request.params.name;\n\n try {\n if (type && namespace && name) {\n const entityRef = `${type}:${namespace}/${name}`.toLowerCase();\n const foundEntity = await catalogApi?.getEntityByRef(entityRef);\n\n if (foundEntity) {\n response.json(\n foundEntity.metadata.annotations?.['pagerduty.com/service-id'],\n );\n } else {\n response.status(404);\n }\n } else {\n response\n .status(400)\n .json(\n \"Bad Request: ':entityRef' must be provided as part of the path\",\n );\n }\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // POST /settings\n router.post('/settings', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const settings: PagerDutySetting[] = request.body;\n\n // For each setting, update or insert the value in the database\n await Promise.all(\n settings.map(async setting => {\n if (setting.id === undefined || setting.value === undefined) {\n response\n .status(400)\n .json(\"Bad Request: 'id' and 'value' are required\");\n return;\n }\n\n if (!isValidSetting(setting.value)) {\n response\n .status(400)\n .json(\n \"Bad Request: 'value' is invalid. Valid options are 'backstage', 'pagerduty', 'both' or 'disabled'\",\n );\n return;\n }\n\n await store.updateSetting(setting);\n }),\n );\n\n response.sendStatus(200);\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /settings/:settingId\n router.get('/settings/:settingId', async (request, response) => {\n try {\n // Get param from the request\n const settingId = request.params.settingId;\n\n // Find setting by id\n const setting = await store.findSetting(settingId);\n\n if (!setting) {\n response.status(404).json({});\n return;\n }\n\n response.json(setting);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n function isValidSetting(value: string): boolean {\n if (\n value === 'backstage' ||\n value === 'pagerduty' ||\n value === 'both' ||\n value === 'disabled'\n ) {\n return true;\n }\n\n return false;\n }\n\n // POST /mapping/entity\n router.post('/mapping/entity', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const entity: PagerDutyEntityMapping = request.body;\n\n if (!entity.serviceId) {\n response\n .status(400)\n .json(\n \"Bad Request: 'serviceId' must be provided as part of the request body\",\n );\n return;\n }\n\n // Get all the entity mappings from the database\n const entityMappings = await store.getAllEntityMappings();\n const oldMapping = entityMappings.find(\n mapping => mapping.serviceId === entity.serviceId,\n );\n\n // in case a mapping is defined and no integration exists,\n // we need to create one\n if (\n entity.entityRef !== '' &&\n (entity.integrationKey === '' || entity.integrationKey === undefined)\n ) {\n const backstageVendorId = 'PRO19CT';\n // check for existing integration key on service\n const service = await getServiceById(entity.serviceId, entity.account);\n const backstageIntegration = service.integrations?.find(\n integration => integration.vendor?.id === backstageVendorId,\n );\n\n if (!backstageIntegration) {\n // If an integration does not exist for service,\n // create it in PagerDuty\n const integrationKey = await createServiceIntegration({\n serviceId: entity.serviceId,\n vendorId: backstageVendorId,\n account: entity.account,\n });\n\n entity.integrationKey = integrationKey;\n } else {\n entity.integrationKey = backstageIntegration.integration_key;\n }\n }\n\n const entityMappingId = await store.insertEntityMapping(entity);\n\n // Refresh new and old entity unless they are empty strings\n if (entity.entityRef !== '') {\n // force refresh of new entity\n await catalogApi?.refreshEntity(entity.entityRef);\n }\n\n if (oldMapping && oldMapping.entityRef !== '') {\n // force refresh of old entity\n await catalogApi?.refreshEntity(oldMapping.entityRef);\n }\n\n response.json({\n id: entityMappingId,\n entityRef: entity.entityRef,\n integrationKey: entity.integrationKey,\n serviceId: entity.serviceId,\n status: entity.status,\n account: entity.account,\n });\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n } else {\n logger.error(\n `Unexpected error occurred while processing request: ${error}`,\n );\n response.status(500).json({\n errors: [error instanceof Error ? error.message : String(error)],\n });\n }\n }\n });\n\n // POST /mapping/entities/bulk\n router.post('/mapping/entities/bulk', async (request, response) => {\n try {\n const { mappings } = request.body;\n\n if (!Array.isArray(mappings)) {\n response.status(400).json({\n error: \"Bad Request: 'mappings' must be an array\",\n });\n return;\n }\n\n const existingMappings = await store.getAllEntityMappings();\n const existingServiceIds = new Set(\n existingMappings.map(m => m.serviceId),\n );\n\n const newMappings: PagerDutyEntityMapping[] = [];\n const skipped: PagerDutyEntityMapping[] = [];\n const errors = [];\n\n for (const entity of mappings) {\n if (!entity.serviceId) {\n errors.push({\n entityRef: entity.entityRef,\n error: 'Missing serviceId',\n });\n continue;\n }\n\n if (existingServiceIds.has(entity.serviceId)) {\n skipped.push(entity);\n continue;\n }\n\n if (\n entity.entityRef !== '' &&\n (entity.integrationKey === '' || entity.integrationKey === undefined)\n ) {\n try {\n const backstageVendorId = 'PRO19CT';\n const service = await getServiceById(\n entity.serviceId,\n entity.account,\n );\n const backstageIntegration = service.integrations?.find(\n integration => integration.vendor?.id === backstageVendorId,\n );\n\n if (!backstageIntegration) {\n const integrationKey = await createServiceIntegration({\n serviceId: entity.serviceId,\n vendorId: backstageVendorId,\n account: entity.account,\n });\n\n entity.integrationKey = integrationKey;\n } else {\n entity.integrationKey = backstageIntegration.integration_key;\n }\n } catch (error) {\n errors.push({\n entityRef: entity.entityRef,\n serviceId: entity.serviceId,\n error:\n error instanceof Error\n ? `Failed to create integration: ${error.message}`\n : 'Failed to create integration',\n });\n continue;\n }\n }\n\n newMappings.push(entity);\n }\n\n let insertedIds: string[] = [];\n if (newMappings.length > 0) {\n try {\n insertedIds = await store.bulkInsertEntityMappings(newMappings);\n\n await Promise.all(\n newMappings.map(async entity => {\n if (entity.entityRef !== '') {\n await catalogApi?.refreshEntity(entity.entityRef);\n }\n }),\n );\n } catch (error) {\n logger.error(`Bulk insert failed: ${error}`);\n response.status(500).json({\n errors: ['Bulk insert failed'],\n });\n return;\n }\n }\n\n const results = newMappings.map((entity, index) => ({\n id: insertedIds[index],\n entityRef: entity.entityRef,\n integrationKey: entity.integrationKey,\n serviceId: entity.serviceId,\n status: entity.status,\n account: entity.account,\n }));\n\n response.json({\n success: results,\n skipped: skipped.map(entity => ({\n entityRef: entity.entityRef,\n serviceId: entity.serviceId,\n reason: 'Mapping already exists for this service ID',\n })),\n errors: errors,\n total: mappings.length,\n successCount: results.length,\n skippedCount: skipped.length,\n errorCount: errors.length,\n });\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing bulk mappings: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n } else {\n logger.error(`Unexpected error: ${error}`);\n response.status(500).json({\n errors: ['Internal server error'],\n });\n }\n }\n });\n\n // DEPRECATED: GET /mapping/entity\n router.get('/mapping/entity', async (_, response) => {\n try {\n // Get all the entity mappings from the database\n const entityMappings = await store.getAllEntityMappings();\n\n // Get all the entities from the catalog\n const componentEntities = await catalogApi!.getEntities({\n filter: {\n kind: 'Component',\n },\n });\n\n // Build reference dictionary of componentEntities with serviceId as the key and entity reference and name pair as the value\n const componentEntitiesDict: Record<\n string,\n { ref: string; name: string }\n > = await CatalogEntityUtils.createComponentEntitiesReferenceDict(componentEntities);\n\n // Get all services from PagerDuty\n const pagerDutyServices = await getAllServices();\n\n // Build the response object\n const result: PagerDutyEntityMappingsResponse =\n await buildEntityMappingsResponse(\n entityMappings,\n componentEntitiesDict,\n componentEntities,\n pagerDutyServices,\n );\n\n response.json(result);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n router.post('/mapping/entities', MappingsController.getMappingEntities(store, catalogApi));\n\n // GET /mapping/entity\n router.get(\n '/mapping/entity/:type/:namespace/:name',\n async (request, response) => {\n try {\n // Get the type, namespace and entity name from the request parameters\n const entityType: string = request.params.type || '';\n const entityNamespace: string = request.params.namespace || '';\n const entityName: string = request.params.name || '';\n\n if (entityType === '' || entityNamespace === '' || entityName === '') {\n response.status(400).json('Required params not specified.');\n return;\n }\n\n const entityRef =\n `${entityType}:${entityNamespace}/${entityName}`.toLowerCase();\n\n // Get all the entity mappings from the database\n const entityMapping = await store.findEntityMappingByEntityRef(\n entityRef,\n );\n\n if (!entityMapping) {\n response\n .status(404)\n .json(`Mapping for entityRef ${entityRef} not found.`);\n return;\n }\n\n response.json({\n mapping: entityMapping,\n });\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // GET /mapping/entity/service/:serviceId\n router.get(\n '/mapping/entity/service/:serviceId',\n async (request, response) => {\n try {\n // Get the type, namespace and entity name from the request parameters\n const serviceId: string = request.params.serviceId ?? '';\n\n if (serviceId === '') {\n response.status(400).json('Required params not specified.');\n return;\n }\n\n // Get all the entity mappings from the database\n const entityMapping = await store.findEntityMappingByServiceId(\n serviceId,\n );\n\n if (!entityMapping) {\n response\n .status(404)\n .json(`Mapping for serviceId ${serviceId} not found.`);\n return;\n }\n\n response.json({\n mapping: entityMapping,\n });\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // POST /mapping/entity/auto-match\n router.post('/mapping/entity/auto-match', async (request, response) => {\n try {\n // Default 100% threshold ensures only exact matches, customers can adjust if needed\n const threshold: number = request.body.threshold ?? 100;\n const account: string | undefined = request.body.account;\n\n if (typeof threshold !== 'number' || threshold < 0 || threshold > 100) {\n response.status(400).json({\n error: 'Invalid threshold. Must be a number between 0 and 100.',\n });\n return;\n }\n\n const bestOnly: boolean = request.body.bestOnly ?? false;\n\n const loadStartTime = Date.now();\n const { pdServices, bsComponents } = await loadBothSources({\n catalogApi: catalogApi!,\n });\n\n const filteredPdServices = account\n ? pdServices.filter(service => service.account === account)\n : pdServices;\n\n const loadTime = Date.now() - loadStartTime;\n\n const matchStartTime = Date.now();\n const matchingConfig: MatchingConfig = { threshold };\n let matches = findMatches(filteredPdServices, bsComponents, matchingConfig);\n\n if (bestOnly) {\n matches = filterToBestMatchPerService(matches);\n }\n\n const matchTime = Date.now() - matchStartTime;\n\n const totalComparisons = filteredPdServices.length * bsComponents.length;\n const exactMatches = matches.filter(m => m.score === 100).length;\n const highConfidence = matches.filter(\n m => m.score >= 90 && m.score < 100,\n ).length;\n const mediumConfidence = matches.filter(\n m => m.score >= 80 && m.score < 90,\n ).length;\n\n const getConfidenceLevel = (\n score: number,\n ): 'exact' | 'high' | 'medium' | 'low' => {\n if (score === 100) return 'exact';\n if (score >= 90) return 'high';\n if (score >= 80) return 'medium';\n return 'low';\n };\n\n response.json({\n matches: matches.map(m => ({\n pagerDutyService: {\n serviceId: m.pagerDutyService.sourceId,\n name: m.pagerDutyService.rawName,\n team: m.pagerDutyService.teamName,\n account: m.pagerDutyService.account,\n },\n backstageComponent: {\n entityRef: m.backstageComponent.sourceId,\n name: m.backstageComponent.rawName,\n owner: m.backstageComponent.teamName,\n },\n score: m.score,\n confidence: getConfidenceLevel(m.score),\n scoreBreakdown: m.scoreBreakdown,\n })),\n statistics: {\n totalPagerDutyServices: filteredPdServices.length,\n totalBackstageComponents: bsComponents.length,\n totalPossibleComparisons: totalComparisons,\n matchesFound: matches.length,\n exactMatches,\n highConfidenceMatches: highConfidence,\n mediumConfidenceMatches: mediumConfidence,\n threshold,\n loadTimeMs: loadTime,\n matchTimeMs: matchTime,\n totalTimeMs: loadTime + matchTime,\n },\n });\n } catch (error) {\n logger.error(`Auto-match failed: ${error}`);\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n } else if (error instanceof ServiceLoadError) {\n response.status(503).json({\n error: 'Service temporarily unavailable',\n message: error.message,\n });\n } else {\n response.status(500).json({\n error: 'Auto-match failed',\n message: error instanceof Error ? error.message : String(error),\n });\n }\n }\n });\n\n // GET /escalation_policies\n router.get('/escalation_policies', async (_, response) => {\n try {\n let escalationPolicyList = await getAllEscalationPolicies();\n\n // sort the escalation policies by account and name\n escalationPolicyList = escalationPolicyList.sort((a, b) => {\n if (a.account === b.account) {\n return a.name.localeCompare(b.name);\n }\n return a.account!.localeCompare(b.account!);\n });\n\n const escalationPolicyDropDownOptions = escalationPolicyList.map(\n policy => {\n let policyLabel = policy.name;\n if (policy.account && policy.account !== 'default') {\n policyLabel = `(${policy.account}) ${policy.name}`;\n }\n\n return {\n label: policyLabel,\n value: policy.id,\n };\n },\n );\n\n response.json(escalationPolicyDropDownOptions);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /oncall\n router.get('/oncall-users', async (request, response) => {\n try {\n // Get the escalation policy ID from the request parameters with parameter name \"escalation_policy_ids[]\"\n const escalationPolicyId: string =\n (request.query.escalation_policy_ids as string) || '';\n const account = (request.query.account as string) || '';\n\n if (escalationPolicyId === '') {\n response\n .status(400)\n .json(\"Bad Request: 'escalation_policy_ids[]' is required\");\n return;\n }\n\n const oncallUsers = await getOncallUsers(escalationPolicyId, account);\n const onCallUsersResponse: PagerDutyOnCallUsersResponse = {\n users: oncallUsers,\n };\n\n response.json(onCallUsersResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /services/:serviceId\n router.get('/services/:serviceId', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n if (serviceId === '') {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' must be provided as part of the path or 'integration_key' as a query parameter\",\n );\n return;\n }\n\n const service = await getServiceById(serviceId, account);\n const serviceResponse: PagerDutyServiceResponse = {\n service: service,\n };\n\n response.json(serviceResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /teams?account=:account\n router.get('/teams', async (request, response) => {\n try {\n const account = request.query.account as string | undefined;\n const teams = await getAllTeams(account);\n response.json(teams);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n\n // GET /services - Unified endpoint for all service queries\n // Query params:\n // - integration_key: fetch service by integration key\n // - team_id, query, limit, account: fetch filtered services\n // - no params: fetch all services\n router.get('/services', async (request, response) => {\n try {\n const integrationKey = request.query.integration_key as string | undefined;\n const teamId = request.query.team_id as string | undefined;\n const query = request.query.query as string | undefined;\n const limit = request.query.limit\n ? parseInt(request.query.limit as string, 10)\n : undefined;\n const account = request.query.account as string | undefined;\n\n // Case 1: Fetch by integration key\n if (integrationKey) {\n const service = await getServiceByIntegrationKey(\n integrationKey,\n account || '',\n );\n const serviceResponse: PagerDutyServiceResponse = {\n service: service,\n };\n response.json(serviceResponse);\n return;\n }\n\n // Case 2: Fetch filtered services (if team_id, query, or limit provided)\n if (teamId || query || limit) {\n const teamIdsArray: string[] | undefined = teamId ? [teamId] : undefined;\n const services = await getFilteredServices(\n teamIdsArray,\n query,\n limit || 100,\n account,\n );\n response.json(services);\n return;\n }\n\n // Case 3: Fetch all services (default)\n const services = await getAllServices();\n const servicesResponse: PagerDutyServicesResponse = {\n services: services,\n };\n response.json(servicesResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n } else {\n logger.error(\n `Unexpected error occurred while processing request: ${error}`,\n );\n response.status(500).json({\n errors: [error instanceof Error ? error.message : String(error)],\n });\n }\n }\n });\n\n // POST /services/:serviceId/integration/:vendorId\n router.post(\n '/services/:serviceId/integration/:vendorId',\n async (request, response) => {\n try {\n const serviceId: string = request.params.serviceId || '';\n const vendorId: string = request.params.vendorId || '';\n const account = (request.query.account as string) || '';\n\n if (serviceId === '' || vendorId === '') {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' and ':vendorId' must be provided as part of the path\",\n );\n return;\n }\n\n const integrationKey = await createServiceIntegration({\n serviceId,\n vendorId,\n account,\n });\n\n response.json(integrationKey);\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // GET /services/:serviceId/change-events\n router.get(\n '/services/:serviceId/change-events',\n async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n const changeEvents = await getChangeEvents(serviceId, account);\n const changeEventsResponse: PagerDutyChangeEventsResponse = {\n change_events: changeEvents,\n };\n\n response.json(changeEventsResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // GET /services/:serviceId/incidents\n router.get('/services/:serviceId/incidents', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n const incidents = await getIncidents(serviceId, account);\n const incidentsResponse: PagerDutyIncidentsResponse = {\n incidents,\n };\n\n response.json(incidentsResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /services/:serviceId/standards\n router.get('/services/:serviceId/standards', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n const serviceStandards = await getServiceStandards(serviceId, account);\n const serviceStandardsResponse: PagerDutyServiceStandardsResponse = {\n standards: serviceStandards,\n };\n\n response.json(serviceStandardsResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /services/:serviceId/metrics\n router.get('/services/:serviceId/metrics', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n const metrics = await getServiceMetrics(serviceId, account);\n\n const metricsResponse: PagerDutyServiceMetricsResponse = {\n metrics: metrics,\n };\n\n response.json(metricsResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /accounts\n router.get('/accounts', async (_, response) => {\n try {\n const accountsConfig = config.getOptional('pagerDuty.accounts') as\n | Array<{\n id: string;\n isDefault?: boolean;\n }>\n | undefined;\n\n if (accountsConfig && accountsConfig.length > 0) {\n const accounts = accountsConfig.map(account => ({\n id: account.id,\n isDefault: account.isDefault || false,\n }));\n response.status(200).json({ accounts });\n } else {\n response.status(200).json({ accounts: [] });\n }\n } catch (error) {\n logger.error(`Failed to get accounts: ${error}`);\n response.status(500).json({ error: 'Failed to get accounts' });\n }\n });\n\n // GET /health\n router.get('/health', async (_, response) => {\n response.status(200).json({ status: 'ok' });\n });\n\n // Add error handler\n router.use(errorHandler());\n\n // Return the router\n return router;\n}\n"],"names":["auth","createLegacyAuthAdapters","loadAuthConfig","loadPagerDutyEndpointsFromConfig","Router","express","removeServiceRelationsFromService","HttpError","addServiceRelationsToService","getServiceRelationshipsById","getServiceById","createServiceIntegration","CatalogEntityUtils.createComponentEntitiesReferenceDict","getAllServices","MappingsController.getMappingEntities","loadBothSources","findMatches","filterToBestMatchPerService","ServiceLoadError","getAllEscalationPolicies","getOncallUsers","getAllTeams","getServiceByIntegrationKey","services","getFilteredServices","getChangeEvents","getIncidents","getServiceStandards","getServiceMetrics","errorHandler"],"mappings":"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"}
1
+ {"version":3,"file":"router.cjs.js","sources":["../../src/service/router.ts"],"sourcesContent":["import {\n AuthService,\n CacheService,\n DiscoveryService,\n LoggerService,\n RootConfigService,\n} from '@backstage/backend-plugin-api';\nimport {\n getAllEscalationPolicies,\n getChangeEvents,\n getIncidents,\n getOncallUsers,\n getServiceById,\n getServiceByIntegrationKey,\n getServiceStandards,\n getServiceMetrics,\n getAllServices,\n getAllTeams,\n getFilteredServices,\n loadPagerDutyEndpointsFromConfig,\n createServiceIntegration,\n getServiceRelationshipsById,\n addServiceRelationsToService,\n removeServiceRelationsFromService,\n} from '../apis/pagerduty';\nimport { createAutoMatchRunner } from '../services/autoMatchRunner';\nimport { AutoMatchJobRegistry } from '../services/autoMatchJobs';\nimport {\n HttpError,\n PagerDutyChangeEventsResponse,\n PagerDutyIncidentsResponse,\n PagerDutyOnCallUsersResponse,\n PagerDutyServiceResponse,\n PagerDutyServiceStandardsResponse,\n PagerDutyServiceMetricsResponse,\n PagerDutyServicesResponse,\n PagerDutyEntityMapping,\n PagerDutyEntityMappingsResponse,\n PagerDutyService,\n PagerDutyServiceDependency,\n PagerDutySetting,\n} from '@pagerduty/backstage-plugin-common';\nimport { loadAuthConfig } from '../auth/auth';\nimport {\n PagerDutyBackendStore,\n RawDbEntityResultRow,\n} from '../db/PagerDutyBackendDatabase';\nimport * as express from 'express';\nimport Router from 'express-promise-router';\nimport type { CatalogApi, GetEntitiesResponse } from '@backstage/catalog-client';\n\nimport * as MappingsController from '../controllers/mappings-controller';\nimport * as CatalogEntityUtils from '../utils/catalog-entity';\nimport { MiddlewareFactory } from '@backstage/backend-defaults/rootHttpRouter';\n\nexport interface RouterOptions {\n logger: LoggerService;\n config: RootConfigService;\n store: PagerDutyBackendStore;\n discovery: DiscoveryService;\n auth: AuthService;\n catalogApi?: CatalogApi;\n cache: CacheService;\n}\n\nexport type Annotations = {\n 'pagerduty.com/integration-key': string;\n 'pagerduty.com/service-id': string;\n 'pagerduty.com/account': string;\n};\n\nexport async function buildEntityMappingsResponse(\n entityMappings: RawDbEntityResultRow[],\n componentEntitiesDict: Record<\n string,\n {\n ref: string;\n name: string;\n }\n >,\n componentEntities: GetEntitiesResponse,\n pagerDutyServices: PagerDutyService[],\n): Promise<PagerDutyEntityMappingsResponse> {\n const result: PagerDutyEntityMappingsResponse = {\n mappings: [],\n };\n\n pagerDutyServices.forEach(service => {\n // Check for service mapping annotation in any entity config file and get the entity ref\n const entityRef = componentEntitiesDict[service.id]?.ref;\n const entityName = componentEntitiesDict[service.id]?.name;\n\n // Check if the service is mapped to an entity in the database\n const entityMapping = entityMappings.find(\n mapping => mapping.serviceId === service.id,\n );\n\n if (entityMapping) {\n if (entityRef === undefined) {\n if (\n entityMapping.entityRef === '' ||\n entityMapping.entityRef === undefined\n ) {\n result.mappings.push({\n entityRef: '',\n entityName: '',\n integrationKey: entityMapping.integrationKey,\n serviceId: entityMapping.serviceId,\n status: 'NotMapped',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n } else {\n const entityRefName =\n componentEntities.items.find(\n entity =>\n `${entity.kind}:${entity.metadata.namespace}/${entity.metadata.name}`.toLowerCase() ===\n entityMapping.entityRef,\n )?.metadata.name ?? '';\n\n result.mappings.push({\n entityRef: entityMapping.entityRef,\n entityName: entityRefName,\n serviceId: entityMapping.serviceId,\n integrationKey: entityMapping.integrationKey,\n status: 'OutOfSync',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n }\n } else if (entityRef !== entityMapping.entityRef) {\n const entityRefName =\n componentEntities.items.find(\n entity =>\n `${entity.kind}:${entity.metadata.namespace}/${entity.metadata.name}`.toLowerCase() ===\n entityMapping.entityRef,\n )?.metadata.name ?? '';\n\n result.mappings.push({\n entityRef:\n entityMapping.entityRef !== '' ? entityMapping.entityRef : '',\n entityName: entityMapping.entityRef !== '' ? entityRefName : '',\n serviceId: entityMapping.serviceId,\n integrationKey: entityMapping.integrationKey,\n status: 'OutOfSync',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n } else if (entityRef === entityMapping.entityRef) {\n result.mappings.push({\n entityRef:\n entityMapping.entityRef !== '' ? entityMapping.entityRef : '',\n entityName: entityMapping.entityRef !== '' ? entityName : '',\n serviceId: entityMapping.serviceId,\n integrationKey: entityMapping.integrationKey,\n status: 'InSync',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n }\n } else {\n const backstageVendorId = 'PRO19CT';\n const backstageIntegrationKey =\n service.integrations?.find(\n integration => integration.vendor?.id === backstageVendorId,\n )?.integration_key ?? '';\n\n if (entityRef !== undefined) {\n result.mappings.push({\n entityRef: entityRef,\n entityName: entityName,\n serviceId: service.id,\n integrationKey: backstageIntegrationKey,\n status: 'InSync',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n } else {\n result.mappings.push({\n entityRef: '',\n entityName: '',\n serviceId: service.id,\n integrationKey: backstageIntegrationKey,\n status: 'NotMapped',\n serviceName: service.name,\n team: service.teams?.[0]?.name ?? '',\n escalationPolicy:\n service.escalation_policy !== undefined\n ? service.escalation_policy.name\n : '',\n serviceUrl: service.html_url,\n account: service.account,\n });\n }\n }\n });\n\n const sortedResult = result.mappings.sort((a, b) => {\n if (a.serviceName! < b.serviceName!) {\n return -1;\n } else if (a.serviceName! > b.serviceName!) {\n return 1;\n }\n return 0;\n });\n\n result.mappings = sortedResult;\n\n return result;\n}\n\nexport async function createRouter(\n options: RouterOptions,\n): Promise<express.Router> {\n const { logger, config, store, catalogApi, cache } = options;\n\n if (!catalogApi) {\n throw new Error('Catalog API is required to start the PagerDuty plugin backend');\n }\n\n if (!cache) {\n throw new Error('Cache service is required to start the PagerDuty plugin backend');\n }\n\n // Get authentication Config\n await loadAuthConfig(config, logger);\n\n // Get optional PagerDuty custom endpoints from config\n loadPagerDutyEndpointsFromConfig(config, logger);\n\n // Create the router\n const router = Router();\n router.use(express.json());\n\n const runAutoMatch = createAutoMatchRunner(catalogApi);\n const autoMatchJobs = new AutoMatchJobRegistry(cache, runAutoMatch);\n\n // DELETE /dependencies/service/:serviceId\n router.delete(\n '/dependencies/service/:serviceId',\n async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n if (serviceId === '') {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' must be provided as part of the path\",\n );\n return;\n }\n\n const dependencies: string[] =\n Object.keys(request.body).length === 0 ? [] : request.body;\n if (!dependencies || dependencies.length === 0) {\n response\n .status(400)\n .json(\n \"Bad Request: 'dependencies' must be provided as part of the request body\",\n );\n return;\n }\n\n const serviceRelations: PagerDutyServiceDependency[] = [];\n\n dependencies.forEach(async dependency => {\n serviceRelations.push({\n supporting_service: {\n id: dependency,\n type: 'service',\n },\n dependent_service: {\n id: serviceId,\n type: 'service',\n },\n });\n });\n\n await removeServiceRelationsFromService(serviceRelations, account);\n\n response.sendStatus(200);\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // POST /dependencies/service/:serviceId\n router.post('/dependencies/service/:serviceId', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n if (serviceId === '') {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' must be provided as part of the path\",\n );\n return;\n }\n\n const dependencies: string[] =\n Object.keys(request.body).length === 0 ? [] : request.body;\n if (!dependencies || dependencies.length === 0) {\n response\n .status(400)\n .json(\n \"Bad Request: 'dependencies' must be provided as part of the request body\",\n );\n return;\n }\n\n const serviceRelations: PagerDutyServiceDependency[] = [];\n\n dependencies.forEach(async dependency => {\n serviceRelations.push({\n supporting_service: {\n id: dependency,\n type: 'service',\n },\n dependent_service: {\n id: serviceId,\n type: 'service',\n },\n });\n });\n\n await addServiceRelationsToService(serviceRelations, account);\n\n response.sendStatus(200);\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n router.get('/dependencies/service/:serviceId', async (request, response) => {\n try {\n const serviceId = request.params.serviceId;\n const account = (request.query.account as string) || '';\n\n if (serviceId) {\n const serviceRelationships: PagerDutyServiceDependency[] =\n await getServiceRelationshipsById(serviceId, account);\n\n if (serviceRelationships) {\n response.json({\n relationships: serviceRelationships,\n });\n }\n } else {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' must be provided as part of the path\",\n );\n }\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /catalog/entity/:entityRef\n router.get(\n '/catalog/entity/:type/:namespace/:name',\n async (request, response) => {\n const type = request.params.type;\n const namespace = request.params.namespace;\n const name = request.params.name;\n\n try {\n if (type && namespace && name) {\n const entityRef = `${type}:${namespace}/${name}`.toLowerCase();\n const foundEntity = await catalogApi?.getEntityByRef(entityRef);\n\n if (foundEntity) {\n response.json(\n foundEntity.metadata.annotations?.['pagerduty.com/service-id'],\n );\n } else {\n response.status(404);\n }\n } else {\n response\n .status(400)\n .json(\n \"Bad Request: ':entityRef' must be provided as part of the path\",\n );\n }\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // POST /settings\n router.post('/settings', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const settings: PagerDutySetting[] = request.body;\n\n // For each setting, update or insert the value in the database\n await Promise.all(\n settings.map(async setting => {\n if (setting.id === undefined || setting.value === undefined) {\n response\n .status(400)\n .json(\"Bad Request: 'id' and 'value' are required\");\n return;\n }\n\n if (!isValidSetting(setting.value)) {\n response\n .status(400)\n .json(\n \"Bad Request: 'value' is invalid. Valid options are 'backstage', 'pagerduty', 'both' or 'disabled'\",\n );\n return;\n }\n\n await store.updateSetting(setting);\n }),\n );\n\n response.sendStatus(200);\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /settings/:settingId\n router.get('/settings/:settingId', async (request, response) => {\n try {\n // Get param from the request\n const settingId = request.params.settingId;\n\n // Find setting by id\n const setting = await store.findSetting(settingId);\n\n if (!setting) {\n response.status(404).json({});\n return;\n }\n\n response.json(setting);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n function isValidSetting(value: string): boolean {\n if (\n value === 'backstage' ||\n value === 'pagerduty' ||\n value === 'both' ||\n value === 'disabled'\n ) {\n return true;\n }\n\n return false;\n }\n\n // POST /mapping/entity\n router.post('/mapping/entity', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const entity: PagerDutyEntityMapping = request.body;\n\n if (!entity.serviceId) {\n response\n .status(400)\n .json(\n \"Bad Request: 'serviceId' must be provided as part of the request body\",\n );\n return;\n }\n\n // Get all the entity mappings from the database\n const entityMappings = await store.getAllEntityMappings();\n const oldMapping = entityMappings.find(\n mapping => mapping.serviceId === entity.serviceId,\n );\n\n // in case a mapping is defined and no integration exists,\n // we need to create one\n if (\n entity.entityRef !== '' &&\n (entity.integrationKey === '' || entity.integrationKey === undefined)\n ) {\n const backstageVendorId = 'PRO19CT';\n // check for existing integration key on service\n const service = await getServiceById(entity.serviceId, entity.account);\n const backstageIntegration = service.integrations?.find(\n integration => integration.vendor?.id === backstageVendorId,\n );\n\n if (!backstageIntegration) {\n // If an integration does not exist for service,\n // create it in PagerDuty\n const integrationKey = await createServiceIntegration({\n serviceId: entity.serviceId,\n vendorId: backstageVendorId,\n account: entity.account,\n });\n\n entity.integrationKey = integrationKey;\n } else {\n entity.integrationKey = backstageIntegration.integration_key;\n }\n }\n\n const entityMappingId = await store.insertEntityMapping(entity);\n\n // Refresh new and old entity unless they are empty strings\n if (entity.entityRef !== '') {\n // force refresh of new entity\n await catalogApi?.refreshEntity(entity.entityRef);\n }\n\n if (oldMapping && oldMapping.entityRef !== '') {\n // force refresh of old entity\n await catalogApi?.refreshEntity(oldMapping.entityRef);\n }\n\n response.json({\n id: entityMappingId,\n entityRef: entity.entityRef,\n integrationKey: entity.integrationKey,\n serviceId: entity.serviceId,\n status: entity.status,\n account: entity.account,\n });\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n } else {\n logger.error(\n `Unexpected error occurred while processing request: ${error}`,\n );\n response.status(500).json({\n errors: [error instanceof Error ? error.message : String(error)],\n });\n }\n }\n });\n\n // POST /mapping/entities/bulk\n router.post('/mapping/entities/bulk', async (request, response) => {\n try {\n const { mappings } = request.body;\n\n if (!Array.isArray(mappings)) {\n response.status(400).json({\n error: \"Bad Request: 'mappings' must be an array\",\n });\n return;\n }\n\n const existingMappings = await store.getAllEntityMappings();\n const existingServiceIds = new Set(\n existingMappings.map(m => m.serviceId),\n );\n\n const newMappings: PagerDutyEntityMapping[] = [];\n const skipped: PagerDutyEntityMapping[] = [];\n const errors = [];\n\n for (const entity of mappings) {\n if (!entity.serviceId) {\n errors.push({\n entityRef: entity.entityRef,\n error: 'Missing serviceId',\n });\n continue;\n }\n\n if (existingServiceIds.has(entity.serviceId)) {\n skipped.push(entity);\n continue;\n }\n\n if (\n entity.entityRef !== '' &&\n (entity.integrationKey === '' || entity.integrationKey === undefined)\n ) {\n try {\n const backstageVendorId = 'PRO19CT';\n const service = await getServiceById(\n entity.serviceId,\n entity.account,\n );\n const backstageIntegration = service.integrations?.find(\n integration => integration.vendor?.id === backstageVendorId,\n );\n\n if (!backstageIntegration) {\n const integrationKey = await createServiceIntegration({\n serviceId: entity.serviceId,\n vendorId: backstageVendorId,\n account: entity.account,\n });\n\n entity.integrationKey = integrationKey;\n } else {\n entity.integrationKey = backstageIntegration.integration_key;\n }\n } catch (error) {\n errors.push({\n entityRef: entity.entityRef,\n serviceId: entity.serviceId,\n error:\n error instanceof Error\n ? `Failed to create integration: ${error.message}`\n : 'Failed to create integration',\n });\n continue;\n }\n }\n\n newMappings.push(entity);\n }\n\n let insertedIds: string[] = [];\n if (newMappings.length > 0) {\n try {\n insertedIds = await store.bulkInsertEntityMappings(newMappings);\n\n await Promise.all(\n newMappings.map(async entity => {\n if (entity.entityRef !== '') {\n await catalogApi?.refreshEntity(entity.entityRef);\n }\n }),\n );\n } catch (error) {\n logger.error(`Bulk insert failed: ${error}`);\n response.status(500).json({\n errors: ['Bulk insert failed'],\n });\n return;\n }\n }\n\n const results = newMappings.map((entity, index) => ({\n id: insertedIds[index],\n entityRef: entity.entityRef,\n integrationKey: entity.integrationKey,\n serviceId: entity.serviceId,\n status: entity.status,\n account: entity.account,\n }));\n\n response.json({\n success: results,\n skipped: skipped.map(entity => ({\n entityRef: entity.entityRef,\n serviceId: entity.serviceId,\n reason: 'Mapping already exists for this service ID',\n })),\n errors: errors,\n total: mappings.length,\n successCount: results.length,\n skippedCount: skipped.length,\n errorCount: errors.length,\n });\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing bulk mappings: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n } else {\n logger.error(`Unexpected error: ${error}`);\n response.status(500).json({\n errors: ['Internal server error'],\n });\n }\n }\n });\n\n // DEPRECATED: GET /mapping/entity\n router.get('/mapping/entity', async (_, response) => {\n try {\n // Get all the entity mappings from the database\n const entityMappings = await store.getAllEntityMappings();\n\n // Get all the entities from the catalog\n const componentEntities = await catalogApi!.getEntities({\n filter: {\n kind: 'Component',\n },\n });\n\n // Build reference dictionary of componentEntities with serviceId as the key and entity reference and name pair as the value\n const componentEntitiesDict: Record<\n string,\n { ref: string; name: string }\n > = await CatalogEntityUtils.createComponentEntitiesReferenceDict(componentEntities);\n\n // Get all services from PagerDuty\n const pagerDutyServices = await getAllServices();\n\n // Build the response object\n const result: PagerDutyEntityMappingsResponse =\n await buildEntityMappingsResponse(\n entityMappings,\n componentEntitiesDict,\n componentEntities,\n pagerDutyServices,\n );\n\n response.json(result);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n router.post('/mapping/entities', MappingsController.getMappingEntities(store, catalogApi));\n\n // GET /mapping/entity\n router.get(\n '/mapping/entity/:type/:namespace/:name',\n async (request, response) => {\n try {\n // Get the type, namespace and entity name from the request parameters\n const entityType: string = request.params.type || '';\n const entityNamespace: string = request.params.namespace || '';\n const entityName: string = request.params.name || '';\n\n if (entityType === '' || entityNamespace === '' || entityName === '') {\n response.status(400).json('Required params not specified.');\n return;\n }\n\n const entityRef =\n `${entityType}:${entityNamespace}/${entityName}`.toLowerCase();\n\n // Get all the entity mappings from the database\n const entityMapping = await store.findEntityMappingByEntityRef(\n entityRef,\n );\n\n if (!entityMapping) {\n response\n .status(404)\n .json(`Mapping for entityRef ${entityRef} not found.`);\n return;\n }\n\n response.json({\n mapping: entityMapping,\n });\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // GET /mapping/entity/service/:serviceId\n router.get(\n '/mapping/entity/service/:serviceId',\n async (request, response) => {\n try {\n // Get the type, namespace and entity name from the request parameters\n const serviceId: string = request.params.serviceId ?? '';\n\n if (serviceId === '') {\n response.status(400).json('Required params not specified.');\n return;\n }\n\n // Get all the entity mappings from the database\n const entityMapping = await store.findEntityMappingByServiceId(\n serviceId,\n );\n\n if (!entityMapping) {\n response\n .status(404)\n .json(`Mapping for serviceId ${serviceId} not found.`);\n return;\n }\n\n response.json({\n mapping: entityMapping,\n });\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // POST /mapping/entity/auto-match/start\n router.post('/mapping/entity/auto-match/start', async (request, response) => {\n const threshold: number = request.body.threshold ?? 100;\n\n if (typeof threshold !== 'number' || threshold < 0 || threshold > 100) {\n response.status(400).json({\n error: 'Invalid threshold. Must be a number between 0 and 100.',\n });\n return;\n }\n\n const bestOnly: boolean = request.body.bestOnly ?? false;\n const team: string | undefined = request.body.team;\n const account: string | undefined = request.body.account;\n\n const job = await autoMatchJobs.start({\n threshold,\n bestOnly,\n team,\n account,\n });\n\n response.status(202).json({\n jobId: job.id,\n status: job.status,\n });\n });\n\n // GET /mapping/entity/auto-match/:jobId\n router.get('/mapping/entity/auto-match/:jobId', async (request, response) => {\n const jobId = request.params.jobId;\n const job = await autoMatchJobs.get(jobId);\n\n if (!job) {\n response.status(404).json({\n error: `Auto-match job ${jobId} not found.`,\n });\n return;\n }\n\n response.json({\n jobId: job.id,\n status: job.status,\n createdAt: job.createdAt,\n completedAt: job.completedAt,\n result: job.result,\n error: job.error,\n });\n });\n\n // GET /escalation_policies\n router.get('/escalation_policies', async (_, response) => {\n try {\n let escalationPolicyList = await getAllEscalationPolicies();\n\n // sort the escalation policies by account and name\n escalationPolicyList = escalationPolicyList.sort((a, b) => {\n if (a.account === b.account) {\n return a.name.localeCompare(b.name);\n }\n return a.account!.localeCompare(b.account!);\n });\n\n const escalationPolicyDropDownOptions = escalationPolicyList.map(\n policy => {\n let policyLabel = policy.name;\n if (policy.account && policy.account !== 'default') {\n policyLabel = `(${policy.account}) ${policy.name}`;\n }\n\n return {\n label: policyLabel,\n value: policy.id,\n };\n },\n );\n\n response.json(escalationPolicyDropDownOptions);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /oncall\n router.get('/oncall-users', async (request, response) => {\n try {\n // Get the escalation policy ID from the request parameters with parameter name \"escalation_policy_ids[]\"\n const escalationPolicyId: string =\n (request.query.escalation_policy_ids as string) || '';\n const account = (request.query.account as string) || '';\n\n if (escalationPolicyId === '') {\n response\n .status(400)\n .json(\"Bad Request: 'escalation_policy_ids[]' is required\");\n return;\n }\n\n const oncallUsers = await getOncallUsers(escalationPolicyId, account);\n const onCallUsersResponse: PagerDutyOnCallUsersResponse = {\n users: oncallUsers,\n };\n\n response.json(onCallUsersResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /services/:serviceId\n router.get('/services/:serviceId', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n if (serviceId === '') {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' must be provided as part of the path or 'integration_key' as a query parameter\",\n );\n return;\n }\n\n const service = await getServiceById(serviceId, account);\n const serviceResponse: PagerDutyServiceResponse = {\n service: service,\n };\n\n response.json(serviceResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /teams?account=:account\n router.get('/teams', async (request, response) => {\n try {\n const account = request.query.account as string | undefined;\n const teams = await getAllTeams(account);\n response.json(teams);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n\n // GET /services - Unified endpoint for all service queries\n // Query params:\n // - integration_key: fetch service by integration key\n // - team_id, query, limit, account: fetch filtered services\n // - no params: fetch all services\n router.get('/services', async (request, response) => {\n try {\n const integrationKey = request.query.integration_key as string | undefined;\n const teamId = request.query.team_id as string | undefined;\n const query = request.query.query as string | undefined;\n const limit = request.query.limit\n ? parseInt(request.query.limit as string, 10)\n : undefined;\n const account = request.query.account as string | undefined;\n\n // Case 1: Fetch by integration key\n if (integrationKey) {\n const service = await getServiceByIntegrationKey(\n integrationKey,\n account || '',\n );\n const serviceResponse: PagerDutyServiceResponse = {\n service: service,\n };\n response.json(serviceResponse);\n return;\n }\n\n // Case 2: Fetch filtered services (if team_id, query, or limit provided)\n if (teamId || query || limit) {\n const teamIdsArray: string[] | undefined = teamId ? [teamId] : undefined;\n const services = await getFilteredServices(\n teamIdsArray,\n query,\n limit || 100,\n account,\n );\n response.json(services);\n return;\n }\n\n // Case 3: Fetch all services (default)\n const services = await getAllServices();\n const servicesResponse: PagerDutyServicesResponse = {\n services: services,\n };\n response.json(servicesResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n } else {\n logger.error(\n `Unexpected error occurred while processing request: ${error}`,\n );\n response.status(500).json({\n errors: [error instanceof Error ? error.message : String(error)],\n });\n }\n }\n });\n\n // POST /services/:serviceId/integration/:vendorId\n router.post(\n '/services/:serviceId/integration/:vendorId',\n async (request, response) => {\n try {\n const serviceId: string = request.params.serviceId || '';\n const vendorId: string = request.params.vendorId || '';\n const account = (request.query.account as string) || '';\n\n if (serviceId === '' || vendorId === '') {\n response\n .status(400)\n .json(\n \"Bad Request: ':serviceId' and ':vendorId' must be provided as part of the path\",\n );\n return;\n }\n\n const integrationKey = await createServiceIntegration({\n serviceId,\n vendorId,\n account,\n });\n\n response.json(integrationKey);\n } catch (error) {\n if (error instanceof HttpError) {\n logger.error(\n `Error occurred while processing request: ${error.message}`,\n );\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // GET /services/:serviceId/change-events\n router.get(\n '/services/:serviceId/change-events',\n async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n const changeEvents = await getChangeEvents(serviceId, account);\n const changeEventsResponse: PagerDutyChangeEventsResponse = {\n change_events: changeEvents,\n };\n\n response.json(changeEventsResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n },\n );\n\n // GET /services/:serviceId/incidents\n router.get('/services/:serviceId/incidents', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n const incidents = await getIncidents(serviceId, account);\n const incidentsResponse: PagerDutyIncidentsResponse = {\n incidents,\n };\n\n response.json(incidentsResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /services/:serviceId/standards\n router.get('/services/:serviceId/standards', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n const serviceStandards = await getServiceStandards(serviceId, account);\n const serviceStandardsResponse: PagerDutyServiceStandardsResponse = {\n standards: serviceStandards,\n };\n\n response.json(serviceStandardsResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /services/:serviceId/metrics\n router.get('/services/:serviceId/metrics', async (request, response) => {\n try {\n // Get the serviceId from the request parameters\n const serviceId: string = request.params.serviceId || '';\n const account = (request.query.account as string) || '';\n\n const metrics = await getServiceMetrics(serviceId, account);\n\n const metricsResponse: PagerDutyServiceMetricsResponse = {\n metrics: metrics,\n };\n\n response.json(metricsResponse);\n } catch (error) {\n if (error instanceof HttpError) {\n response.status(error.status).json({\n errors: [`${error.message}`],\n });\n }\n }\n });\n\n // GET /accounts\n router.get('/accounts', async (_, response) => {\n try {\n const accountsConfig = config.getOptional('pagerDuty.accounts') as\n | Array<{\n id: string;\n isDefault?: boolean;\n }>\n | undefined;\n\n if (accountsConfig && accountsConfig.length > 0) {\n const accounts = accountsConfig.map(account => ({\n id: account.id,\n isDefault: account.isDefault || false,\n }));\n response.status(200).json({ accounts });\n } else {\n response.status(200).json({ accounts: [] });\n }\n } catch (error) {\n logger.error(`Failed to get accounts: ${error}`);\n response.status(500).json({ error: 'Failed to get accounts' });\n }\n });\n\n // GET /health\n router.get('/health', async (_, response) => {\n response.status(200).json({ status: 'ok' });\n });\n\n // Add error handler\n router.use(MiddlewareFactory.create({ config, logger }).error());\n\n // Return the router\n return router;\n}\n"],"names":["loadAuthConfig","loadPagerDutyEndpointsFromConfig","Router","express","createAutoMatchRunner","autoMatchJobs","AutoMatchJobRegistry","removeServiceRelationsFromService","HttpError","addServiceRelationsToService","getServiceRelationshipsById","getServiceById","createServiceIntegration","CatalogEntityUtils.createComponentEntitiesReferenceDict","getAllServices","MappingsController.getMappingEntities","getAllEscalationPolicies","getOncallUsers","getAllTeams","getServiceByIntegrationKey","services","getFilteredServices","getChangeEvents","getIncidents","getServiceStandards","getServiceMetrics","MiddlewareFactory"],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ var uuid = require('uuid');
4
+
5
+ const JOB_TTL_MS = 30 * 60 * 1e3;
6
+ const KEY_PREFIX = "auto-match-job:";
7
+ const key = (id) => `${KEY_PREFIX}${id}`;
8
+ class AutoMatchJobRegistry {
9
+ constructor(cache, runner, ttlMs = JOB_TTL_MS) {
10
+ this.cache = cache;
11
+ this.runner = runner;
12
+ this.ttlMs = ttlMs;
13
+ }
14
+ async start(params) {
15
+ const job = {
16
+ id: uuid.v4(),
17
+ status: "pending",
18
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
19
+ };
20
+ await this.write(job);
21
+ void this.execute(job, params);
22
+ return job;
23
+ }
24
+ async get(jobId) {
25
+ return await this.cache.get(key(jobId));
26
+ }
27
+ async write(job) {
28
+ await this.cache.set(key(job.id), job, { ttl: this.ttlMs });
29
+ }
30
+ async execute(job, params) {
31
+ const running = { ...job, status: "running" };
32
+ await this.write(running);
33
+ try {
34
+ const result = await this.runner(params);
35
+ await this.write({
36
+ ...running,
37
+ status: "completed",
38
+ result,
39
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
40
+ });
41
+ } catch (error) {
42
+ await this.write({
43
+ ...running,
44
+ status: "failed",
45
+ error: error instanceof Error ? error.message : String(error),
46
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
47
+ });
48
+ }
49
+ }
50
+ }
51
+
52
+ exports.AutoMatchJobRegistry = AutoMatchJobRegistry;
53
+ //# sourceMappingURL=autoMatchJobs.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoMatchJobs.cjs.js","sources":["../../src/services/autoMatchJobs.ts"],"sourcesContent":["import { v4 as uuid } from 'uuid';\nimport { CacheService } from '@backstage/backend-plugin-api';\nimport {\n AutoMatchEntityMappingsResponse,\n AutoMatchJobStatus,\n} from '@pagerduty/backstage-plugin-common';\n\nexport interface AutoMatchJob {\n id: string;\n status: AutoMatchJobStatus;\n createdAt: string;\n completedAt?: string;\n result?: AutoMatchEntityMappingsResponse;\n error?: string;\n}\n\nexport interface AutoMatchJobParams {\n threshold: number;\n bestOnly: boolean;\n team?: string;\n account?: string;\n}\n\nexport type AutoMatchJobRunner = (\n params: AutoMatchJobParams,\n) => Promise<AutoMatchEntityMappingsResponse>;\n\nconst JOB_TTL_MS = 30 * 60 * 1000;\nconst KEY_PREFIX = 'auto-match-job:';\n\nconst key = (id: string) => `${KEY_PREFIX}${id}`;\n\nexport class AutoMatchJobRegistry {\n constructor(\n private readonly cache: CacheService,\n private readonly runner: AutoMatchJobRunner,\n private readonly ttlMs: number = JOB_TTL_MS,\n ) {}\n\n async start(params: AutoMatchJobParams): Promise<AutoMatchJob> {\n const job: AutoMatchJob = {\n id: uuid(),\n status: 'pending',\n createdAt: new Date().toISOString(),\n };\n await this.write(job);\n\n // Kick off execution without awaiting.\n void this.execute(job, params);\n\n return job;\n }\n\n async get(jobId: string): Promise<AutoMatchJob | undefined> {\n return (await this.cache.get(key(jobId))) as AutoMatchJob | undefined;\n }\n\n private async write(job: AutoMatchJob): Promise<void> {\n await this.cache.set(key(job.id), job as unknown as Parameters<CacheService['set']>[1], { ttl: this.ttlMs });\n }\n\n private async execute(\n job: AutoMatchJob,\n params: AutoMatchJobParams,\n ): Promise<void> {\n const running: AutoMatchJob = { ...job, status: 'running' };\n await this.write(running);\n\n try {\n const result = await this.runner(params);\n await this.write({\n ...running,\n status: 'completed',\n result,\n completedAt: new Date().toISOString(),\n });\n } catch (error) {\n await this.write({\n ...running,\n status: 'failed',\n error: error instanceof Error ? error.message : String(error),\n completedAt: new Date().toISOString(),\n });\n }\n }\n}\n"],"names":["uuid"],"mappings":";;;;AA2BA,MAAM,UAAA,GAAa,KAAK,EAAA,GAAK,GAAA;AAC7B,MAAM,UAAA,GAAa,iBAAA;AAEnB,MAAM,MAAM,CAAC,EAAA,KAAe,CAAA,EAAG,UAAU,GAAG,EAAE,CAAA,CAAA;AAEvC,MAAM,oBAAA,CAAqB;AAAA,EAChC,WAAA,CACmB,KAAA,EACA,MAAA,EACA,KAAA,GAAgB,UAAA,EACjC;AAHiB,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAAA,EAChB;AAAA,EAEH,MAAM,MAAM,MAAA,EAAmD;AAC7D,IAAA,MAAM,GAAA,GAAoB;AAAA,MACxB,IAAIA,OAAA,EAAK;AAAA,MACT,MAAA,EAAQ,SAAA;AAAA,MACR,SAAA,EAAA,iBAAW,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,KACpC;AACA,IAAA,MAAM,IAAA,CAAK,MAAM,GAAG,CAAA;AAGpB,IAAA,KAAK,IAAA,CAAK,OAAA,CAAQ,GAAA,EAAK,MAAM,CAAA;AAE7B,IAAA,OAAO,GAAA;AAAA,EACT;AAAA,EAEA,MAAM,IAAI,KAAA,EAAkD;AAC1D,IAAA,OAAQ,MAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,KAAK,CAAC,CAAA;AAAA,EACzC;AAAA,EAEA,MAAc,MAAM,GAAA,EAAkC;AACpD,IAAA,MAAM,IAAA,CAAK,KAAA,CAAM,GAAA,CAAI,GAAA,CAAI,GAAA,CAAI,EAAE,CAAA,EAAG,GAAA,EAAsD,EAAE,GAAA,EAAK,IAAA,CAAK,KAAA,EAAO,CAAA;AAAA,EAC7G;AAAA,EAEA,MAAc,OAAA,CACZ,GAAA,EACA,MAAA,EACe;AACf,IAAA,MAAM,OAAA,GAAwB,EAAE,GAAG,GAAA,EAAK,QAAQ,SAAA,EAAU;AAC1D,IAAA,MAAM,IAAA,CAAK,MAAM,OAAO,CAAA;AAExB,IAAA,IAAI;AACF,MAAA,MAAM,MAAA,GAAS,MAAM,IAAA,CAAK,MAAA,CAAO,MAAM,CAAA;AACvC,MAAA,MAAM,KAAK,KAAA,CAAM;AAAA,QACf,GAAG,OAAA;AAAA,QACH,MAAA,EAAQ,WAAA;AAAA,QACR,MAAA;AAAA,QACA,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,OACrC,CAAA;AAAA,IACH,SAAS,KAAA,EAAO;AACd,MAAA,MAAM,KAAK,KAAA,CAAM;AAAA,QACf,GAAG,OAAA;AAAA,QACH,MAAA,EAAQ,QAAA;AAAA,QACR,OAAO,KAAA,YAAiB,KAAA,GAAQ,KAAA,CAAM,OAAA,GAAU,OAAO,KAAK,CAAA;AAAA,QAC5D,WAAA,EAAA,iBAAa,IAAI,IAAA,EAAK,EAAE,WAAA;AAAY,OACrC,CAAA;AAAA,IACH;AAAA,EACF;AACF;;;;"}
@@ -0,0 +1,72 @@
1
+ 'use strict';
2
+
3
+ var dataLoader = require('./dataLoader.cjs.js');
4
+ var matchingEngine = require('./matchingEngine.cjs.js');
5
+
6
+ const getConfidenceLevel = (score) => {
7
+ if (score === 100) return "exact";
8
+ if (score >= 90) return "high";
9
+ if (score >= 80) return "medium";
10
+ return "low";
11
+ };
12
+ function createAutoMatchRunner(catalogApi) {
13
+ return async function runAutoMatch(params) {
14
+ const { threshold, bestOnly, team, account } = params;
15
+ const loadStartTime = Date.now();
16
+ const { pdServices, bsComponents } = await dataLoader.loadBothSources({
17
+ catalogApi,
18
+ teamFilter: team
19
+ });
20
+ const filteredPdServices = account ? pdServices.filter((service) => service.account === account) : pdServices;
21
+ const loadTime = Date.now() - loadStartTime;
22
+ const matchStartTime = Date.now();
23
+ const matchingConfig = { threshold };
24
+ let matches = matchingEngine.findMatches(filteredPdServices, bsComponents, matchingConfig);
25
+ if (bestOnly) {
26
+ matches = matchingEngine.filterToBestMatchPerService(matches);
27
+ }
28
+ const matchTime = Date.now() - matchStartTime;
29
+ const totalComparisons = filteredPdServices.length * bsComponents.length;
30
+ const exactMatches = matches.filter((m) => m.score === 100).length;
31
+ const highConfidence = matches.filter(
32
+ (m) => m.score >= 90 && m.score < 100
33
+ ).length;
34
+ const mediumConfidence = matches.filter(
35
+ (m) => m.score >= 80 && m.score < 90
36
+ ).length;
37
+ return {
38
+ matches: matches.map((m) => ({
39
+ pagerDutyService: {
40
+ serviceId: m.pagerDutyService.sourceId,
41
+ name: m.pagerDutyService.rawName,
42
+ team: m.pagerDutyService.teamName,
43
+ account: m.pagerDutyService.account
44
+ },
45
+ backstageComponent: {
46
+ entityRef: m.backstageComponent.sourceId,
47
+ name: m.backstageComponent.rawName,
48
+ owner: m.backstageComponent.teamName
49
+ },
50
+ score: m.score,
51
+ confidence: getConfidenceLevel(m.score),
52
+ scoreBreakdown: m.scoreBreakdown
53
+ })),
54
+ statistics: {
55
+ totalPagerDutyServices: filteredPdServices.length,
56
+ totalBackstageComponents: bsComponents.length,
57
+ totalPossibleComparisons: totalComparisons,
58
+ matchesFound: matches.length,
59
+ exactMatches,
60
+ highConfidenceMatches: highConfidence,
61
+ mediumConfidenceMatches: mediumConfidence,
62
+ threshold,
63
+ loadTimeMs: loadTime,
64
+ matchTimeMs: matchTime,
65
+ totalTimeMs: loadTime + matchTime
66
+ }
67
+ };
68
+ };
69
+ }
70
+
71
+ exports.createAutoMatchRunner = createAutoMatchRunner;
72
+ //# sourceMappingURL=autoMatchRunner.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoMatchRunner.cjs.js","sources":["../../src/services/autoMatchRunner.ts"],"sourcesContent":["import type { CatalogApi } from '@backstage/catalog-client';\nimport { AutoMatchEntityMappingsResponse } from '@pagerduty/backstage-plugin-common';\nimport { loadBothSources } from './dataLoader';\nimport {\n findMatches,\n filterToBestMatchPerService,\n type MatchingConfig,\n} from './matchingEngine';\nimport type { AutoMatchJobParams } from './autoMatchJobs';\n\nconst getConfidenceLevel = (\n score: number,\n): 'exact' | 'high' | 'medium' | 'low' => {\n if (score === 100) return 'exact';\n if (score >= 90) return 'high';\n if (score >= 80) return 'medium';\n return 'low';\n};\n\nexport function createAutoMatchRunner(catalogApi: CatalogApi) {\n return async function runAutoMatch(\n params: AutoMatchJobParams,\n ): Promise<AutoMatchEntityMappingsResponse> {\n const { threshold, bestOnly, team, account } = params;\n\n const loadStartTime = Date.now();\n const { pdServices, bsComponents } = await loadBothSources({\n catalogApi,\n teamFilter: team,\n });\n\n const filteredPdServices = account\n ? pdServices.filter(service => service.account === account)\n : pdServices;\n\n const loadTime = Date.now() - loadStartTime;\n\n const matchStartTime = Date.now();\n const matchingConfig: MatchingConfig = { threshold };\n let matches = findMatches(filteredPdServices, bsComponents, matchingConfig);\n\n if (bestOnly) {\n matches = filterToBestMatchPerService(matches);\n }\n\n const matchTime = Date.now() - matchStartTime;\n\n const totalComparisons = filteredPdServices.length * bsComponents.length;\n const exactMatches = matches.filter(m => m.score === 100).length;\n const highConfidence = matches.filter(\n m => m.score >= 90 && m.score < 100,\n ).length;\n const mediumConfidence = matches.filter(\n m => m.score >= 80 && m.score < 90,\n ).length;\n\n return {\n matches: matches.map(m => ({\n pagerDutyService: {\n serviceId: m.pagerDutyService.sourceId,\n name: m.pagerDutyService.rawName,\n team: m.pagerDutyService.teamName,\n account: m.pagerDutyService.account,\n },\n backstageComponent: {\n entityRef: m.backstageComponent.sourceId,\n name: m.backstageComponent.rawName,\n owner: m.backstageComponent.teamName,\n },\n score: m.score,\n confidence: getConfidenceLevel(m.score),\n scoreBreakdown: m.scoreBreakdown,\n })),\n statistics: {\n totalPagerDutyServices: filteredPdServices.length,\n totalBackstageComponents: bsComponents.length,\n totalPossibleComparisons: totalComparisons,\n matchesFound: matches.length,\n exactMatches,\n highConfidenceMatches: highConfidence,\n mediumConfidenceMatches: mediumConfidence,\n threshold,\n loadTimeMs: loadTime,\n matchTimeMs: matchTime,\n totalTimeMs: loadTime + matchTime,\n },\n };\n };\n}\n"],"names":["loadBothSources","findMatches","filterToBestMatchPerService"],"mappings":"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"}
@@ -29,13 +29,20 @@ async function loadPagerDutyServices() {
29
29
  }
30
30
  }
31
31
  async function loadBackstageComponents({
32
- catalogApi
32
+ catalogApi,
33
+ teamFilter
33
34
  }) {
34
35
  try {
36
+ const filter = {
37
+ kind: "Component"
38
+ };
39
+ if (teamFilter) {
40
+ const bare = teamFilter.replace(/^group:[^/]+\//i, "");
41
+ const full = teamFilter.includes(":") ? teamFilter : `group:default/${teamFilter}`;
42
+ filter["spec.owner"] = bare === full ? [bare] : [bare, full];
43
+ }
35
44
  const response = await catalogApi.getEntities({
36
- filter: {
37
- kind: "Component"
38
- }
45
+ filter
39
46
  });
40
47
  const normalizedComponents = response.items.map(
41
48
  (entity) => {
@@ -1 +1 @@
1
- {"version":3,"file":"dataLoader.cjs.js","sources":["../../src/services/dataLoader.ts"],"sourcesContent":["import { getAllServices } from '../apis/pagerduty';\nimport {\n normalizePagerDutyService,\n normalizeBackstageComponent,\n type NormalizedService,\n} from '../utils/normalization';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport type { PagerDutyService } from '@pagerduty/backstage-plugin-common';\nimport type { Entity } from '@backstage/catalog-model';\n\nexport class ServiceLoadError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ServiceLoadError';\n }\n}\n\nexport interface DataLoaderContext {\n catalogApi: CatalogApi;\n}\n\nexport interface LoadedSources {\n pdServices: NormalizedService[];\n bsComponents: NormalizedService[];\n}\n\nexport async function loadPagerDutyServices(): Promise<NormalizedService[]> {\n try {\n const services: PagerDutyService[] = await getAllServices();\n\n const normalizedServices: NormalizedService[] = services.map(service => {\n const teamName = service.teams?.[0]?.summary ?? '';\n\n return normalizePagerDutyService(\n service.name,\n teamName,\n service.id,\n service.account,\n );\n });\n\n return normalizedServices;\n } catch (error) {\n throw new ServiceLoadError(\n `Failed to load PagerDuty services: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n}\n\nexport async function loadBackstageComponents({\n catalogApi,\n}: DataLoaderContext): Promise<NormalizedService[]> {\n try {\n\n const response = await catalogApi.getEntities({\n filter: {\n kind: 'Component',\n },\n });\n\n const normalizedComponents: NormalizedService[] = response.items.map(\n (entity: Entity) => {\n const entityRef =\n `${entity.kind}:${entity.metadata.namespace}/${entity.metadata.name}`.toLowerCase();\n\n const owner =\n typeof entity.spec?.owner === 'string' ? entity.spec.owner : '';\n\n return normalizeBackstageComponent(\n entity.metadata.name,\n owner,\n entityRef,\n );\n },\n );\n\n return normalizedComponents;\n } catch (error) {\n throw new ServiceLoadError(\n `Failed to load Backstage components: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n}\n\nexport async function loadBothSources(\n context: DataLoaderContext,\n): Promise<LoadedSources> {\n const [pdServices, bsComponents] = await Promise.all([\n loadPagerDutyServices(),\n loadBackstageComponents(context),\n ]);\n\n return {\n pdServices,\n bsComponents,\n };\n}\n"],"names":["getAllServices","normalizePagerDutyService","normalizeBackstageComponent"],"mappings":";;;;;AAUO,MAAM,yBAAyB,KAAA,CAAM;AAAA,EAC1C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,EACd;AACF;AAWA,eAAsB,qBAAA,GAAsD;AAC1E,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAA+B,MAAMA,wBAAA,EAAe;AAE1D,IAAA,MAAM,kBAAA,GAA0C,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,KAAW;AACtE,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,KAAA,GAAQ,CAAC,GAAG,OAAA,IAAW,EAAA;AAEhD,MAAA,OAAOC,uCAAA;AAAA,QACL,OAAA,CAAQ,IAAA;AAAA,QACR,QAAA;AAAA,QACA,OAAA,CAAQ,EAAA;AAAA,QACR,OAAA,CAAQ;AAAA,OACV;AAAA,IACF,CAAC,CAAA;AAED,IAAA,OAAO,kBAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,gBAAA;AAAA,MACR,sCACE,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CACvD,CAAA;AAAA,KACF;AAAA,EACF;AACF;AAEA,eAAsB,uBAAA,CAAwB;AAAA,EAC5C;AACF,CAAA,EAAoD;AAClD,EAAA,IAAI;AAEF,IAAA,MAAM,QAAA,GAAW,MAAM,UAAA,CAAW,WAAA,CAAY;AAAA,MAC5C,MAAA,EAAQ;AAAA,QACN,IAAA,EAAM;AAAA;AACR,KACD,CAAA;AAED,IAAA,MAAM,oBAAA,GAA4C,SAAS,KAAA,CAAM,GAAA;AAAA,MAC/D,CAAC,MAAA,KAAmB;AAClB,QAAA,MAAM,SAAA,GACJ,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,CAAA,EAAI,MAAA,CAAO,QAAA,CAAS,IAAI,GAAG,WAAA,EAAY;AAEpF,QAAA,MAAM,KAAA,GACJ,OAAO,MAAA,CAAO,IAAA,EAAM,UAAU,QAAA,GAAW,MAAA,CAAO,KAAK,KAAA,GAAQ,EAAA;AAE/D,QAAA,OAAOC,yCAAA;AAAA,UACL,OAAO,QAAA,CAAS,IAAA;AAAA,UAChB,KAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,KACF;AAEA,IAAA,OAAO,oBAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,gBAAA;AAAA,MACR,wCACE,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CACvD,CAAA;AAAA,KACF;AAAA,EACF;AACF;AAEA,eAAsB,gBACpB,OAAA,EACwB;AACxB,EAAA,MAAM,CAAC,UAAA,EAAY,YAAY,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,IACnD,qBAAA,EAAsB;AAAA,IACtB,wBAAwB,OAAO;AAAA,GAChC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA;AAAA,GACF;AACF;;;;;;;"}
1
+ {"version":3,"file":"dataLoader.cjs.js","sources":["../../src/services/dataLoader.ts"],"sourcesContent":["import { getAllServices } from '../apis/pagerduty';\nimport {\n normalizePagerDutyService,\n normalizeBackstageComponent,\n type NormalizedService,\n} from '../utils/normalization';\nimport type { CatalogApi } from '@backstage/catalog-client';\nimport type { PagerDutyService } from '@pagerduty/backstage-plugin-common';\nimport type { Entity } from '@backstage/catalog-model';\n\nexport class ServiceLoadError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'ServiceLoadError';\n }\n}\n\nexport interface DataLoaderContext {\n catalogApi: CatalogApi;\n teamFilter?: string;\n}\n\nexport interface LoadedSources {\n pdServices: NormalizedService[];\n bsComponents: NormalizedService[];\n}\n\nexport async function loadPagerDutyServices(): Promise<NormalizedService[]> {\n try {\n const services: PagerDutyService[] = await getAllServices();\n\n const normalizedServices: NormalizedService[] = services.map(service => {\n const teamName = service.teams?.[0]?.summary ?? '';\n\n return normalizePagerDutyService(\n service.name,\n teamName,\n service.id,\n service.account,\n );\n });\n\n return normalizedServices;\n } catch (error) {\n throw new ServiceLoadError(\n `Failed to load PagerDuty services: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n}\n\nexport async function loadBackstageComponents({\n catalogApi,\n teamFilter,\n}: DataLoaderContext): Promise<NormalizedService[]> {\n try {\n const filter: Record<string, string | string[]> = {\n kind: 'Component',\n };\n\n if (teamFilter) {\n // Catalog may normalize owners to full entity refs (e.g. \"group:default/foo\")\n // or store them as plain names (\"foo\"). Accept both forms.\n const bare = teamFilter.replace(/^group:[^/]+\\//i, '');\n const full = teamFilter.includes(':') ? teamFilter : `group:default/${teamFilter}`;\n filter['spec.owner'] = bare === full ? [bare] : [bare, full];\n }\n\n const response = await catalogApi.getEntities({\n filter,\n });\n\n const normalizedComponents: NormalizedService[] = response.items.map(\n (entity: Entity) => {\n const entityRef =\n `${entity.kind}:${entity.metadata.namespace}/${entity.metadata.name}`.toLowerCase();\n\n const owner =\n typeof entity.spec?.owner === 'string' ? entity.spec.owner : '';\n\n return normalizeBackstageComponent(\n entity.metadata.name,\n owner,\n entityRef,\n );\n },\n );\n\n return normalizedComponents;\n } catch (error) {\n throw new ServiceLoadError(\n `Failed to load Backstage components: ${\n error instanceof Error ? error.message : String(error)\n }`,\n );\n }\n}\n\nexport async function loadBothSources(\n context: DataLoaderContext,\n): Promise<LoadedSources> {\n const [pdServices, bsComponents] = await Promise.all([\n loadPagerDutyServices(),\n loadBackstageComponents(context),\n ]);\n\n return {\n pdServices,\n bsComponents,\n };\n}\n"],"names":["getAllServices","normalizePagerDutyService","normalizeBackstageComponent"],"mappings":";;;;;AAUO,MAAM,yBAAyB,KAAA,CAAM;AAAA,EAC1C,YAAY,OAAA,EAAiB;AAC3B,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,kBAAA;AAAA,EACd;AACF;AAYA,eAAsB,qBAAA,GAAsD;AAC1E,EAAA,IAAI;AACF,IAAA,MAAM,QAAA,GAA+B,MAAMA,wBAAA,EAAe;AAE1D,IAAA,MAAM,kBAAA,GAA0C,QAAA,CAAS,GAAA,CAAI,CAAA,OAAA,KAAW;AACtE,MAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,KAAA,GAAQ,CAAC,GAAG,OAAA,IAAW,EAAA;AAEhD,MAAA,OAAOC,uCAAA;AAAA,QACL,OAAA,CAAQ,IAAA;AAAA,QACR,QAAA;AAAA,QACA,OAAA,CAAQ,EAAA;AAAA,QACR,OAAA,CAAQ;AAAA,OACV;AAAA,IACF,CAAC,CAAA;AAED,IAAA,OAAO,kBAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,gBAAA;AAAA,MACR,sCACE,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CACvD,CAAA;AAAA,KACF;AAAA,EACF;AACF;AAEA,eAAsB,uBAAA,CAAwB;AAAA,EAC5C,UAAA;AAAA,EACA;AACF,CAAA,EAAoD;AAClD,EAAA,IAAI;AACF,IAAA,MAAM,MAAA,GAA4C;AAAA,MAChD,IAAA,EAAM;AAAA,KACR;AAEA,IAAA,IAAI,UAAA,EAAY;AAGd,MAAA,MAAM,IAAA,GAAO,UAAA,CAAW,OAAA,CAAQ,iBAAA,EAAmB,EAAE,CAAA;AACrD,MAAA,MAAM,OAAO,UAAA,CAAW,QAAA,CAAS,GAAG,CAAA,GAAI,UAAA,GAAa,iBAAiB,UAAU,CAAA,CAAA;AAChF,MAAA,MAAA,CAAO,YAAY,IAAI,IAAA,KAAS,IAAA,GAAO,CAAC,IAAI,CAAA,GAAI,CAAC,IAAA,EAAM,IAAI,CAAA;AAAA,IAC7D;AAEA,IAAA,MAAM,QAAA,GAAW,MAAM,UAAA,CAAW,WAAA,CAAY;AAAA,MAC5C;AAAA,KACD,CAAA;AAED,IAAA,MAAM,oBAAA,GAA4C,SAAS,KAAA,CAAM,GAAA;AAAA,MAC/D,CAAC,MAAA,KAAmB;AAClB,QAAA,MAAM,SAAA,GACJ,CAAA,EAAG,MAAA,CAAO,IAAI,CAAA,CAAA,EAAI,MAAA,CAAO,QAAA,CAAS,SAAS,CAAA,CAAA,EAAI,MAAA,CAAO,QAAA,CAAS,IAAI,GAAG,WAAA,EAAY;AAEpF,QAAA,MAAM,KAAA,GACJ,OAAO,MAAA,CAAO,IAAA,EAAM,UAAU,QAAA,GAAW,MAAA,CAAO,KAAK,KAAA,GAAQ,EAAA;AAE/D,QAAA,OAAOC,yCAAA;AAAA,UACL,OAAO,QAAA,CAAS,IAAA;AAAA,UAChB,KAAA;AAAA,UACA;AAAA,SACF;AAAA,MACF;AAAA,KACF;AAEA,IAAA,OAAO,oBAAA;AAAA,EACT,SAAS,KAAA,EAAO;AACd,IAAA,MAAM,IAAI,gBAAA;AAAA,MACR,wCACE,KAAA,YAAiB,KAAA,GAAQ,MAAM,OAAA,GAAU,MAAA,CAAO,KAAK,CACvD,CAAA;AAAA,KACF;AAAA,EACF;AACF;AAEA,eAAsB,gBACpB,OAAA,EACwB;AACxB,EAAA,MAAM,CAAC,UAAA,EAAY,YAAY,CAAA,GAAI,MAAM,QAAQ,GAAA,CAAI;AAAA,IACnD,qBAAA,EAAsB;AAAA,IACtB,wBAAwB,OAAO;AAAA,GAChC,CAAA;AAED,EAAA,OAAO;AAAA,IACL,UAAA;AAAA,IACA;AAAA,GACF;AACF;;;;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pagerduty/backstage-plugin-backend",
3
- "version": "0.12.0",
3
+ "version": "0.13.0",
4
4
  "main": "dist/index.cjs.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "license": "Apache-2.0",
@@ -37,10 +37,10 @@
37
37
  "postpack": "backstage-cli package postpack"
38
38
  },
39
39
  "dependencies": {
40
- "@backstage/backend-common": "^0.25.0",
40
+ "@backstage/backend-defaults": "^0.15.1",
41
41
  "@backstage/backend-plugin-api": "^1.6.2",
42
42
  "@backstage/catalog-client": "^1.12.1",
43
- "@pagerduty/backstage-plugin-common": "~0.3.0",
43
+ "@pagerduty/backstage-plugin-common": "~0.4.0",
44
44
  "@skyra/jaro-winkler": "^1.1.1",
45
45
  "@types/express": "^4.17.6",
46
46
  "express": "^4.20.0",
@@ -51,7 +51,6 @@
51
51
  "uuid": "^9.0.1"
52
52
  },
53
53
  "devDependencies": {
54
- "@backstage/backend-defaults": "^0.15.1",
55
54
  "@backstage/backend-test-utils": "^1.10.4",
56
55
  "@backstage/cli": "^0.35.3",
57
56
  "jest-mock": "^30.0.2",