@backstage/core-app-api 1.7.0 → 1.8.0-next.1

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,28 @@
1
1
  # @backstage/core-app-api
2
2
 
3
+ ## 1.8.0-next.1
4
+
5
+ ### Minor Changes
6
+
7
+ - c89437db899: The analytics' `navigate` event will now include the route parameters as attributes of the navigate event
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies
12
+ - @backstage/core-plugin-api@1.5.1
13
+ - @backstage/config@1.0.7
14
+
15
+ ## 1.7.1-next.0
16
+
17
+ ### Patch Changes
18
+
19
+ - 42d817e76ab: Added `FrontendHostDiscovery` for config driven discovery implementation
20
+ - Updated dependencies
21
+ - @backstage/core-plugin-api@1.5.1
22
+ - @backstage/config@1.0.7
23
+ - @backstage/types@1.0.2
24
+ - @backstage/version-bridge@1.0.4
25
+
3
26
  ## 1.7.0
4
27
 
5
28
  ### Minor Changes
package/dist/index.d.ts CHANGED
@@ -411,6 +411,43 @@ declare class UrlPatternDiscovery implements DiscoveryApi {
411
411
  getBaseUrl(pluginId: string): Promise<string>;
412
412
  }
413
413
 
414
+ /**
415
+ * FrontendHostDiscovery is a config driven DiscoveryApi implementation.
416
+ * It uses the app-config to determine the url for a plugin.
417
+ *
418
+ * @public
419
+ */
420
+ declare class FrontendHostDiscovery implements DiscoveryApi {
421
+ private readonly endpoints;
422
+ private readonly defaultEndpoint;
423
+ /**
424
+ * Creates a new FrontendHostDiscovery discovery instance by reading
425
+ * the external target URL from the `discovery.endpoints` config section.
426
+ *
427
+ * eg.
428
+ * ```yaml
429
+ * discovery:
430
+ * endpoints:
431
+ * - target: https://internal.example.com/internal-catalog
432
+ * plugins: [catalog]
433
+ * - target: https://internal.example.com/secure/api/{{pluginId}}
434
+ * plugins: [auth, permissions]
435
+ * - target:
436
+ * internal: https://internal.example.com/search
437
+ * external: https://example.com/search
438
+ * plugins: [search]
439
+ * ```
440
+ *
441
+ * If a plugin is not declared in the config, the discovery will fall back to using the baseUrl with
442
+ * the provided `pathPattern` appended. The default path pattern is `"/api/{{ pluginId }}"`.
443
+ */
444
+ static fromConfig(config: Config, options?: {
445
+ pathPattern?: string;
446
+ }): FrontendHostDiscovery;
447
+ private constructor();
448
+ getBaseUrl(pluginId: string): Promise<string>;
449
+ }
450
+
414
451
  /**
415
452
  * Decorates an ErrorApi by also forwarding error messages
416
453
  * to the alertApi with an 'error' severity.
@@ -1004,4 +1041,4 @@ type FeatureFlaggedProps = {
1004
1041
  */
1005
1042
  declare const FeatureFlagged: (props: FeatureFlaggedProps) => JSX.Element;
1006
1043
 
