@backstage/core-plugin-api 1.11.1-next.0 → 1.11.2-next.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,23 @@
1
1
  # @backstage/core-plugin-api
2
2
 
3
+ ## 1.11.2-next.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 05f60e1: Refactored constructor parameter properties to explicit property declarations for compatibility with TypeScript's `erasableSyntaxOnly` setting. This internal refactoring maintains all existing functionality while ensuring TypeScript compilation compatibility.
8
+ - Updated dependencies
9
+ - @backstage/config@1.3.6-next.0
10
+ - @backstage/errors@1.2.7
11
+ - @backstage/types@1.2.2
12
+ - @backstage/version-bridge@1.0.11
13
+
14
+ ## 1.11.1
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies
19
+ - @backstage/config@1.3.5
20
+
3
21
  ## 1.11.1-next.0
4
22
 
5
23
  ### Patch Changes
@@ -10,6 +10,8 @@ const globalEvents = getOrCreateGlobalSingleton(
10
10
  );
11
11
  const routableExtensionRenderedEvent = "_ROUTABLE-EXTENSION-RENDERED";
12
12
  class Tracker {
13
+ analyticsApi;
14
+ context;
13
15
  constructor(analyticsApi, context = {
14
16
  routeRef: "unknown",
15
17
  pluginId: "root",
@@ -1 +1 @@
1
- {"version":3,"file":"Tracker.esm.js","sources":["../../src/analytics/Tracker.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\nimport {\n AnalyticsApi,\n AnalyticsEventAttributes,\n AnalyticsTracker,\n} from '../apis';\nimport { AnalyticsContextValue } from './types';\n\ntype TempGlobalEvents = {\n /**\n * Stores the most recent \"gathered\" mountpoint navigation.\n */\n mostRecentGatheredNavigation?: {\n action: string;\n subject: string;\n value?: number;\n attributes?: AnalyticsEventAttributes;\n context: AnalyticsContextValue;\n };\n /**\n * Stores the most recent routable extension render.\n */\n mostRecentRoutableExtensionRender?: {\n context: AnalyticsContextValue;\n };\n /**\n * Tracks whether or not a beforeunload event listener has already been\n * registered.\n */\n beforeUnloadRegistered: boolean;\n};\n\n/**\n * Temporary global store for select event data. Used to make `navigate` events\n * more accurate when gathered mountpoints are used.\n */\nconst globalEvents = getOrCreateGlobalSingleton<TempGlobalEvents>(\n 'core-plugin-api:analytics-tracker-events',\n () => ({\n mostRecentGatheredNavigation: undefined,\n mostRecentRoutableExtensionRender: undefined,\n beforeUnloadRegistered: false,\n }),\n);\n\n/**\n * Internal-only event representing when a routable extension is rendered.\n */\nexport const routableExtensionRenderedEvent = '_ROUTABLE-EXTENSION-RENDERED';\n\nexport class Tracker implements AnalyticsTracker {\n constructor(\n private readonly analyticsApi: AnalyticsApi,\n private context: AnalyticsContextValue = {\n routeRef: 'unknown',\n pluginId: 'root',\n extension: 'App',\n },\n ) {\n // Only register a single beforeunload event across all trackers.\n if (!globalEvents.beforeUnloadRegistered) {\n // Before the page unloads, attempt to capture any deferred navigation\n // events that haven't yet been captured.\n addEventListener(\n 'beforeunload',\n () => {\n if (globalEvents.mostRecentGatheredNavigation) {\n this.analyticsApi.captureEvent({\n ...globalEvents.mostRecentGatheredNavigation,\n ...globalEvents.mostRecentRoutableExtensionRender,\n });\n globalEvents.mostRecentGatheredNavigation = undefined;\n globalEvents.mostRecentRoutableExtensionRender = undefined;\n }\n },\n { once: true, passive: true },\n );\n\n // Prevent duplicate handlers from being registered.\n globalEvents.beforeUnloadRegistered = true;\n }\n }\n\n setContext(context: AnalyticsContextValue) {\n this.context = context;\n }\n\n captureEvent(\n action: string,\n subject: string,\n {\n value,\n attributes,\n }: { value?: number; attributes?: AnalyticsEventAttributes } = {},\n ) {\n // Never pass internal \"_routeNodeType\" context value.\n const { _routeNodeType, ...context } = this.context;\n\n // Never fire the special \"_routable-extension-rendered\" internal event.\n if (action === routableExtensionRenderedEvent) {\n // But keep track of it if we're delaying a `navigate` event for a\n // a gathered route node type.\n if (globalEvents.mostRecentGatheredNavigation) {\n globalEvents.mostRecentRoutableExtensionRender = {\n context: {\n ...context,\n extension: 'App',\n },\n };\n }\n return;\n }\n\n // If we are about to fire a real event, and we have an un-fired gathered\n // mountpoint navigation on the global store, we need to fire the navigate\n // event first, so this real event happens accurately after the navigation.\n if (globalEvents.mostRecentGatheredNavigation) {\n try {\n this.analyticsApi.captureEvent({\n ...globalEvents.mostRecentGatheredNavigation,\n ...globalEvents.mostRecentRoutableExtensionRender,\n });\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn('Error during analytics event capture. %o', e);\n }\n\n // Clear the global stores.\n globalEvents.mostRecentGatheredNavigation = undefined;\n globalEvents.mostRecentRoutableExtensionRender = undefined;\n }\n\n // Never directly fire a navigation event on a gathered route with default\n // contextual details.\n if (\n action === 'navigate' &&\n _routeNodeType === 'gathered' &&\n context.pluginId === 'root'\n ) {\n // Instead, set it on the global store.\n globalEvents.mostRecentGatheredNavigation = {\n action,\n subject,\n value,\n attributes,\n context,\n };\n return;\n }\n\n try {\n this.analyticsApi.captureEvent({\n action,\n subject,\n value,\n attributes,\n context,\n });\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn('Error during analytics event capture. %o', e);\n }\n }\n}\n"],"names":[],"mappings":";;AAoDA,MAAM,YAAA,GAAe,0BAAA;AAAA,EACnB,0CAAA;AAAA,EACA,OAAO;AAAA,IACL,4BAAA,EAA8B,MAAA;AAAA,IAC9B,iCAAA,EAAmC,MAAA;AAAA,IACnC,sBAAA,EAAwB;AAAA,GAC1B;AACF,CAAA;AAKO,MAAM,8BAAA,GAAiC;AAEvC,MAAM,OAAA,CAAoC;AAAA,EAC/C,WAAA,CACmB,cACT,OAAA,GAAiC;AAAA,IACvC,QAAA,EAAU,SAAA;AAAA,IACV,QAAA,EAAU,MAAA;AAAA,IACV,SAAA,EAAW;AAAA,GACb,EACA;AANiB,IAAA,IAAA,CAAA,YAAA,GAAA,YAAA;AACT,IAAA,IAAA,CAAA,OAAA,GAAA,OAAA;AAOR,IAAA,IAAI,CAAC,aAAa,sBAAA,EAAwB;AAGxC,MAAA,gBAAA;AAAA,QACE,cAAA;AAAA,QACA,MAAM;AACJ,UAAA,IAAI,aAAa,4BAAA,EAA8B;AAC7C,YAAA,IAAA,CAAK,aAAa,YAAA,CAAa;AAAA,cAC7B,GAAG,YAAA,CAAa,4BAAA;AAAA,cAChB,GAAG,YAAA,CAAa;AAAA,aACjB,CAAA;AACD,YAAA,YAAA,CAAa,4BAAA,GAA+B,MAAA;AAC5C,YAAA,YAAA,CAAa,iCAAA,GAAoC,MAAA;AAAA,UACnD;AAAA,QACF,CAAA;AAAA,QACA,EAAE,IAAA,EAAM,IAAA,EAAM,OAAA,EAAS,IAAA;AAAK,OAC9B;AAGA,MAAA,YAAA,CAAa,sBAAA,GAAyB,IAAA;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,WAAW,OAAA,EAAgC;AACzC,IAAA,IAAA,CAAK,OAAA,GAAU,OAAA;AAAA,EACjB;AAAA,EAEA,YAAA,CACE,QACA,OAAA,EACA;AAAA,IACE,KAAA;AAAA,IACA;AAAA,GACF,GAA+D,EAAC,EAChE;AAEA,IAAA,MAAM,EAAE,cAAA,EAAgB,GAAG,OAAA,KAAY,IAAA,CAAK,OAAA;AAG5C,IAAA,IAAI,WAAW,8BAAA,EAAgC;AAG7C,MAAA,IAAI,aAAa,4BAAA,EAA8B;AAC7C,QAAA,YAAA,CAAa,iCAAA,GAAoC;AAAA,UAC/C,OAAA,EAAS;AAAA,YACP,GAAG,OAAA;AAAA,YACH,SAAA,EAAW;AAAA;AACb,SACF;AAAA,MACF;AACA,MAAA;AAAA,IACF;AAKA,IAAA,IAAI,aAAa,4BAAA,EAA8B;AAC7C,MAAA,IAAI;AACF,QAAA,IAAA,CAAK,aAAa,YAAA,CAAa;AAAA,UAC7B,GAAG,YAAA,CAAa,4BAAA;AAAA,UAChB,GAAG,YAAA,CAAa;AAAA,SACjB,CAAA;AAAA,MACH,SAAS,CAAA,EAAG;AAEV,QAAA,OAAA,CAAQ,IAAA,CAAK,4CAA4C,CAAC,CAAA;AAAA,MAC5D;AAGA,MAAA,YAAA,CAAa,4BAAA,GAA+B,MAAA;AAC5C,MAAA,YAAA,CAAa,iCAAA,GAAoC,MAAA;AAAA,IACnD;AAIA,IAAA,IACE,WAAW,UAAA,IACX,cAAA,KAAmB,UAAA,IACnB,OAAA,CAAQ,aAAa,MAAA,EACrB;AAEA,MAAA,YAAA,CAAa,4BAAA,GAA+B;AAAA,QAC1C,MAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA;AAAA,QACA;AAAA,OACF;AACA,MAAA;AAAA,IACF;AAEA,IAAA,IAAI;AACF,MAAA,IAAA,CAAK,aAAa,YAAA,CAAa;AAAA,QAC7B,MAAA;AAAA,QACA,OAAA;AAAA,QACA,KAAA;AAAA,QACA,UAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH,SAAS,CAAA,EAAG;AAEV,MAAA,OAAA,CAAQ,IAAA,CAAK,4CAA4C,CAAC,CAAA;AAAA,IAC5D;AAAA,EACF;AACF;;;;"}
1
+ {"version":3,"file":"Tracker.esm.js","sources":["../../src/analytics/Tracker.ts"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { getOrCreateGlobalSingleton } from '@backstage/version-bridge';\nimport {\n AnalyticsApi,\n AnalyticsEventAttributes,\n AnalyticsTracker,\n} from '../apis';\nimport { AnalyticsContextValue } from './types';\n\ntype TempGlobalEvents = {\n /**\n * Stores the most recent \"gathered\" mountpoint navigation.\n */\n mostRecentGatheredNavigation?: {\n action: string;\n subject: string;\n value?: number;\n attributes?: AnalyticsEventAttributes;\n context: AnalyticsContextValue;\n };\n /**\n * Stores the most recent routable extension render.\n */\n mostRecentRoutableExtensionRender?: {\n context: AnalyticsContextValue;\n };\n /**\n * Tracks whether or not a beforeunload event listener has already been\n * registered.\n */\n beforeUnloadRegistered: boolean;\n};\n\n/**\n * Temporary global store for select event data. Used to make `navigate` events\n * more accurate when gathered mountpoints are used.\n */\nconst globalEvents = getOrCreateGlobalSingleton<TempGlobalEvents>(\n 'core-plugin-api:analytics-tracker-events',\n () => ({\n mostRecentGatheredNavigation: undefined,\n mostRecentRoutableExtensionRender: undefined,\n beforeUnloadRegistered: false,\n }),\n);\n\n/**\n * Internal-only event representing when a routable extension is rendered.\n */\nexport const routableExtensionRenderedEvent = '_ROUTABLE-EXTENSION-RENDERED';\n\nexport class Tracker implements AnalyticsTracker {\n private readonly analyticsApi: AnalyticsApi;\n private context: AnalyticsContextValue;\n\n constructor(\n analyticsApi: AnalyticsApi,\n context: AnalyticsContextValue = {\n routeRef: 'unknown',\n pluginId: 'root',\n extension: 'App',\n },\n ) {\n this.analyticsApi = analyticsApi;\n this.context = context;\n // Only register a single beforeunload event across all trackers.\n if (!globalEvents.beforeUnloadRegistered) {\n // Before the page unloads, attempt to capture any deferred navigation\n // events that haven't yet been captured.\n addEventListener(\n 'beforeunload',\n () => {\n if (globalEvents.mostRecentGatheredNavigation) {\n this.analyticsApi.captureEvent({\n ...globalEvents.mostRecentGatheredNavigation,\n ...globalEvents.mostRecentRoutableExtensionRender,\n });\n globalEvents.mostRecentGatheredNavigation = undefined;\n globalEvents.mostRecentRoutableExtensionRender = undefined;\n }\n },\n { once: true, passive: true },\n );\n\n // Prevent duplicate handlers from being registered.\n globalEvents.beforeUnloadRegistered = true;\n }\n }\n\n setContext(context: AnalyticsContextValue) {\n this.context = context;\n }\n\n captureEvent(\n action: string,\n subject: string,\n {\n value,\n attributes,\n }: { value?: number; attributes?: AnalyticsEventAttributes } = {},\n ) {\n // Never pass internal \"_routeNodeType\" context value.\n const { _routeNodeType, ...context } = this.context;\n\n // Never fire the special \"_routable-extension-rendered\" internal event.\n if (action === routableExtensionRenderedEvent) {\n // But keep track of it if we're delaying a `navigate` event for a\n // a gathered route node type.\n if (globalEvents.mostRecentGatheredNavigation) {\n globalEvents.mostRecentRoutableExtensionRender = {\n context: {\n ...context,\n extension: 'App',\n },\n };\n }\n return;\n }\n\n // If we are about to fire a real event, and we have an un-fired gathered\n // mountpoint navigation on the global store, we need to fire the navigate\n // event first, so this real event happens accurately after the navigation.\n if (globalEvents.mostRecentGatheredNavigation) {\n try {\n this.analyticsApi.captureEvent({\n ...globalEvents.mostRecentGatheredNavigation,\n ...globalEvents.mostRecentRoutableExtensionRender,\n });\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn('Error during analytics event capture. %o', e);\n }\n\n // Clear the global stores.\n globalEvents.mostRecentGatheredNavigation = undefined;\n globalEvents.mostRecentRoutableExtensionRender = undefined;\n }\n\n // Never directly fire a navigation event on a gathered route with default\n // contextual details.\n if (\n action === 'navigate' &&\n _routeNodeType === 'gathered' &&\n context.pluginId === 'root'\n ) {\n // Instead, set it on the global store.\n globalEvents.mostRecentGatheredNavigation = {\n action,\n subject,\n value,\n attributes,\n context,\n };\n return;\n }\n\n try {\n this.analyticsApi.captureEvent({\n action,\n subject,\n value,\n attributes,\n context,\n });\n } catch (e) {\n // eslint-disable-next-line no-console\n console.warn('Error during analytics event capture. %o', e);\n }\n }\n}\n"],"names":[],"mappings":"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"}
@@ -55,6 +55,8 @@ function selectChildren(rootNode, featureFlagsApi, selector, strictError) {
55
55
  });
56
56
  }
57
57
  class Collection {
58
+ node;
59
+ featureFlagsApi;
58
60
  constructor(node, featureFlagsApi) {
59
61
  this.node = node;
60
62
  this.featureFlagsApi = featureFlagsApi;
@@ -1 +1 @@
1
- {"version":3,"file":"useElementFilter.esm.js","sources":["../../src/extensions/useElementFilter.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n Children,\n Fragment,\n isValidElement,\n ReactNode,\n ReactElement,\n useMemo,\n} from 'react';\nimport { getComponentData } from './componentData';\nimport { useApi, FeatureFlagsApi, featureFlagsApiRef } from '../apis';\n\nfunction selectChildren(\n rootNode: ReactNode,\n featureFlagsApi: FeatureFlagsApi,\n selector?: (element: ReactElement<unknown>) => boolean,\n strictError?: string,\n): Array<ReactElement<unknown>> {\n return Children.toArray(rootNode).flatMap(node => {\n if (!isValidElement(node)) {\n return [];\n }\n\n if (node.type === Fragment) {\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n }\n\n if (getComponentData(node, 'core.featureFlagged')) {\n const props = node.props as { with: string } | { without: string };\n const isEnabled =\n 'with' in props\n ? featureFlagsApi.isActive(props.with)\n : !featureFlagsApi.isActive(props.without);\n if (isEnabled) {\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n }\n return [];\n }\n\n if (selector === undefined || selector(node)) {\n return [node];\n }\n\n if (strictError) {\n throw new Error(strictError);\n }\n\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n });\n}\n\n/**\n * A querying interface tailored to traversing a set of selected React elements\n * and extracting data.\n *\n * @remarks\n *\n * Methods prefixed with `selectBy` are used to narrow the set of selected elements.\n *\n * Methods prefixed with `find` return concrete data using a deep traversal of the set.\n *\n * Methods prefixed with `get` return concrete data using a shallow traversal of the set.\n *\n * @public\n */\nexport interface ElementCollection {\n /**\n * Narrows the set of selected components by doing a deep traversal and\n * only including those that have defined component data for the given `key`.\n *\n * @remarks\n *\n * Whether an element in the tree has component data set for the given key\n * is determined by whether `getComponentData` returns undefined.\n *\n * The traversal does not continue deeper past elements that match the criteria,\n * and it also includes the root children in the selection, meaning that if the,\n * of all the currently selected elements contain data for the given key, this\n * method is a no-op.\n *\n * If `withStrictError` is set, the resulting selection must be a full match, meaning\n * there may be no elements that were excluded in the selection. If the selection\n * is not a clean match, an error will be throw with `withStrictError` as the message.\n *\n * @param query - Filtering query.\n */\n selectByComponentData(query: {\n key: string;\n withStrictError?: string;\n }): ElementCollection;\n\n /**\n * Finds all elements using the same criteria as `selectByComponentData`, but\n * returns the actual component data of each of those elements instead.\n *\n * @param query - Lookup query.\n */\n findComponentData<T>(query: { key: string }): T[];\n\n /**\n * Returns all of the elements currently selected by this collection.\n */\n getElements<Props extends { [name: string]: unknown }>(): Array<\n ReactElement<Props>\n >;\n}\n\nclass Collection implements ElementCollection {\n constructor(\n private readonly node: ReactNode,\n private readonly featureFlagsApi: FeatureFlagsApi,\n ) {}\n\n selectByComponentData(query: { key: string; withStrictError?: string }) {\n const selection = selectChildren(\n this.node,\n this.featureFlagsApi,\n node => getComponentData(node, query.key) !== undefined,\n query.withStrictError,\n );\n return new Collection(selection, this.featureFlagsApi);\n }\n\n findComponentData<T>(query: { key: string }): T[] {\n const selection = selectChildren(\n this.node,\n this.featureFlagsApi,\n node => getComponentData(node, query.key) !== undefined,\n );\n return selection\n .map(node => getComponentData<T>(node, query.key))\n .filter((data: T | undefined): data is T => data !== undefined);\n }\n\n getElements<Props extends { [name: string]: unknown }>(): Array<\n ReactElement<Props>\n > {\n return selectChildren(this.node, this.featureFlagsApi) as Array<\n ReactElement<Props>\n >;\n }\n}\n\n/**\n * useElementFilter is a utility that helps you narrow down and retrieve data\n * from a React element tree, typically operating on the `children` property\n * passed in to a component.\n *\n * @remarks\n *\n * A common use-case is to construct declarative APIs\n * where a React component defines its behavior based on its children, such as\n * the relationship between `Routes` and `Route` in `react-router`.\n *\n * The purpose of this hook is similar to `React.Children.map`, and it expands upon\n * it to also handle traversal of fragments and Backstage specific things like the\n * `FeatureFlagged` component.\n *\n * The return value of the hook is computed by the provided filter function, but\n * with added memoization based on the input `node`. If further memoization\n * dependencies are used in the filter function, they should be added to the\n * third `dependencies` argument, just like `useMemo`, `useEffect`, etc.\n *\n * @public\n */\nexport function useElementFilter<T>(\n node: ReactNode,\n filterFn: (arg: ElementCollection) => T,\n dependencies: any[] = [],\n) {\n const featureFlagsApi = useApi(featureFlagsApiRef);\n const elements = new Collection(node, featureFlagsApi);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => filterFn(elements), [node, ...dependencies]);\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"useElementFilter.esm.js","sources":["../../src/extensions/useElementFilter.tsx"],"sourcesContent":["/*\n * Copyright 2021 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport {\n Children,\n Fragment,\n isValidElement,\n ReactNode,\n ReactElement,\n useMemo,\n} from 'react';\nimport { getComponentData } from './componentData';\nimport { useApi, FeatureFlagsApi, featureFlagsApiRef } from '../apis';\n\nfunction selectChildren(\n rootNode: ReactNode,\n featureFlagsApi: FeatureFlagsApi,\n selector?: (element: ReactElement<unknown>) => boolean,\n strictError?: string,\n): Array<ReactElement<unknown>> {\n return Children.toArray(rootNode).flatMap(node => {\n if (!isValidElement(node)) {\n return [];\n }\n\n if (node.type === Fragment) {\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n }\n\n if (getComponentData(node, 'core.featureFlagged')) {\n const props = node.props as { with: string } | { without: string };\n const isEnabled =\n 'with' in props\n ? featureFlagsApi.isActive(props.with)\n : !featureFlagsApi.isActive(props.without);\n if (isEnabled) {\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n }\n return [];\n }\n\n if (selector === undefined || selector(node)) {\n return [node];\n }\n\n if (strictError) {\n throw new Error(strictError);\n }\n\n return selectChildren(\n node.props.children,\n featureFlagsApi,\n selector,\n strictError,\n );\n });\n}\n\n/**\n * A querying interface tailored to traversing a set of selected React elements\n * and extracting data.\n *\n * @remarks\n *\n * Methods prefixed with `selectBy` are used to narrow the set of selected elements.\n *\n * Methods prefixed with `find` return concrete data using a deep traversal of the set.\n *\n * Methods prefixed with `get` return concrete data using a shallow traversal of the set.\n *\n * @public\n */\nexport interface ElementCollection {\n /**\n * Narrows the set of selected components by doing a deep traversal and\n * only including those that have defined component data for the given `key`.\n *\n * @remarks\n *\n * Whether an element in the tree has component data set for the given key\n * is determined by whether `getComponentData` returns undefined.\n *\n * The traversal does not continue deeper past elements that match the criteria,\n * and it also includes the root children in the selection, meaning that if the,\n * of all the currently selected elements contain data for the given key, this\n * method is a no-op.\n *\n * If `withStrictError` is set, the resulting selection must be a full match, meaning\n * there may be no elements that were excluded in the selection. If the selection\n * is not a clean match, an error will be throw with `withStrictError` as the message.\n *\n * @param query - Filtering query.\n */\n selectByComponentData(query: {\n key: string;\n withStrictError?: string;\n }): ElementCollection;\n\n /**\n * Finds all elements using the same criteria as `selectByComponentData`, but\n * returns the actual component data of each of those elements instead.\n *\n * @param query - Lookup query.\n */\n findComponentData<T>(query: { key: string }): T[];\n\n /**\n * Returns all of the elements currently selected by this collection.\n */\n getElements<Props extends { [name: string]: unknown }>(): Array<\n ReactElement<Props>\n >;\n}\n\nclass Collection implements ElementCollection {\n private readonly node: ReactNode;\n private readonly featureFlagsApi: FeatureFlagsApi;\n\n constructor(node: ReactNode, featureFlagsApi: FeatureFlagsApi) {\n this.node = node;\n this.featureFlagsApi = featureFlagsApi;\n }\n\n selectByComponentData(query: { key: string; withStrictError?: string }) {\n const selection = selectChildren(\n this.node,\n this.featureFlagsApi,\n node => getComponentData(node, query.key) !== undefined,\n query.withStrictError,\n );\n return new Collection(selection, this.featureFlagsApi);\n }\n\n findComponentData<T>(query: { key: string }): T[] {\n const selection = selectChildren(\n this.node,\n this.featureFlagsApi,\n node => getComponentData(node, query.key) !== undefined,\n );\n return selection\n .map(node => getComponentData<T>(node, query.key))\n .filter((data: T | undefined): data is T => data !== undefined);\n }\n\n getElements<Props extends { [name: string]: unknown }>(): Array<\n ReactElement<Props>\n > {\n return selectChildren(this.node, this.featureFlagsApi) as Array<\n ReactElement<Props>\n >;\n }\n}\n\n/**\n * useElementFilter is a utility that helps you narrow down and retrieve data\n * from a React element tree, typically operating on the `children` property\n * passed in to a component.\n *\n * @remarks\n *\n * A common use-case is to construct declarative APIs\n * where a React component defines its behavior based on its children, such as\n * the relationship between `Routes` and `Route` in `react-router`.\n *\n * The purpose of this hook is similar to `React.Children.map`, and it expands upon\n * it to also handle traversal of fragments and Backstage specific things like the\n * `FeatureFlagged` component.\n *\n * The return value of the hook is computed by the provided filter function, but\n * with added memoization based on the input `node`. If further memoization\n * dependencies are used in the filter function, they should be added to the\n * third `dependencies` argument, just like `useMemo`, `useEffect`, etc.\n *\n * @public\n */\nexport function useElementFilter<T>(\n node: ReactNode,\n filterFn: (arg: ElementCollection) => T,\n dependencies: any[] = [],\n) {\n const featureFlagsApi = useApi(featureFlagsApiRef);\n const elements = new Collection(node, featureFlagsApi);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n return useMemo(() => filterFn(elements), [node, ...dependencies]);\n}\n"],"names":[],"mappings":"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"}
@@ -1,13 +1,17 @@
1
1
  import { routeRefType } from './types.esm.js';
2
2
 
3
3
  class ExternalRouteRefImpl {
4
+ [routeRefType] = "external";
5
+ id;
6
+ params;
7
+ optional;
8
+ defaultTarget;
4
9
  constructor(id, params, optional, defaultTarget) {
5
10
  this.id = id;
6
11
  this.params = params;
7
12
  this.optional = optional;
8
13
  this.defaultTarget = defaultTarget;
9
14
  }
10
- [routeRefType] = "external";
11
15
  toString() {
12
16
  return `routeRef{type=external,id=${this.id}}`;
13
17
  }
@@ -1 +1 @@
1
- {"version":3,"file":"ExternalRouteRef.esm.js","sources":["../../src/routing/ExternalRouteRef.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ExternalRouteRef,\n routeRefType,\n AnyParams,\n ParamKeys,\n OptionalParams,\n} from './types';\n\n/**\n * @internal\n */\nexport class ExternalRouteRefImpl<\n Params extends AnyParams,\n Optional extends boolean,\n> implements ExternalRouteRef<Params, Optional>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'external';\n readonly [routeRefType] = 'external';\n\n constructor(\n private readonly id: string,\n readonly params: ParamKeys<Params>,\n readonly optional: Optional,\n readonly defaultTarget: string | undefined,\n ) {}\n\n toString() {\n return `routeRef{type=external,id=${this.id}}`;\n }\n\n getDefaultTarget() {\n return this.defaultTarget;\n }\n}\n\n/**\n * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @param options - Description of the route reference to be created.\n * @public\n */\nexport function createExternalRouteRef<\n Params extends { [param in ParamKey]: string },\n Optional extends boolean = false,\n ParamKey extends string = never,\n>(options: {\n /**\n * An identifier for this route, used to identify it in error messages\n */\n id: string;\n\n /**\n * The parameters that will be provided to the external route reference.\n */\n params?: ParamKey[];\n\n /**\n * Whether or not this route is optional, defaults to false.\n *\n * Optional external routes are not required to be bound in the app, and\n * if they aren't, `useRouteRef` will return `undefined`.\n */\n optional?: Optional;\n\n /**\n * The route (typically in another plugin) that this should map to by default.\n *\n * The string is expected to be on the standard `<plugin id>.<route id>` form,\n * for example `techdocs.docRoot`.\n */\n defaultTarget?: string;\n}): ExternalRouteRef<OptionalParams<Params>, Optional> {\n return new ExternalRouteRefImpl(\n options.id,\n (options.params ?? []) as ParamKeys<OptionalParams<Params>>,\n Boolean(options.optional) as Optional,\n options?.defaultTarget,\n );\n}\n"],"names":[],"mappings":";;AA2BO,MAAM,oBAAA,CAIb;AAAA,EAKE,WAAA,CACmB,EAAA,EACR,MAAA,EACA,QAAA,EACA,aAAA,EACT;AAJiB,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA;AACR,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,QAAA,GAAA,QAAA;AACA,IAAA,IAAA,CAAA,aAAA,GAAA,aAAA;AAAA,EACR;AAAA,EAPH,CAAU,YAAY,IAAI,UAAA;AAAA,EAS1B,QAAA,GAAW;AACT,IAAA,OAAO,CAAA,0BAAA,EAA6B,KAAK,EAAE,CAAA,CAAA,CAAA;AAAA,EAC7C;AAAA,EAEA,gBAAA,GAAmB;AACjB,IAAA,OAAO,IAAA,CAAK,aAAA;AAAA,EACd;AACF;AAYO,SAAS,uBAId,OAAA,EA0BqD;AACrD,EAAA,OAAO,IAAI,oBAAA;AAAA,IACT,OAAA,CAAQ,EAAA;AAAA,IACP,OAAA,CAAQ,UAAU,EAAC;AAAA,IACpB,OAAA,CAAQ,QAAQ,QAAQ,CAAA;AAAA,IACxB,OAAA,EAAS;AAAA,GACX;AACF;;;;"}
1
+ {"version":3,"file":"ExternalRouteRef.esm.js","sources":["../../src/routing/ExternalRouteRef.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n ExternalRouteRef,\n routeRefType,\n AnyParams,\n ParamKeys,\n OptionalParams,\n} from './types';\n\n/**\n * @internal\n */\nexport class ExternalRouteRefImpl<\n Params extends AnyParams,\n Optional extends boolean,\n> implements ExternalRouteRef<Params, Optional>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'external';\n readonly [routeRefType] = 'external';\n\n private readonly id: string;\n readonly params: ParamKeys<Params>;\n readonly optional: Optional;\n readonly defaultTarget: string | undefined;\n\n constructor(\n id: string,\n params: ParamKeys<Params>,\n optional: Optional,\n defaultTarget: string | undefined,\n ) {\n this.id = id;\n this.params = params;\n this.optional = optional;\n this.defaultTarget = defaultTarget;\n }\n\n toString() {\n return `routeRef{type=external,id=${this.id}}`;\n }\n\n getDefaultTarget() {\n return this.defaultTarget;\n }\n}\n\n/**\n * Creates a route descriptor, to be later bound to a concrete route by the app. Used to implement cross-plugin route references.\n *\n * @remarks\n *\n * See {@link https://backstage.io/docs/plugins/composability#routing-system}.\n *\n * @param options - Description of the route reference to be created.\n * @public\n */\nexport function createExternalRouteRef<\n Params extends { [param in ParamKey]: string },\n Optional extends boolean = false,\n ParamKey extends string = never,\n>(options: {\n /**\n * An identifier for this route, used to identify it in error messages\n */\n id: string;\n\n /**\n * The parameters that will be provided to the external route reference.\n */\n params?: ParamKey[];\n\n /**\n * Whether or not this route is optional, defaults to false.\n *\n * Optional external routes are not required to be bound in the app, and\n * if they aren't, `useRouteRef` will return `undefined`.\n */\n optional?: Optional;\n\n /**\n * The route (typically in another plugin) that this should map to by default.\n *\n * The string is expected to be on the standard `<plugin id>.<route id>` form,\n * for example `techdocs.docRoot`.\n */\n defaultTarget?: string;\n}): ExternalRouteRef<OptionalParams<Params>, Optional> {\n return new ExternalRouteRefImpl(\n options.id,\n (options.params ?? []) as ParamKeys<OptionalParams<Params>>,\n Boolean(options.optional) as Optional,\n options?.defaultTarget,\n );\n}\n"],"names":[],"mappings":";;AA2BO,MAAM,oBAAA,CAIb;AAAA,EAGE,CAAU,YAAY,IAAI,UAAA;AAAA,EAET,EAAA;AAAA,EACR,MAAA;AAAA,EACA,QAAA;AAAA,EACA,aAAA;AAAA,EAET,WAAA,CACE,EAAA,EACA,MAAA,EACA,QAAA,EACA,aAAA,EACA;AACA,IAAA,IAAA,CAAK,EAAA,GAAK,EAAA;AACV,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,QAAA,GAAW,QAAA;AAChB,IAAA,IAAA,CAAK,aAAA,GAAgB,aAAA;AAAA,EACvB;AAAA,EAEA,QAAA,GAAW;AACT,IAAA,OAAO,CAAA,0BAAA,EAA6B,KAAK,EAAE,CAAA,CAAA,CAAA;AAAA,EAC7C;AAAA,EAEA,gBAAA,GAAmB;AACjB,IAAA,OAAO,IAAA,CAAK,aAAA;AAAA,EACd;AACF;AAYO,SAAS,uBAId,OAAA,EA0BqD;AACrD,EAAA,OAAO,IAAI,oBAAA;AAAA,IACT,OAAA,CAAQ,EAAA;AAAA,IACP,OAAA,CAAQ,UAAU,EAAC;AAAA,IACpB,OAAA,CAAQ,QAAQ,QAAQ,CAAA;AAAA,IACxB,OAAA,EAAS;AAAA,GACX;AACF;;;;"}
@@ -1,11 +1,13 @@
1
1
  import { routeRefType } from './types.esm.js';
2
2
 
3
3
  class RouteRefImpl {
4
+ [routeRefType] = "absolute";
5
+ id;
6
+ params;
4
7
  constructor(id, params) {
5
8
  this.id = id;
6
9
  this.params = params;
7
10
  }
8
- [routeRefType] = "absolute";
9
11
  get title() {
10
12
  return this.id;
11
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"RouteRef.esm.js","sources":["../../src/routing/RouteRef.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RouteRef,\n routeRefType,\n AnyParams,\n ParamKeys,\n OptionalParams,\n} from './types';\n\n/**\n * @internal\n */\nexport class RouteRefImpl<Params extends AnyParams>\n implements RouteRef<Params>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'absolute';\n readonly [routeRefType] = 'absolute';\n\n constructor(\n private readonly id: string,\n readonly params: ParamKeys<Params>,\n ) {}\n\n get title() {\n return this.id;\n }\n\n toString() {\n return `routeRef{type=absolute,id=${this.id}}`;\n }\n}\n\n/**\n * Create a {@link RouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createRouteRef<\n // Params is the type that we care about and the one to be embedded in the route ref.\n // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string}\n Params extends { [param in ParamKey]: string },\n // ParamKey is here to make sure the Params type properly has its keys narrowed down\n // to only the elements of params. Defaulting to never makes sure we end up with\n // Param = {} if the params array is empty.\n ParamKey extends string = never,\n>(config: {\n /** The id of the route ref, used to identify it when printed */\n id: string;\n /** A list of parameter names that the path that this route ref is bound to must contain */\n params?: ParamKey[];\n}): RouteRef<OptionalParams<Params>> {\n return new RouteRefImpl(\n config.id,\n (config.params ?? []) as ParamKeys<OptionalParams<Params>>,\n );\n}\n"],"names":[],"mappings":";;AA2BO,MAAM,YAAA,CAEb;AAAA,EAKE,WAAA,CACmB,IACR,MAAA,EACT;AAFiB,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA;AACR,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EACR;AAAA,EALH,CAAU,YAAY,IAAI,UAAA;AAAA,EAO1B,IAAI,KAAA,GAAQ;AACV,IAAA,OAAO,IAAA,CAAK,EAAA;AAAA,EACd;AAAA,EAEA,QAAA,GAAW;AACT,IAAA,OAAO,CAAA,0BAAA,EAA6B,KAAK,EAAE,CAAA,CAAA,CAAA;AAAA,EAC7C;AACF;AAQO,SAAS,eAQd,MAAA,EAKmC;AACnC,EAAA,OAAO,IAAI,YAAA;AAAA,IACT,MAAA,CAAO,EAAA;AAAA,IACN,MAAA,CAAO,UAAU;AAAC,GACrB;AACF;;;;"}
1
+ {"version":3,"file":"RouteRef.esm.js","sources":["../../src/routing/RouteRef.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n RouteRef,\n routeRefType,\n AnyParams,\n ParamKeys,\n OptionalParams,\n} from './types';\n\n/**\n * @internal\n */\nexport class RouteRefImpl<Params extends AnyParams>\n implements RouteRef<Params>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'absolute';\n readonly [routeRefType] = 'absolute';\n\n private readonly id: string;\n readonly params: ParamKeys<Params>;\n\n constructor(id: string, params: ParamKeys<Params>) {\n this.id = id;\n this.params = params;\n }\n\n get title() {\n return this.id;\n }\n\n toString() {\n return `routeRef{type=absolute,id=${this.id}}`;\n }\n}\n\n/**\n * Create a {@link RouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createRouteRef<\n // Params is the type that we care about and the one to be embedded in the route ref.\n // For example, given the params ['name', 'kind'], Params will be {name: string, kind: string}\n Params extends { [param in ParamKey]: string },\n // ParamKey is here to make sure the Params type properly has its keys narrowed down\n // to only the elements of params. Defaulting to never makes sure we end up with\n // Param = {} if the params array is empty.\n ParamKey extends string = never,\n>(config: {\n /** The id of the route ref, used to identify it when printed */\n id: string;\n /** A list of parameter names that the path that this route ref is bound to must contain */\n params?: ParamKey[];\n}): RouteRef<OptionalParams<Params>> {\n return new RouteRefImpl(\n config.id,\n (config.params ?? []) as ParamKeys<OptionalParams<Params>>,\n );\n}\n"],"names":[],"mappings":";;AA2BO,MAAM,YAAA,CAEb;AAAA,EAGE,CAAU,YAAY,IAAI,UAAA;AAAA,EAET,EAAA;AAAA,EACR,MAAA;AAAA,EAET,WAAA,CAAY,IAAY,MAAA,EAA2B;AACjD,IAAA,IAAA,CAAK,EAAA,GAAK,EAAA;AACV,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,IAAI,KAAA,GAAQ;AACV,IAAA,OAAO,IAAA,CAAK,EAAA;AAAA,EACd;AAAA,EAEA,QAAA,GAAW;AACT,IAAA,OAAO,CAAA,0BAAA,EAA6B,KAAK,EAAE,CAAA,CAAA,CAAA;AAAA,EAC7C;AACF;AAQO,SAAS,eAQd,MAAA,EAKmC;AACnC,EAAA,OAAO,IAAI,YAAA;AAAA,IACT,MAAA,CAAO,EAAA;AAAA,IACN,MAAA,CAAO,UAAU;AAAC,GACrB;AACF;;;;"}
@@ -2,13 +2,17 @@ import { routeRefType } from './types.esm.js';
2
2
 
3
3
  const PARAM_PATTERN = /^\w+$/;
4
4
  class SubRouteRefImpl {
5
+ [routeRefType] = "sub";
6
+ id;
7
+ path;
8
+ parent;
9
+ params;
5
10
  constructor(id, path, parent, params) {
6
11
  this.id = id;
7
12
  this.path = path;
8
13
  this.parent = parent;
9
14
  this.params = params;
10
15
  }
11
- [routeRefType] = "sub";
12
16
  toString() {
13
17
  return `routeRef{type=sub,id=${this.id}}`;
14
18
  }
@@ -1 +1 @@
1
- {"version":3,"file":"SubRouteRef.esm.js","sources":["../../src/routing/SubRouteRef.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AnyParams,\n OptionalParams,\n ParamKeys,\n RouteRef,\n routeRefType,\n SubRouteRef,\n} from './types';\n\n// Should match the pattern in react-router\nconst PARAM_PATTERN = /^\\w+$/;\n\n/**\n * @internal\n */\nexport class SubRouteRefImpl<Params extends AnyParams>\n implements SubRouteRef<Params>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'sub';\n readonly [routeRefType] = 'sub';\n\n constructor(\n private readonly id: string,\n readonly path: string,\n readonly parent: RouteRef,\n readonly params: ParamKeys<Params>,\n ) {}\n\n toString() {\n return `routeRef{type=sub,id=${this.id}}`;\n }\n}\n\n/**\n * Used in {@link PathParams} type declaration.\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamPart<S extends string> = S extends `:${infer Param}`\n ? Param\n : never;\n\n/**\n * Used in {@link PathParams} type declaration.\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamNames<S extends string> =\n S extends `${infer Part}/${infer Rest}`\n ? ParamPart<Part> | ParamNames<Rest>\n : ParamPart<S>;\n/**\n * This utility type helps us infer a Param object type from a string path\n * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }`\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type PathParams<S extends string> = { [name in ParamNames<S>]: string };\n\n/**\n * Merges a param object type with an optional params type into a params object.\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type MergeParams<\n P1 extends { [param in string]: string },\n P2 extends AnyParams,\n> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);\n\n/**\n * Creates a SubRouteRef type given the desired parameters and parent route parameters.\n * The parameters types are merged together while ensuring that there is no overlap between the two.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type MakeSubRouteRef<\n Params extends { [param in string]: string },\n ParentParams extends AnyParams,\n> = keyof Params & keyof ParentParams extends never\n ? SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>\n : never;\n\n/**\n * Create a {@link SubRouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createSubRouteRef<\n Path extends string,\n ParentParams extends AnyParams = never,\n>(config: {\n id: string;\n path: Path;\n parent: RouteRef<ParentParams>;\n}): MakeSubRouteRef<PathParams<Path>, ParentParams> {\n const { id, path, parent } = config;\n type Params = PathParams<Path>;\n\n // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz'\n const pathParams = path\n .split('/')\n .filter(p => p.startsWith(':'))\n .map(p => p.substring(1));\n const params = [...parent.params, ...pathParams];\n\n if (parent.params.some(p => pathParams.includes(p as string))) {\n throw new Error(\n 'SubRouteRef may not have params that overlap with its parent',\n );\n }\n if (!path.startsWith('/')) {\n throw new Error(`SubRouteRef path must start with '/', got '${path}'`);\n }\n if (path.endsWith('/')) {\n throw new Error(`SubRouteRef path must not end with '/', got '${path}'`);\n }\n for (const param of pathParams) {\n if (!PARAM_PATTERN.test(param)) {\n throw new Error(`SubRouteRef path has invalid param, got '${param}'`);\n }\n }\n\n // We ensure that the type of the return type is sane here\n const subRouteRef = new SubRouteRefImpl(\n id,\n path,\n parent,\n params as ParamKeys<MergeParams<Params, ParentParams>>,\n ) as SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>;\n\n // But skip type checking of the return value itself, because the conditional\n // type checking of the parent parameter overlap is tricky to express.\n return subRouteRef as any;\n}\n"],"names":[],"mappings":";;AA0BA,MAAM,aAAA,GAAgB,OAAA;AAKf,MAAM,eAAA,CAEb;AAAA,EAKE,WAAA,CACmB,EAAA,EACR,IAAA,EACA,MAAA,EACA,MAAA,EACT;AAJiB,IAAA,IAAA,CAAA,EAAA,GAAA,EAAA;AACR,IAAA,IAAA,CAAA,IAAA,GAAA,IAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AACA,IAAA,IAAA,CAAA,MAAA,GAAA,MAAA;AAAA,EACR;AAAA,EAPH,CAAU,YAAY,IAAI,KAAA;AAAA,EAS1B,QAAA,GAAW;AACT,IAAA,OAAO,CAAA,qBAAA,EAAwB,KAAK,EAAE,CAAA,CAAA,CAAA;AAAA,EACxC;AACF;AA0DO,SAAS,kBAGd,MAAA,EAIkD;AAClD,EAAA,MAAM,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAO,GAAI,MAAA;AAI7B,EAAA,MAAM,aAAa,IAAA,CAChB,KAAA,CAAM,GAAG,CAAA,CACT,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,CAAW,GAAG,CAAC,CAAA,CAC7B,GAAA,CAAI,OAAK,CAAA,CAAE,SAAA,CAAU,CAAC,CAAC,CAAA;AAC1B,EAAA,MAAM,SAAS,CAAC,GAAG,MAAA,CAAO,MAAA,EAAQ,GAAG,UAAU,CAAA;AAE/C,EAAA,IAAI,MAAA,CAAO,OAAO,IAAA,CAAK,CAAA,CAAA,KAAK,WAAW,QAAA,CAAS,CAAW,CAAC,CAAA,EAAG;AAC7D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AACzB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2CAAA,EAA8C,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EACvE;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6CAAA,EAAgD,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EACzE;AACA,EAAA,KAAA,MAAW,SAAS,UAAA,EAAY;AAC9B,IAAA,IAAI,CAAC,aAAA,CAAc,IAAA,CAAK,KAAK,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yCAAA,EAA4C,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,IACtE;AAAA,EACF;AAGA,EAAA,MAAM,cAAc,IAAI,eAAA;AAAA,IACtB,EAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AAIA,EAAA,OAAO,WAAA;AACT;;;;"}
1
+ {"version":3,"file":"SubRouteRef.esm.js","sources":["../../src/routing/SubRouteRef.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport {\n AnyParams,\n OptionalParams,\n ParamKeys,\n RouteRef,\n routeRefType,\n SubRouteRef,\n} from './types';\n\n// Should match the pattern in react-router\nconst PARAM_PATTERN = /^\\w+$/;\n\n/**\n * @internal\n */\nexport class SubRouteRefImpl<Params extends AnyParams>\n implements SubRouteRef<Params>\n{\n // The marker is used for type checking while the symbol is used at runtime.\n declare $$routeRefType: 'sub';\n readonly [routeRefType] = 'sub';\n\n private readonly id: string;\n readonly path: string;\n readonly parent: RouteRef;\n readonly params: ParamKeys<Params>;\n\n constructor(\n id: string,\n path: string,\n parent: RouteRef,\n params: ParamKeys<Params>,\n ) {\n this.id = id;\n this.path = path;\n this.parent = parent;\n this.params = params;\n }\n\n toString() {\n return `routeRef{type=sub,id=${this.id}}`;\n }\n}\n\n/**\n * Used in {@link PathParams} type declaration.\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamPart<S extends string> = S extends `:${infer Param}`\n ? Param\n : never;\n\n/**\n * Used in {@link PathParams} type declaration.\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type ParamNames<S extends string> =\n S extends `${infer Part}/${infer Rest}`\n ? ParamPart<Part> | ParamNames<Rest>\n : ParamPart<S>;\n/**\n * This utility type helps us infer a Param object type from a string path\n * For example, `/foo/:bar/:baz` inferred to `{ bar: string, baz: string }`\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type PathParams<S extends string> = { [name in ParamNames<S>]: string };\n\n/**\n * Merges a param object type with an optional params type into a params object.\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type MergeParams<\n P1 extends { [param in string]: string },\n P2 extends AnyParams,\n> = (P1[keyof P1] extends never ? {} : P1) & (P2 extends undefined ? {} : P2);\n\n/**\n * Creates a SubRouteRef type given the desired parameters and parent route parameters.\n * The parameters types are merged together while ensuring that there is no overlap between the two.\n *\n * @public\n * @deprecated this type is deprecated and will be removed in the future\n */\nexport type MakeSubRouteRef<\n Params extends { [param in string]: string },\n ParentParams extends AnyParams,\n> = keyof Params & keyof ParentParams extends never\n ? SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>\n : never;\n\n/**\n * Create a {@link SubRouteRef} from a route descriptor.\n *\n * @param config - Description of the route reference to be created.\n * @public\n */\nexport function createSubRouteRef<\n Path extends string,\n ParentParams extends AnyParams = never,\n>(config: {\n id: string;\n path: Path;\n parent: RouteRef<ParentParams>;\n}): MakeSubRouteRef<PathParams<Path>, ParentParams> {\n const { id, path, parent } = config;\n type Params = PathParams<Path>;\n\n // Collect runtime parameters from the path, e.g. ['bar', 'baz'] from '/foo/:bar/:baz'\n const pathParams = path\n .split('/')\n .filter(p => p.startsWith(':'))\n .map(p => p.substring(1));\n const params = [...parent.params, ...pathParams];\n\n if (parent.params.some(p => pathParams.includes(p as string))) {\n throw new Error(\n 'SubRouteRef may not have params that overlap with its parent',\n );\n }\n if (!path.startsWith('/')) {\n throw new Error(`SubRouteRef path must start with '/', got '${path}'`);\n }\n if (path.endsWith('/')) {\n throw new Error(`SubRouteRef path must not end with '/', got '${path}'`);\n }\n for (const param of pathParams) {\n if (!PARAM_PATTERN.test(param)) {\n throw new Error(`SubRouteRef path has invalid param, got '${param}'`);\n }\n }\n\n // We ensure that the type of the return type is sane here\n const subRouteRef = new SubRouteRefImpl(\n id,\n path,\n parent,\n params as ParamKeys<MergeParams<Params, ParentParams>>,\n ) as SubRouteRef<OptionalParams<MergeParams<Params, ParentParams>>>;\n\n // But skip type checking of the return value itself, because the conditional\n // type checking of the parent parameter overlap is tricky to express.\n return subRouteRef as any;\n}\n"],"names":[],"mappings":";;AA0BA,MAAM,aAAA,GAAgB,OAAA;AAKf,MAAM,eAAA,CAEb;AAAA,EAGE,CAAU,YAAY,IAAI,KAAA;AAAA,EAET,EAAA;AAAA,EACR,IAAA;AAAA,EACA,MAAA;AAAA,EACA,MAAA;AAAA,EAET,WAAA,CACE,EAAA,EACA,IAAA,EACA,MAAA,EACA,MAAA,EACA;AACA,IAAA,IAAA,CAAK,EAAA,GAAK,EAAA;AACV,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AACd,IAAA,IAAA,CAAK,MAAA,GAAS,MAAA;AAAA,EAChB;AAAA,EAEA,QAAA,GAAW;AACT,IAAA,OAAO,CAAA,qBAAA,EAAwB,KAAK,EAAE,CAAA,CAAA,CAAA;AAAA,EACxC;AACF;AA0DO,SAAS,kBAGd,MAAA,EAIkD;AAClD,EAAA,MAAM,EAAE,EAAA,EAAI,IAAA,EAAM,MAAA,EAAO,GAAI,MAAA;AAI7B,EAAA,MAAM,aAAa,IAAA,CAChB,KAAA,CAAM,GAAG,CAAA,CACT,OAAO,CAAA,CAAA,KAAK,CAAA,CAAE,UAAA,CAAW,GAAG,CAAC,CAAA,CAC7B,GAAA,CAAI,OAAK,CAAA,CAAE,SAAA,CAAU,CAAC,CAAC,CAAA;AAC1B,EAAA,MAAM,SAAS,CAAC,GAAG,MAAA,CAAO,MAAA,EAAQ,GAAG,UAAU,CAAA;AAE/C,EAAA,IAAI,MAAA,CAAO,OAAO,IAAA,CAAK,CAAA,CAAA,KAAK,WAAW,QAAA,CAAS,CAAW,CAAC,CAAA,EAAG;AAC7D,IAAA,MAAM,IAAI,KAAA;AAAA,MACR;AAAA,KACF;AAAA,EACF;AACA,EAAA,IAAI,CAAC,IAAA,CAAK,UAAA,CAAW,GAAG,CAAA,EAAG;AACzB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,2CAAA,EAA8C,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EACvE;AACA,EAAA,IAAI,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,6CAAA,EAAgD,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,EACzE;AACA,EAAA,KAAA,MAAW,SAAS,UAAA,EAAY;AAC9B,IAAA,IAAI,CAAC,aAAA,CAAc,IAAA,CAAK,KAAK,CAAA,EAAG;AAC9B,MAAA,MAAM,IAAI,KAAA,CAAM,CAAA,yCAAA,EAA4C,KAAK,CAAA,CAAA,CAAG,CAAA;AAAA,IACtE;AAAA,EACF;AAGA,EAAA,MAAM,cAAc,IAAI,eAAA;AAAA,IACtB,EAAA;AAAA,IACA,IAAA;AAAA,IACA,MAAA;AAAA,IACA;AAAA,GACF;AAIA,EAAA,OAAO,WAAA;AACT;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@backstage/core-plugin-api",
3
- "version": "1.11.1-next.0",
3
+ "version": "1.11.2-next.0",
4
4
  "description": "Core API used by Backstage plugins",
5
5
  "backstage": {
6
6
  "role": "web-library"
@@ -57,16 +57,16 @@
57
57
  "test": "backstage-cli package test"
58
58
  },
59
59
  "dependencies": {
60
- "@backstage/config": "1.3.4-next.0",
60
+ "@backstage/config": "1.3.6-next.0",
61
61
  "@backstage/errors": "1.2.7",
62
62
  "@backstage/types": "1.2.2",
63
63
  "@backstage/version-bridge": "1.0.11",
64
64
  "history": "^5.0.0"
65
65
  },
66
66
  "devDependencies": {
67
- "@backstage/cli": "0.34.4-next.1",
68
- "@backstage/core-app-api": "1.19.1-next.0",
69
- "@backstage/test-utils": "1.7.12-next.0",
67
+ "@backstage/cli": "0.34.5-next.0",
68
+ "@backstage/core-app-api": "1.19.2-next.0",
69
+ "@backstage/test-utils": "1.7.13-next.0",
70
70
  "@testing-library/dom": "^10.0.0",
71
71
  "@testing-library/jest-dom": "^6.0.0",
72
72
  "@testing-library/react": "^16.0.0",