1007
- export { AlertApiForwarder, ApiFactoryHolder, ApiFactoryRegistry, ApiFactoryScope, ApiProvider, ApiProviderProps, ApiResolver, AppComponents, AppConfigLoader, AppContext, AppIcons, AppOptions, AppRouteBinder, AppRouter, AppRouterProps, AppThemeSelector, AtlassianAuth, AuthApiCreateOptions, BackstageApp, BitbucketAuth, BitbucketServerAuth, BitbucketServerSession, BitbucketSession, BootErrorPageProps, ErrorAlerter, ErrorApiForwarder, ErrorBoundaryFallbackProps, FeatureFlagged, FeatureFlaggedProps, FetchMiddleware, FetchMiddlewares, FlatRoutes, FlatRoutesProps, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, MultipleAnalyticsApi, NoOpAnalyticsApi, OAuth2, OAuth2CreateOptions, OAuth2Session, OAuthApiCreateOptions, OAuthRequestManager, OktaAuth, OneLoginAuth, OneLoginAuthCreateOptions, SamlAuth, SignInPageProps, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
1044
+ export { AlertApiForwarder, ApiFactoryHolder, ApiFactoryRegistry, ApiFactoryScope, ApiProvider, ApiProviderProps, ApiResolver, AppComponents, AppConfigLoader, AppContext, AppIcons, AppOptions, AppRouteBinder, AppRouter, AppRouterProps, AppThemeSelector, AtlassianAuth, AuthApiCreateOptions, BackstageApp, BitbucketAuth, BitbucketServerAuth, BitbucketServerSession, BitbucketSession, BootErrorPageProps, ErrorAlerter, ErrorApiForwarder, ErrorBoundaryFallbackProps, FeatureFlagged, FeatureFlaggedProps, FetchMiddleware, FetchMiddlewares, FlatRoutes, FlatRoutesProps, FrontendHostDiscovery, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, MultipleAnalyticsApi, NoOpAnalyticsApi, OAuth2, OAuth2CreateOptions, OAuth2Session, OAuthApiCreateOptions, OAuthRequestManager, OktaAuth, OneLoginAuth, OneLoginAuthCreateOptions, SamlAuth, SignInPageProps, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
package/dist/index.esm.js CHANGED
@@ -1476,7 +1476,56 @@ class UrlPatternDiscovery {
1476
1476
  return new UrlPatternDiscovery(parts);
1477
1477
  }
1478
1478
  async getBaseUrl(pluginId) {
1479
- return this.parts.join(pluginId);
1479
+ return this.parts.join(encodeURIComponent(pluginId));
1480
+ }
1481
+ }
1482
+
1483
+ class FrontendHostDiscovery {
1484
+ constructor(endpoints, defaultEndpoint) {
1485
+ this.endpoints = endpoints;
1486
+ this.defaultEndpoint = defaultEndpoint;
1487
+ }
1488
+ /**
1489
+ * Creates a new FrontendHostDiscovery discovery instance by reading
1490
+ * the external target URL from the `discovery.endpoints` config section.
1491
+ *
1492
+ * eg.
1493
+ * ```yaml
1494
+ * discovery:
1495
+ * endpoints:
1496
+ * - target: https://internal.example.com/internal-catalog
1497
+ * plugins: [catalog]
1498
+ * - target: https://internal.example.com/secure/api/{{pluginId}}
1499
+ * plugins: [auth, permissions]
1500
+ * - target:
1501
+ * internal: https://internal.example.com/search
1502
+ * external: https://example.com/search
1503
+ * plugins: [search]
1504
+ * ```
1505
+ *
1506
+ * If a plugin is not declared in the config, the discovery will fall back to using the baseUrl with
1507
+ * the provided `pathPattern` appended. The default path pattern is `"/api/{{ pluginId }}"`.
1508
+ */
1509
+ static fromConfig(config, options) {
1510
+ var _a, _b;
1511
+ const path = (_a = options == null ? void 0 : options.pathPattern) != null ? _a : "/api/{{ pluginId }}";
1512
+ const baseUrl = config.getString("backend.baseUrl");
1513
+ const endpoints = (_b = config.getOptionalConfigArray("discovery.endpoints")) == null ? void 0 : _b.flatMap((e) => {
1514
+ const target = typeof e.get("target") === "object" ? e.getString("target.external") : e.getString("target");
1515
+ const discovery = UrlPatternDiscovery.compile(target);
1516
+ return e.getStringArray("plugins").map((pluginId) => [pluginId, discovery]);
1517
+ });
1518
+ return new FrontendHostDiscovery(
1519
+ new Map(endpoints),
1520
+ UrlPatternDiscovery.compile(`${baseUrl}${path}`)
1521
+ );
1522
+ }
1523
+ async getBaseUrl(pluginId) {
1524
+ const endpoint = this.endpoints.get(pluginId);
1525
+ if (endpoint) {
1526
+ return endpoint.getBaseUrl(pluginId);
1527
+ }
1528
+ return this.defaultEndpoint.getBaseUrl(pluginId);
1480
1529
  }
1481
1530
  }
1482
1531
 
@@ -1956,45 +2005,70 @@ function isReactRouterBeta() {
1956
2005
  }
1957
2006
 
1958
2007
  const getExtensionContext = (pathname, routes) => {
1959
- var _a, _b;
2008
+ var _a;
1960
2009
  try {
1961
2010
  const matches = matchRoutes(routes, { pathname });
1962
- const routeObject = (_a = matches == null ? void 0 : matches.filter((match) => {
2011
+ const routeMatch = matches == null ? void 0 : matches.filter((match) => {
1963
2012
  var _a2;
1964
2013
  return ((_a2 = match == null ? void 0 : match.route.routeRefs) == null ? void 0 : _a2.size) > 0;
1965
- }).pop()) == null ? void 0 : _a.route;
2014
+ }).pop();
2015
+ const routeObject = routeMatch == null ? void 0 : routeMatch.route;
1966
2016
  if (!routeObject) {
1967
- return {};
2017
+ return void 0;
1968
2018
  }
1969
2019
  let routeRef;
1970
2020
  if (routeObject.routeRefs.size === 1) {
1971
2021
  routeRef = routeObject.routeRefs.values().next().value;
1972
2022
  }
2023
+ const params = Object.entries(
2024
+ (routeMatch == null ? void 0 : routeMatch.params) || {}
2025
+ ).reduce((acc, [key, value]) => {
2026
+ if (value !== void 0) {
2027
+ acc[key] = value;
2028
+ }
2029
+ return acc;
2030
+ }, {});
1973
2031
  return {
1974
2032
  extension: "App",
1975
- pluginId: ((_b = routeObject.plugin) == null ? void 0 : _b.getId()) || "root",
1976
- ...routeRef ? { routeRef: routeRef.id } : {}
2033
+ pluginId: ((_a = routeObject.plugin) == null ? void 0 : _a.getId()) || "root",
2034
+ ...routeRef ? { routeRef: routeRef.id } : {},
2035
+ params
1977
2036
  };
1978
2037
  } catch {
1979
- return {};
2038
+ return void 0;
1980
2039
  }
1981
2040
  };
1982
2041
  const TrackNavigation = ({
1983
2042
  pathname,
1984
2043
  search,
1985
- hash
2044
+ hash,
2045
+ attributes
1986
2046
  }) => {
1987
2047
  const analytics = useAnalytics();
1988
2048
  useEffect(() => {
1989
- analytics.captureEvent("navigate", `${pathname}${search}${hash}`);
1990
- }, [analytics, pathname, search, hash]);
2049
+ analytics.captureEvent("navigate", `${pathname}${search}${hash}`, {
2050
+ attributes
2051
+ });
2052
+ }, [analytics, pathname, search, hash, attributes]);
1991
2053
  return null;
1992
2054
  };
1993
2055
  const RouteTracker = ({
1994
2056
  routeObjects
1995
2057
  }) => {
1996
2058
  const { pathname, search, hash } = useLocation();
1997
- return /* @__PURE__ */ React.createElement(AnalyticsContext, { attributes: getExtensionContext(pathname, routeObjects) }, /* @__PURE__ */ React.createElement(TrackNavigation, { pathname, search, hash }));
2059
+ const { params, ...attributes } = getExtensionContext(
2060
+ pathname,
2061
+ routeObjects
2062
+ ) || { params: {} };
2063
+ return /* @__PURE__ */ React.createElement(AnalyticsContext, { attributes }, /* @__PURE__ */ React.createElement(
2064
+ TrackNavigation,
2065
+ {
2066
+ pathname,
2067
+ search,
2068
+ hash,
2069
+ attributes: params
2070
+ }
2071
+ ));
1998
2072
  };
1999
2073
 
2000
2074
  function getBasePath(configApi) {
@@ -3263,5 +3337,5 @@ const FlatRoutes = (props) => {
3263
3337
  return useRoutes(withNotFound);
3264
3338
  };
3265
3339
 
3266
- export { AlertApiForwarder, ApiFactoryRegistry, ApiProvider, ApiResolver, AppRouter, AppThemeSelector, AtlassianAuth, BitbucketAuth, BitbucketServerAuth, ErrorAlerter, ErrorApiForwarder, FeatureFlagged, FetchMiddlewares, FlatRoutes, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, MultipleAnalyticsApi, NoOpAnalyticsApi, OAuth2, OAuthRequestManager, OktaAuth, OneLoginAuth, SamlAuth, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
3340
+ export { AlertApiForwarder, ApiFactoryRegistry, ApiProvider, ApiResolver, AppRouter, AppThemeSelector, AtlassianAuth, BitbucketAuth, BitbucketServerAuth, ErrorAlerter, ErrorApiForwarder, FeatureFlagged, FetchMiddlewares, FlatRoutes, FrontendHostDiscovery, GithubAuth, GitlabAuth, GoogleAuth, LocalStorageFeatureFlags, MicrosoftAuth, MultipleAnalyticsApi, NoOpAnalyticsApi, OAuth2, OAuthRequestManager, OktaAuth, OneLoginAuth, SamlAuth, UnhandledErrorForwarder, UrlPatternDiscovery, WebStorage, createFetchApi, createSpecializedApp, defaultConfigLoader };
3267
3341
  //# sourceMappingURL=index.esm.js.map