@backstage/frontend-app-api 0.7.5-next.1 → 0.7.5-next.3
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 +31 -0
- package/dist/extensions/AppNav.esm.js +5 -2
- package/dist/extensions/AppNav.esm.js.map +1 -1
- package/dist/frontend-plugin-api/src/routing/ExternalRouteRef.esm.js.map +1 -1
- package/dist/frontend-plugin-api/src/wiring/createExtension.esm.js.map +1 -1
- package/dist/frontend-plugin-api/src/wiring/createPlugin.esm.js.map +1 -1
- package/dist/frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js +7 -1
- package/dist/frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/routing/RouteResolver.esm.js.map +1 -1
- package/dist/routing/resolveRouteBindings.esm.js +0 -5
- package/dist/routing/resolveRouteBindings.esm.js.map +1 -1
- package/dist/tree/instantiateAppNodeTree.esm.js +9 -0
- package/dist/tree/instantiateAppNodeTree.esm.js.map +1 -1
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,36 @@
|
|
|
1
1
|
# @backstage/frontend-app-api
|
|
2
2
|
|
|
3
|
+
## 0.7.5-next.3
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Updated dependencies
|
|
8
|
+
- @backstage/frontend-plugin-api@0.7.0-next.3
|
|
9
|
+
- @backstage/config@1.2.0
|
|
10
|
+
- @backstage/core-app-api@1.14.2-next.0
|
|
11
|
+
- @backstage/core-components@0.14.10-next.0
|
|
12
|
+
- @backstage/core-plugin-api@1.9.3
|
|
13
|
+
- @backstage/errors@1.2.4
|
|
14
|
+
- @backstage/theme@0.5.6
|
|
15
|
+
- @backstage/types@1.1.1
|
|
16
|
+
- @backstage/version-bridge@1.0.8
|
|
17
|
+
|
|
18
|
+
## 0.7.5-next.2
|
|
19
|
+
|
|
20
|
+
### Patch Changes
|
|
21
|
+
|
|
22
|
+
- 72754db: Updated usage of `useRouteRef`, which can now always return `undefined`.
|
|
23
|
+
- Updated dependencies
|
|
24
|
+
- @backstage/frontend-plugin-api@0.7.0-next.2
|
|
25
|
+
- @backstage/config@1.2.0
|
|
26
|
+
- @backstage/core-app-api@1.14.2-next.0
|
|
27
|
+
- @backstage/core-components@0.14.10-next.0
|
|
28
|
+
- @backstage/core-plugin-api@1.9.3
|
|
29
|
+
- @backstage/errors@1.2.4
|
|
30
|
+
- @backstage/theme@0.5.6
|
|
31
|
+
- @backstage/types@1.1.1
|
|
32
|
+
- @backstage/version-bridge@1.0.8
|
|
33
|
+
|
|
3
34
|
## 0.7.5-next.1
|
|
4
35
|
|
|
5
36
|
### Patch Changes
|
|
@@ -26,8 +26,11 @@ const SidebarLogo = (props) => {
|
|
|
26
26
|
};
|
|
27
27
|
const SidebarNavItem = (props) => {
|
|
28
28
|
const { icon: Icon, title, routeRef } = props;
|
|
29
|
-
const
|
|
30
|
-
|
|
29
|
+
const link = useRouteRef(routeRef);
|
|
30
|
+
if (!link) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
return /* @__PURE__ */ React.createElement(SidebarItem, { to: link(), icon: Icon, text: title });
|
|
31
34
|
};
|
|
32
35
|
const AppNav = createExtension({
|
|
33
36
|
namespace: "app",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppNav.esm.js","sources":["../../src/extensions/AppNav.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 React from 'react';\nimport {\n createExtension,\n coreExtensionData,\n createExtensionInput,\n useRouteRef,\n createNavItemExtension,\n createNavLogoExtension,\n} from '@backstage/frontend-plugin-api';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n Sidebar,\n useSidebarOpenState,\n Link,\n sidebarConfig,\n SidebarDivider,\n SidebarItem,\n} from '@backstage/core-components';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport LogoIcon from '../../../app/src/components/Root/LogoIcon';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport LogoFull from '../../../app/src/components/Root/LogoFull';\n\nconst useSidebarLogoStyles = makeStyles({\n root: {\n width: sidebarConfig.drawerWidthClosed,\n height: 3 * sidebarConfig.logoHeight,\n display: 'flex',\n flexFlow: 'row nowrap',\n alignItems: 'center',\n marginBottom: -14,\n },\n link: {\n width: sidebarConfig.drawerWidthClosed,\n marginLeft: 24,\n },\n});\n\nconst SidebarLogo = (\n props: (typeof createNavLogoExtension.logoElementsDataRef)['T'],\n) => {\n const classes = useSidebarLogoStyles();\n const { isOpen } = useSidebarOpenState();\n\n return (\n <div className={classes.root}>\n <Link to=\"/\" underline=\"none\" className={classes.link} aria-label=\"Home\">\n {isOpen\n ? props?.logoFull ?? <LogoFull />\n : props?.logoIcon ?? <LogoIcon />}\n </Link>\n </div>\n );\n};\n\nconst SidebarNavItem = (\n props: (typeof createNavItemExtension.targetDataRef)['T'],\n) => {\n const { icon: Icon, title, routeRef } = props;\n const
|
|
1
|
+
{"version":3,"file":"AppNav.esm.js","sources":["../../src/extensions/AppNav.tsx"],"sourcesContent":["/*\n * Copyright 2023 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 React from 'react';\nimport {\n createExtension,\n coreExtensionData,\n createExtensionInput,\n useRouteRef,\n createNavItemExtension,\n createNavLogoExtension,\n} from '@backstage/frontend-plugin-api';\nimport { makeStyles } from '@material-ui/core/styles';\nimport {\n Sidebar,\n useSidebarOpenState,\n Link,\n sidebarConfig,\n SidebarDivider,\n SidebarItem,\n} from '@backstage/core-components';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport LogoIcon from '../../../app/src/components/Root/LogoIcon';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport LogoFull from '../../../app/src/components/Root/LogoFull';\n\nconst useSidebarLogoStyles = makeStyles({\n root: {\n width: sidebarConfig.drawerWidthClosed,\n height: 3 * sidebarConfig.logoHeight,\n display: 'flex',\n flexFlow: 'row nowrap',\n alignItems: 'center',\n marginBottom: -14,\n },\n link: {\n width: sidebarConfig.drawerWidthClosed,\n marginLeft: 24,\n },\n});\n\nconst SidebarLogo = (\n props: (typeof createNavLogoExtension.logoElementsDataRef)['T'],\n) => {\n const classes = useSidebarLogoStyles();\n const { isOpen } = useSidebarOpenState();\n\n return (\n <div className={classes.root}>\n <Link to=\"/\" underline=\"none\" className={classes.link} aria-label=\"Home\">\n {isOpen\n ? props?.logoFull ?? <LogoFull />\n : props?.logoIcon ?? <LogoIcon />}\n </Link>\n </div>\n );\n};\n\nconst SidebarNavItem = (\n props: (typeof createNavItemExtension.targetDataRef)['T'],\n) => {\n const { icon: Icon, title, routeRef } = props;\n const link = useRouteRef(routeRef);\n if (!link) {\n return null;\n }\n // TODO: Support opening modal, for example, the search one\n return <SidebarItem to={link()} icon={Icon} text={title} />;\n};\n\nexport const AppNav = createExtension({\n namespace: 'app',\n name: 'nav',\n attachTo: { id: 'app/layout', input: 'nav' },\n inputs: {\n items: createExtensionInput({\n target: createNavItemExtension.targetDataRef,\n }),\n logos: createExtensionInput(\n {\n elements: createNavLogoExtension.logoElementsDataRef,\n },\n {\n singleton: true,\n optional: true,\n },\n ),\n },\n output: {\n element: coreExtensionData.reactElement,\n },\n factory({ inputs }) {\n return {\n element: (\n <Sidebar>\n <SidebarLogo {...inputs.logos?.output.elements} />\n <SidebarDivider />\n {inputs.items.map((item, index) => (\n <SidebarNavItem {...item.output.target} key={index} />\n ))}\n </Sidebar>\n ),\n };\n },\n});\n"],"names":[],"mappings":";;;;;;;AAuCA,MAAM,uBAAuB,UAAW,CAAA;AAAA,EACtC,IAAM,EAAA;AAAA,IACJ,OAAO,aAAc,CAAA,iBAAA;AAAA,IACrB,MAAA,EAAQ,IAAI,aAAc,CAAA,UAAA;AAAA,IAC1B,OAAS,EAAA,MAAA;AAAA,IACT,QAAU,EAAA,YAAA;AAAA,IACV,UAAY,EAAA,QAAA;AAAA,IACZ,YAAc,EAAA,CAAA,EAAA;AAAA,GAChB;AAAA,EACA,IAAM,EAAA;AAAA,IACJ,OAAO,aAAc,CAAA,iBAAA;AAAA,IACrB,UAAY,EAAA,EAAA;AAAA,GACd;AACF,CAAC,CAAA,CAAA;AAED,MAAM,WAAA,GAAc,CAClB,KACG,KAAA;AACH,EAAA,MAAM,UAAU,oBAAqB,EAAA,CAAA;AACrC,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,mBAAoB,EAAA,CAAA;AAEvC,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,KAAI,EAAA,EAAA,SAAA,EAAW,OAAQ,CAAA,IAAA,EAAA,kBACrB,KAAA,CAAA,aAAA,CAAA,IAAA,EAAA,EAAK,EAAG,EAAA,GAAA,EAAI,SAAU,EAAA,MAAA,EAAO,SAAW,EAAA,OAAA,CAAQ,IAAM,EAAA,YAAA,EAAW,MAC/D,EAAA,EAAA,MAAA,GACG,KAAO,EAAA,QAAA,oBAAa,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,IAAS,CAC7B,GAAA,KAAA,EAAO,QAAY,oBAAA,KAAA,CAAA,aAAA,CAAC,QAAS,EAAA,IAAA,CACnC,CACF,CAAA,CAAA;AAEJ,CAAA,CAAA;AAEA,MAAM,cAAA,GAAiB,CACrB,KACG,KAAA;AACH,EAAA,MAAM,EAAE,IAAA,EAAM,IAAM,EAAA,KAAA,EAAO,UAAa,GAAA,KAAA,CAAA;AACxC,EAAM,MAAA,IAAA,GAAO,YAAY,QAAQ,CAAA,CAAA;AACjC,EAAA,IAAI,CAAC,IAAM,EAAA;AACT,IAAO,OAAA,IAAA,CAAA;AAAA,GACT;AAEA,EAAO,uBAAA,KAAA,CAAA,aAAA,CAAC,eAAY,EAAI,EAAA,IAAA,IAAQ,IAAM,EAAA,IAAA,EAAM,MAAM,KAAO,EAAA,CAAA,CAAA;AAC3D,CAAA,CAAA;AAEO,MAAM,SAAS,eAAgB,CAAA;AAAA,EACpC,SAAW,EAAA,KAAA;AAAA,EACX,IAAM,EAAA,KAAA;AAAA,EACN,QAAU,EAAA,EAAE,EAAI,EAAA,YAAA,EAAc,OAAO,KAAM,EAAA;AAAA,EAC3C,MAAQ,EAAA;AAAA,IACN,OAAO,oBAAqB,CAAA;AAAA,MAC1B,QAAQ,sBAAuB,CAAA,aAAA;AAAA,KAChC,CAAA;AAAA,IACD,KAAO,EAAA,oBAAA;AAAA,MACL;AAAA,QACE,UAAU,sBAAuB,CAAA,mBAAA;AAAA,OACnC;AAAA,MACA;AAAA,QACE,SAAW,EAAA,IAAA;AAAA,QACX,QAAU,EAAA,IAAA;AAAA,OACZ;AAAA,KACF;AAAA,GACF;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,SAAS,iBAAkB,CAAA,YAAA;AAAA,GAC7B;AAAA,EACA,OAAA,CAAQ,EAAE,MAAA,EAAU,EAAA;AAClB,IAAO,OAAA;AAAA,MACL,OACE,kBAAA,KAAA,CAAA,aAAA,CAAC,OACC,EAAA,IAAA,kBAAA,KAAA,CAAA,aAAA,CAAC,WAAa,EAAA,EAAA,GAAG,MAAO,CAAA,KAAA,EAAO,MAAO,CAAA,QAAA,EAAU,CAChD,kBAAA,KAAA,CAAA,aAAA,CAAC,cAAe,EAAA,IAAA,CAAA,EACf,MAAO,CAAA,KAAA,CAAM,GAAI,CAAA,CAAC,IAAM,EAAA,KAAA,qBACtB,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,EAAgB,GAAG,IAAA,CAAK,MAAO,CAAA,MAAA,EAAQ,GAAK,EAAA,KAAA,EAAO,CACrD,CACH,CAAA;AAAA,KAEJ,CAAA;AAAA,GACF;AACF,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExternalRouteRef.esm.js","sources":["../../../../../frontend-plugin-api/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 { RouteRefImpl } from './RouteRef';\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * 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 * @public\n */\nexport interface ExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n
|
|
1
|
+
{"version":3,"file":"ExternalRouteRef.esm.js","sources":["../../../../../frontend-plugin-api/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 { RouteRefImpl } from './RouteRef';\nimport { describeParentCallSite } from './describeParentCallSite';\nimport { AnyRouteRefParams } from './types';\n\n/**\n * 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 * @public\n */\nexport interface ExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> {\n readonly $$type: '@backstage/ExternalRouteRef';\n readonly T: TParams;\n}\n\n/** @internal */\nexport interface InternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n> extends ExternalRouteRef<TParams> {\n readonly version: 'v1';\n getParams(): string[];\n getDescription(): string;\n getDefaultTarget(): string | undefined;\n\n setId(id: string): void;\n}\n\n/** @internal */\nexport function toInternalExternalRouteRef<\n TParams extends AnyRouteRefParams = AnyRouteRefParams,\n>(resource: ExternalRouteRef<TParams>): InternalExternalRouteRef<TParams> {\n const r = resource as InternalExternalRouteRef<TParams>;\n if (r.$$type !== '@backstage/ExternalRouteRef') {\n throw new Error(`Invalid ExternalRouteRef, bad type '${r.$$type}'`);\n }\n\n return r;\n}\n\n/** @internal */\nexport function isExternalRouteRef(opaque: {\n $$type: string;\n}): opaque is ExternalRouteRef {\n return opaque.$$type === '@backstage/ExternalRouteRef';\n}\n\n/** @internal */\nclass ExternalRouteRefImpl\n extends RouteRefImpl\n implements InternalExternalRouteRef\n{\n readonly $$type = '@backstage/ExternalRouteRef' as any;\n\n constructor(\n readonly params: string[] = [],\n readonly defaultTarget: string | undefined,\n creationSite: string,\n ) {\n super(params, creationSite);\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 TParams extends { [param in TParamKeys]: string } | undefined = undefined,\n TParamKeys extends string = string,\n>(options?: {\n /**\n * The parameters that will be provided to the external route reference.\n */\n readonly params?: string extends TParamKeys\n ? (keyof TParams)[]\n : TParamKeys[];\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<\n keyof TParams extends never\n ? undefined\n : string extends TParamKeys\n ? TParams\n : { [param in TParamKeys]: string }\n> {\n return new ExternalRouteRefImpl(\n options?.params as string[] | undefined,\n options?.defaultTarget,\n describeParentCallSite(),\n );\n}\n"],"names":[],"mappings":"AAiDO,SAAS,2BAEd,QAAwE,EAAA;AACxE,EAAA,MAAM,CAAI,GAAA,QAAA,CAAA;AACV,EAAI,IAAA,CAAA,CAAE,WAAW,6BAA+B,EAAA;AAC9C,IAAA,MAAM,IAAI,KAAA,CAAM,CAAuC,oCAAA,EAAA,CAAA,CAAE,MAAM,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GACpE;AAEA,EAAO,OAAA,CAAA,CAAA;AACT,CAAA;AAGO,SAAS,mBAAmB,MAEJ,EAAA;AAC7B,EAAA,OAAO,OAAO,MAAW,KAAA,6BAAA,CAAA;AAC3B;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createExtension.esm.js","sources":["../../../../../frontend-plugin-api/src/wiring/createExtension.ts"],"sourcesContent":["/*\n * Copyright 2023 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 { AppNode } from '../apis';\nimport { PortableSchema, createSchemaFromZod } from '../schema';\nimport { Expand } from '../types';\nimport {\n AnyExtensionDataRef,\n ExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput, LegacyExtensionInput } from './createExtensionInput';\nimport { z } from 'zod';\n\n/**\n * @public\n * @deprecated Extension data maps will be removed.\n */\nexport type AnyExtensionDataMap = {\n [name in string]: AnyExtensionDataRef;\n};\n\n/**\n * @public\n * @deprecated This type will be removed.\n */\nexport type AnyExtensionInputMap = {\n [inputName in string]: LegacyExtensionInput<\n AnyExtensionDataMap,\n { optional: boolean; singleton: boolean }\n >;\n};\n\n/**\n * Converts an extension data map into the matching concrete data values type.\n * @public\n * @deprecated Extension data maps will be removed.\n */\nexport type ExtensionDataValues<TExtensionData extends AnyExtensionDataMap> = {\n [DataName in keyof TExtensionData as TExtensionData[DataName]['config'] extends {\n optional: true;\n }\n ? never\n : DataName]: TExtensionData[DataName]['T'];\n} & {\n [DataName in keyof TExtensionData as TExtensionData[DataName]['config'] extends {\n optional: true;\n }\n ? DataName\n : never]?: TExtensionData[DataName]['T'];\n};\n\n/** @public */\nexport type ExtensionDataContainer<UExtensionData extends AnyExtensionDataRef> =\n {\n get<TId extends UExtensionData['id']>(\n ref: ExtensionDataRef<any, TId, any>,\n ): UExtensionData extends ExtensionDataRef<infer IData, TId, infer IConfig>\n ? IConfig['optional'] extends true\n ? IData | undefined\n : IData\n : never;\n };\n\n/**\n * Convert a single extension input into a matching resolved input.\n * @public\n */\nexport type ResolvedExtensionInput<\n TExtensionInput extends ExtensionInput<any, any>,\n> = TExtensionInput['extensionData'] extends Array<AnyExtensionDataRef>\n ? {\n node: AppNode;\n } & ExtensionDataContainer<TExtensionInput['extensionData'][number]>\n : TExtensionInput['extensionData'] extends AnyExtensionDataMap\n ? {\n node: AppNode;\n output: ExtensionDataValues<TExtensionInput['extensionData']>;\n }\n : never;\n\n/**\n * Converts an extension input map into a matching collection of resolved inputs.\n * @public\n */\nexport type ResolvedExtensionInputs<\n TInputs extends {\n [name in string]: ExtensionInput<any, any> | LegacyExtensionInput<any, any>;\n },\n> = {\n [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton']\n ? Array<Expand<ResolvedExtensionInput<TInputs[InputName]>>>\n : false extends TInputs[InputName]['config']['optional']\n ? Expand<ResolvedExtensionInput<TInputs[InputName]>>\n : Expand<ResolvedExtensionInput<TInputs[InputName]> | undefined>;\n};\n\n/**\n * @public\n * @deprecated This way of structuring the options is deprecated, this type will be removed in the future\n */\nexport interface LegacyCreateExtensionOptions<\n TOutput extends AnyExtensionDataMap,\n TInputs extends AnyExtensionInputMap,\n TConfig,\n TConfigInput,\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n> {\n kind?: string;\n namespace?: string;\n name?: string;\n attachTo: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n output: TOutput;\n /** @deprecated - use `config.schema` instead */\n configSchema?: PortableSchema<TConfig, TConfigInput>;\n config?: {\n schema: TConfigSchema;\n };\n factory(context: {\n node: AppNode;\n config: TConfig &\n (string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n });\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Expand<ExtensionDataValues<TOutput>>;\n}\n\n/** @ignore */\nexport type VerifyExtensionFactoryOutput<\n UDeclaredOutput extends AnyExtensionDataRef,\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = (\n UDeclaredOutput extends any\n ? UDeclaredOutput['config']['optional'] extends true\n ? never\n : UDeclaredOutput['id']\n : never\n) extends infer IRequiredOutputIds\n ? [IRequiredOutputIds] extends [UFactoryOutput['id']]\n ? {}\n : {\n 'Error: The extension factory is missing the following outputs': Exclude<\n IRequiredOutputIds,\n UFactoryOutput['id']\n >;\n }\n : never;\n\n/** @public */\nexport type CreateExtensionOptions<\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfig,\n TConfigInput,\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = {\n kind?: string;\n namespace?: string;\n name?: string;\n attachTo: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n output: Array<UOutput>;\n /** @deprecated - use `config.schema` instead */\n configSchema?: PortableSchema<TConfig, TConfigInput>;\n config?: {\n schema: TConfigSchema;\n };\n factory(context: {\n node: AppNode;\n config: TConfig &\n (string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n });\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Iterable<UFactoryOutput>;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport interface ExtensionDefinition<TConfig, TConfigInput = TConfig> {\n $$type: '@backstage/ExtensionDefinition';\n readonly kind?: string;\n readonly namespace?: string;\n readonly name?: string;\n readonly attachTo: { id: string; input: string };\n readonly disabled: boolean;\n readonly configSchema?: PortableSchema<TConfig, TConfigInput>;\n}\n\n/** @internal */\nexport type InternalExtensionDefinition<TConfig, TConfigInput> =\n ExtensionDefinition<TConfig, TConfigInput> &\n (\n | {\n readonly version: 'v1';\n readonly inputs: AnyExtensionInputMap;\n readonly output: AnyExtensionDataMap;\n factory(context: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<AnyExtensionInputMap>;\n }): ExtensionDataValues<any>;\n }\n | {\n readonly version: 'v2';\n readonly inputs: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n readonly output: Array<AnyExtensionDataRef>;\n factory(context: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n }>;\n }): Iterable<ExtensionDataValue<any, any>>;\n }\n );\n\n/** @internal */\nexport function toInternalExtensionDefinition<TConfig, TConfigInput>(\n overrides: ExtensionDefinition<TConfig, TConfigInput>,\n): InternalExtensionDefinition<TConfig, TConfigInput> {\n const internal = overrides as InternalExtensionDefinition<\n TConfig,\n TConfigInput\n >;\n if (internal.$$type !== '@backstage/ExtensionDefinition') {\n throw new Error(\n `Invalid extension definition instance, bad type '${internal.$$type}'`,\n );\n }\n const version = internal.version;\n if (version !== 'v1' && version !== 'v2') {\n throw new Error(\n `Invalid extension definition instance, bad version '${version}'`,\n );\n }\n return internal;\n}\n\n/** @public */\nexport function createExtension<\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfig,\n TConfigInput,\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n>(\n options: CreateExtensionOptions<\n UOutput,\n TInputs,\n TConfig,\n TConfigInput,\n TConfigSchema,\n UFactoryOutput\n >,\n): ExtensionDefinition<\n TConfig &\n (string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n }),\n TConfigInput &\n (string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >)\n>;\n/**\n * @public\n * @deprecated - use the array format of `output` instead, see TODO-doc-link\n */\nexport function createExtension<\n TOutput extends AnyExtensionDataMap,\n TInputs extends AnyExtensionInputMap,\n TConfig,\n TConfigInput,\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n>(\n options: LegacyCreateExtensionOptions<\n TOutput,\n TInputs,\n TConfig,\n TConfigInput,\n TConfigSchema\n >,\n): ExtensionDefinition<\n TConfig &\n (string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n }),\n TConfigInput &\n (string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >)\n>;\nexport function createExtension<\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TLegacyInputs extends AnyExtensionInputMap,\n TConfig,\n TConfigInput,\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n>(\n options:\n | CreateExtensionOptions<\n UOutput,\n TInputs,\n TConfig,\n TConfigInput,\n TConfigSchema,\n UFactoryOutput\n >\n | LegacyCreateExtensionOptions<\n AnyExtensionDataMap,\n TLegacyInputs,\n TConfig,\n TConfigInput,\n TConfigSchema\n >,\n): ExtensionDefinition<\n TConfig &\n (string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n }),\n TConfigInput &\n (string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >)\n> {\n const newConfigSchema = options.config?.schema;\n if (newConfigSchema && options.configSchema) {\n throw new Error(`Cannot provide both configSchema and config.schema`);\n }\n const configSchema = newConfigSchema\n ? createSchemaFromZod(innerZ =>\n innerZ.object(\n Object.fromEntries(\n Object.entries(newConfigSchema).map(([k, v]) => [k, v(innerZ)]),\n ),\n ),\n )\n : options.configSchema;\n\n return {\n $$type: '@backstage/ExtensionDefinition',\n version: Symbol.iterator in options.output ? 'v2' : 'v1',\n kind: options.kind,\n namespace: options.namespace,\n name: options.name,\n attachTo: options.attachTo,\n disabled: options.disabled ?? false,\n inputs: options.inputs ?? {},\n output: options.output,\n configSchema,\n factory: options.factory,\n toString() {\n const parts: string[] = [];\n if (options.kind) {\n parts.push(`kind=${options.kind}`);\n }\n if (options.namespace) {\n parts.push(`namespace=${options.namespace}`);\n }\n if (options.name) {\n parts.push(`name=${options.name}`);\n }\n parts.push(`attachTo=${options.attachTo.id}@${options.attachTo.input}`);\n return `ExtensionDefinition{${parts.join(',')}}`;\n },\n } as InternalExtensionDefinition<\n TConfig &\n (string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n }),\n TConfigInput &\n (string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >)\n >;\n}\n"],"names":[],"mappings":";;;AAgQO,SAAS,8BACd,SACoD,EAAA;AACpD,EAAA,MAAM,QAAW,GAAA,SAAA,CAAA;AAIjB,EAAI,IAAA,QAAA,CAAS,WAAW,gCAAkC,EAAA;AACxD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,iDAAA,EAAoD,SAAS,MAAM,CAAA,CAAA,CAAA;AAAA,KACrE,CAAA;AAAA,GACF;AACA,EAAA,MAAM,UAAU,QAAS,CAAA,OAAA,CAAA;AACzB,EAAI,IAAA,OAAA,KAAY,IAAQ,IAAA,OAAA,KAAY,IAAM,EAAA;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,uDAAuD,OAAO,CAAA,CAAA,CAAA;AAAA,KAChE,CAAA;AAAA,GACF;AACA,EAAO,OAAA,QAAA,CAAA;AACT;;;;"}
|
|
1
|
+
{"version":3,"file":"createExtension.esm.js","sources":["../../../../../frontend-plugin-api/src/wiring/createExtension.ts"],"sourcesContent":["/*\n * Copyright 2023 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 { AppNode } from '../apis';\nimport { PortableSchema, createSchemaFromZod } from '../schema';\nimport { Expand } from '../types';\nimport {\n ResolveInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\nimport {\n ExtensionDataContainer,\n createExtensionDataContainer,\n} from './createExtensionDataContainer';\nimport {\n AnyExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput, LegacyExtensionInput } from './createExtensionInput';\nimport { z } from 'zod';\n\n/**\n * @public\n * @deprecated Extension data maps will be removed.\n */\nexport type AnyExtensionDataMap = {\n [name in string]: AnyExtensionDataRef;\n};\n\n/**\n * @public\n * @deprecated This type will be removed.\n */\nexport type AnyExtensionInputMap = {\n [inputName in string]: LegacyExtensionInput<\n AnyExtensionDataMap,\n { optional: boolean; singleton: boolean }\n >;\n};\n\n/**\n * Converts an extension data map into the matching concrete data values type.\n * @public\n * @deprecated Extension data maps will be removed.\n */\nexport type ExtensionDataValues<TExtensionData extends AnyExtensionDataMap> = {\n [DataName in keyof TExtensionData as TExtensionData[DataName]['config'] extends {\n optional: true;\n }\n ? never\n : DataName]: TExtensionData[DataName]['T'];\n} & {\n [DataName in keyof TExtensionData as TExtensionData[DataName]['config'] extends {\n optional: true;\n }\n ? DataName\n : never]?: TExtensionData[DataName]['T'];\n};\n\n/**\n * Convert a single extension input into a matching resolved input.\n * @public\n */\nexport type ResolvedExtensionInput<\n TExtensionInput extends ExtensionInput<any, any>,\n> = TExtensionInput['extensionData'] extends Array<AnyExtensionDataRef>\n ? {\n node: AppNode;\n } & ExtensionDataContainer<TExtensionInput['extensionData'][number]>\n : TExtensionInput['extensionData'] extends AnyExtensionDataMap\n ? {\n node: AppNode;\n output: ExtensionDataValues<TExtensionInput['extensionData']>;\n }\n : never;\n\n/**\n * Converts an extension input map into a matching collection of resolved inputs.\n * @public\n */\nexport type ResolvedExtensionInputs<\n TInputs extends {\n [name in string]: ExtensionInput<any, any> | LegacyExtensionInput<any, any>;\n },\n> = {\n [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton']\n ? Array<Expand<ResolvedExtensionInput<TInputs[InputName]>>>\n : false extends TInputs[InputName]['config']['optional']\n ? Expand<ResolvedExtensionInput<TInputs[InputName]>>\n : Expand<ResolvedExtensionInput<TInputs[InputName]> | undefined>;\n};\n\n/**\n * @public\n * @deprecated This way of structuring the options is deprecated, this type will be removed in the future\n */\nexport interface LegacyCreateExtensionOptions<\n TOutput extends AnyExtensionDataMap,\n TInputs extends AnyExtensionInputMap,\n TConfig,\n TConfigInput,\n> {\n kind?: string;\n namespace?: string;\n name?: string;\n attachTo: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n output: TOutput;\n configSchema?: PortableSchema<TConfig, TConfigInput>;\n factory(context: {\n node: AppNode;\n config: TConfig;\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Expand<ExtensionDataValues<TOutput>>;\n}\n\ntype ToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I,\n) => void\n ? I\n : never;\n\ntype PopUnion<U> = ToIntersection<\n U extends any ? () => U : never\n> extends () => infer R\n ? [rest: Exclude<U, R>, next: R]\n : undefined;\n\n/** @ignore */\ntype JoinStringUnion<\n U,\n TDiv extends string = ', ',\n TResult extends string = '',\n> = PopUnion<U> extends [infer IRest extends string, infer INext extends string]\n ? TResult extends ''\n ? JoinStringUnion<IRest, TDiv, INext>\n : JoinStringUnion<IRest, TDiv, `${TResult}${TDiv}${INext}`>\n : TResult;\n\n/** @ignore */\nexport type VerifyExtensionFactoryOutput<\n UDeclaredOutput extends AnyExtensionDataRef,\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = (\n UDeclaredOutput extends any\n ? UDeclaredOutput['config']['optional'] extends true\n ? never\n : UDeclaredOutput['id']\n : never\n) extends infer IRequiredOutputIds\n ? [IRequiredOutputIds] extends [UFactoryOutput['id']]\n ? [UFactoryOutput['id']] extends [UDeclaredOutput['id']]\n ? {}\n : `Error: The extension factory has undeclared output(s): ${JoinStringUnion<\n Exclude<UFactoryOutput['id'], UDeclaredOutput['id']>\n >}`\n : `Error: The extension factory is missing the following output(s): ${JoinStringUnion<\n Exclude<IRequiredOutputIds, UFactoryOutput['id']>\n >}`\n : never;\n\n/** @public */\nexport type CreateExtensionOptions<\n TKind extends string | undefined,\n TNamespace extends string | undefined,\n TName extends string | undefined,\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = {\n kind?: TKind;\n namespace?: TNamespace;\n name?: TName;\n attachTo: { id: string; input: string };\n disabled?: boolean;\n inputs?: TInputs;\n output: Array<UOutput>;\n config?: {\n schema: TConfigSchema;\n };\n factory(context: {\n node: AppNode;\n config: {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Iterable<UFactoryOutput>;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport interface ExtensionDefinition<\n TConfig,\n TConfigInput = TConfig,\n UOutput extends AnyExtensionDataRef = AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n } = {},\n TKind extends string | undefined = string | undefined,\n TNamespace extends string | undefined = string | undefined,\n TName extends string | undefined = string | undefined,\n> {\n $$type: '@backstage/ExtensionDefinition';\n readonly kind?: TKind;\n readonly namespace?: TNamespace;\n readonly name?: TName;\n readonly attachTo: { id: string; input: string };\n readonly disabled: boolean;\n readonly configSchema?: PortableSchema<TConfig, TConfigInput>;\n\n override<\n TExtensionConfigSchema extends {\n [key in string]: (zImpl: typeof z) => z.ZodType;\n },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends AnyExtensionDataRef,\n TExtraInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n >(\n args: {\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TExtraInputs & {\n [KName in keyof TInputs]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: {\n schema: TExtensionConfigSchema & {\n [KName in keyof TConfig]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n };\n factory(\n originalFactory: (context?: {\n config?: TConfig;\n inputs?: ResolveInputValueOverrides<TInputs>;\n }) => ExtensionDataContainer<UOutput>,\n context: {\n node: AppNode;\n config: TConfig & {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n } & VerifyExtensionFactoryOutput<\n AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput,\n UFactoryOutput\n >,\n ): ExtensionDefinition<\n {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n } & TConfig,\n z.input<\n z.ZodObject<{\n [key in keyof TExtensionConfigSchema]: ReturnType<\n TExtensionConfigSchema[key]\n >;\n }>\n > &\n TConfigInput,\n AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput,\n TInputs & TExtraInputs,\n TKind,\n TNamespace,\n TName\n >;\n}\n\n/** @internal */\nexport type InternalExtensionDefinition<\n TConfig,\n TConfigInput = TConfig,\n UOutput extends AnyExtensionDataRef = AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n } = {},\n TKind extends string | undefined = string | undefined,\n TNamespace extends string | undefined = string | undefined,\n TName extends string | undefined = string | undefined,\n> = ExtensionDefinition<\n TConfig,\n TConfigInput,\n UOutput,\n TInputs,\n TKind,\n TNamespace,\n TName\n> &\n (\n | {\n readonly version: 'v1';\n readonly inputs: AnyExtensionInputMap;\n readonly output: AnyExtensionDataMap;\n factory(context: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<AnyExtensionInputMap>;\n }): ExtensionDataValues<any>;\n }\n | {\n readonly version: 'v2';\n readonly inputs: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n readonly output: Array<AnyExtensionDataRef>;\n factory(context: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n }>;\n }): Iterable<ExtensionDataValue<any, any>>;\n }\n );\n\n/** @internal */\nexport function toInternalExtensionDefinition<TConfig, TConfigInput>(\n overrides: ExtensionDefinition<TConfig, TConfigInput>,\n): InternalExtensionDefinition<TConfig, TConfigInput> {\n const internal = overrides as InternalExtensionDefinition<\n TConfig,\n TConfigInput\n >;\n if (internal.$$type !== '@backstage/ExtensionDefinition') {\n throw new Error(\n `Invalid extension definition instance, bad type '${internal.$$type}'`,\n );\n }\n const version = internal.version;\n if (version !== 'v1' && version !== 'v2') {\n throw new Error(\n `Invalid extension definition instance, bad version '${version}'`,\n );\n }\n return internal;\n}\n\n/** @public */\nexport function createExtension<\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n const TKind extends string | undefined = undefined,\n const TNamespace extends string | undefined = undefined,\n const TName extends string | undefined = undefined,\n>(\n options: CreateExtensionOptions<\n TKind,\n TNamespace,\n TName,\n UOutput,\n TInputs,\n TConfigSchema,\n UFactoryOutput\n >,\n): ExtensionDefinition<\n {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n },\n z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >,\n UOutput,\n TInputs,\n string | undefined extends TKind ? undefined : TKind,\n string | undefined extends TNamespace ? undefined : TNamespace,\n string | undefined extends TName ? undefined : TName\n>;\n/**\n * @public\n * @deprecated - use the array format of `output` instead, see TODO-doc-link\n */\nexport function createExtension<\n TOutput extends AnyExtensionDataMap,\n TInputs extends AnyExtensionInputMap,\n TConfig,\n TConfigInput,\n>(\n options: LegacyCreateExtensionOptions<\n TOutput,\n TInputs,\n TConfig,\n TConfigInput\n >,\n): ExtensionDefinition<TConfig, TConfigInput, never, never>;\nexport function createExtension<\n const TKind extends string | undefined,\n const TNamespace extends string | undefined,\n const TName extends string | undefined,\n UOutput extends AnyExtensionDataRef,\n TInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n TLegacyInputs extends AnyExtensionInputMap,\n TConfig,\n TConfigInput,\n TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n>(\n options:\n | CreateExtensionOptions<\n TKind,\n TNamespace,\n TName,\n UOutput,\n TInputs,\n TConfigSchema,\n UFactoryOutput\n >\n | LegacyCreateExtensionOptions<\n AnyExtensionDataMap,\n TLegacyInputs,\n TConfig,\n TConfigInput\n >,\n): ExtensionDefinition<\n TConfig &\n (string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n }),\n TConfigInput &\n (string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >),\n UOutput,\n TInputs,\n TKind,\n TNamespace,\n TName\n> {\n if ('configSchema' in options && 'config' in options) {\n throw new Error(`Cannot provide both configSchema and config.schema`);\n }\n let configSchema: PortableSchema<any, any> | undefined;\n if ('configSchema' in options) {\n configSchema = options.configSchema;\n }\n if ('config' in options) {\n const newConfigSchema = options.config?.schema;\n configSchema =\n newConfigSchema &&\n createSchemaFromZod(innerZ =>\n innerZ.object(\n Object.fromEntries(\n Object.entries(newConfigSchema).map(([k, v]) => [k, v(innerZ)]),\n ),\n ),\n );\n }\n\n return {\n $$type: '@backstage/ExtensionDefinition',\n version: Symbol.iterator in options.output ? 'v2' : 'v1',\n kind: options.kind,\n namespace: options.namespace,\n name: options.name,\n attachTo: options.attachTo,\n disabled: options.disabled ?? false,\n inputs: options.inputs ?? {},\n output: options.output,\n configSchema,\n factory: options.factory,\n toString() {\n const parts: string[] = [];\n if (options.kind) {\n parts.push(`kind=${options.kind}`);\n }\n if (options.namespace) {\n parts.push(`namespace=${options.namespace}`);\n }\n if (options.name) {\n parts.push(`name=${options.name}`);\n }\n parts.push(`attachTo=${options.attachTo.id}@${options.attachTo.input}`);\n return `ExtensionDefinition{${parts.join(',')}}`;\n },\n override: <\n TExtensionConfigSchema extends {\n [key in string]: (zImpl: typeof z) => z.ZodType;\n },\n UOverrideFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends AnyExtensionDataRef,\n TExtraInputs extends {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n >(overrideOptions: {\n attachTo?: { id: string; input: string };\n disabled?: boolean;\n inputs?: TExtraInputs;\n output?: Array<UNewOutput>;\n config?: {\n schema: TExtensionConfigSchema;\n };\n factory(\n originalFactory: (context?: {\n config?: {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n };\n inputs?: ResolveInputValueOverrides<TInputs>;\n }) => ExtensionDataContainer<UOutput>,\n context: {\n node: AppNode;\n config: {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n } & {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs & TExtraInputs>>;\n },\n ): Iterable<UOverrideFactoryOutput>;\n }): ExtensionDefinition<\n {\n [key in keyof TExtensionConfigSchema]: z.infer<\n ReturnType<TExtensionConfigSchema[key]>\n >;\n } & {\n [key in keyof TConfigSchema]: z.infer<ReturnType<TConfigSchema[key]>>;\n },\n z.input<\n z.ZodObject<\n {\n [key in keyof TExtensionConfigSchema]: ReturnType<\n TExtensionConfigSchema[key]\n >;\n } & {\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }\n >\n >,\n AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput,\n TInputs & TExtraInputs,\n TKind,\n TNamespace,\n TName\n > => {\n if (!Array.isArray(options.output)) {\n throw new Error(\n 'Cannot override an extension that is not declared using the new format with outputs as an array',\n );\n }\n const newOptions = options as CreateExtensionOptions<\n TKind,\n TNamespace,\n TName,\n UOutput,\n TInputs,\n TConfigSchema,\n UFactoryOutput\n >;\n const overrideNewConfigSchema = overrideOptions.config?.schema;\n\n const schema = {\n ...newOptions.config?.schema,\n ...overrideNewConfigSchema,\n } as TConfigSchema & TExtensionConfigSchema;\n\n return createExtension({\n kind: newOptions.kind,\n namespace: newOptions.namespace,\n name: newOptions.name,\n attachTo: overrideOptions.attachTo ?? newOptions.attachTo,\n disabled: overrideOptions.disabled ?? newOptions.disabled,\n inputs: { ...overrideOptions.inputs, ...newOptions.inputs },\n output: overrideOptions.output ?? newOptions.output,\n config: Object.keys(schema).length === 0 ? undefined : { schema },\n factory: ({ node, config, inputs }) => {\n if (!overrideOptions.factory) {\n return newOptions.factory({\n node,\n config,\n inputs: inputs as unknown as Expand<\n ResolvedExtensionInputs<TInputs>\n >,\n });\n }\n const parentResult = overrideOptions.factory(\n (innerContext?: {\n config?: {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n };\n inputs?: ResolveInputValueOverrides<TInputs>;\n }): ExtensionDataContainer<UOutput> => {\n return createExtensionDataContainer<UOutput>(\n newOptions.factory({\n node,\n config: innerContext?.config ?? config,\n inputs: resolveInputOverrides(\n newOptions.inputs,\n inputs,\n innerContext?.inputs,\n ) as any, // TODO: Might be able to improve this once legacy inputs are gone\n }) as Iterable<any>,\n newOptions.output,\n );\n },\n {\n node,\n config,\n inputs,\n },\n );\n\n const deduplicatedResult = new Map<string, UOverrideFactoryOutput>();\n for (const item of parentResult) {\n deduplicatedResult.set(item.id, item);\n }\n\n return deduplicatedResult.values() as Iterable<UOverrideFactoryOutput>;\n },\n } as CreateExtensionOptions<TKind, TNamespace, TName, AnyExtensionDataRef extends UNewOutput ? UOutput : UNewOutput, TInputs & TExtraInputs, TConfigSchema & TExtensionConfigSchema, UOverrideFactoryOutput>);\n },\n } as InternalExtensionDefinition<\n TConfig &\n (string extends keyof TConfigSchema\n ? {}\n : {\n [key in keyof TConfigSchema]: z.infer<\n ReturnType<TConfigSchema[key]>\n >;\n }),\n TConfigInput &\n (string extends keyof TConfigSchema\n ? {}\n : z.input<\n z.ZodObject<{\n [key in keyof TConfigSchema]: ReturnType<TConfigSchema[key]>;\n }>\n >),\n UOutput,\n TInputs,\n TKind,\n TNamespace,\n TName\n >;\n}\n"],"names":[],"mappings":";;;AAqWO,SAAS,8BACd,SACoD,EAAA;AACpD,EAAA,MAAM,QAAW,GAAA,SAAA,CAAA;AAIjB,EAAI,IAAA,QAAA,CAAS,WAAW,gCAAkC,EAAA;AACxD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,iDAAA,EAAoD,SAAS,MAAM,CAAA,CAAA,CAAA;AAAA,KACrE,CAAA;AAAA,GACF;AACA,EAAA,MAAM,UAAU,QAAS,CAAA,OAAA,CAAA;AACzB,EAAI,IAAA,OAAA,KAAY,IAAQ,IAAA,OAAA,KAAY,IAAM,EAAA;AACxC,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,uDAAuD,OAAO,CAAA,CAAA,CAAA;AAAA,KAChE,CAAA;AAAA,GACF;AACA,EAAO,OAAA,QAAA,CAAA;AACT;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createPlugin.esm.js","sources":["../../../../../frontend-plugin-api/src/wiring/createPlugin.ts"],"sourcesContent":["/*\n * Copyright 2023 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 { ExtensionDefinition } from './createExtension';\nimport {\n Extension,\n resolveExtensionDefinition,\n} from './resolveExtensionDefinition';\nimport {\n AnyExternalRoutes,\n AnyRoutes,\n BackstagePlugin,\n FeatureFlagConfig,\n} from './types';\n\n/** @public */\nexport interface PluginOptions<\n
|
|
1
|
+
{"version":3,"file":"createPlugin.esm.js","sources":["../../../../../frontend-plugin-api/src/wiring/createPlugin.ts"],"sourcesContent":["/*\n * Copyright 2023 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 { ExtensionDefinition } from './createExtension';\nimport {\n Extension,\n ResolveExtensionId,\n resolveExtensionDefinition,\n} from './resolveExtensionDefinition';\nimport {\n AnyExternalRoutes,\n AnyRoutes,\n BackstagePlugin,\n FeatureFlagConfig,\n} from './types';\n\n/** @public */\nexport interface PluginOptions<\n TId extends string,\n TRoutes extends AnyRoutes,\n TExternalRoutes extends AnyExternalRoutes,\n TExtensions extends readonly ExtensionDefinition<any, any>[],\n> {\n id: TId;\n routes?: TRoutes;\n externalRoutes?: TExternalRoutes;\n extensions?: TExtensions;\n featureFlags?: FeatureFlagConfig[];\n}\n\n/** @public */\nexport interface InternalBackstagePlugin<\n TRoutes extends AnyRoutes = AnyRoutes,\n TExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,\n> extends BackstagePlugin<TRoutes, TExternalRoutes> {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n}\n\n/** @public */\nexport function createPlugin<\n TId extends string,\n TRoutes extends AnyRoutes = {},\n TExternalRoutes extends AnyExternalRoutes = {},\n TExtensions extends readonly ExtensionDefinition<any, any>[] = [],\n>(\n options: PluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>,\n): BackstagePlugin<\n TRoutes,\n TExternalRoutes,\n {\n [KExtension in TExtensions[number] as ResolveExtensionId<\n KExtension,\n TId\n >]: KExtension;\n }\n> {\n const extensions = new Array<Extension<unknown>>();\n const extensionDefinitionsById = new Map<\n string,\n ExtensionDefinition<unknown>\n >();\n\n for (const def of options.extensions ?? []) {\n const ext = resolveExtensionDefinition(def, { namespace: options.id });\n extensions.push(ext);\n extensionDefinitionsById.set(ext.id, { ...def, namespace: options.id });\n }\n\n if (extensions.length !== extensionDefinitionsById.size) {\n const extensionIds = extensions.map(e => e.id);\n const duplicates = Array.from(\n new Set(\n extensionIds.filter((id, index) => extensionIds.indexOf(id) !== index),\n ),\n );\n // TODO(Rugvip): This could provide some more information about the kind + name of the extensions\n throw new Error(\n `Plugin '${options.id}' provided duplicate extensions: ${duplicates.join(\n ', ',\n )}`,\n );\n }\n\n return {\n $$type: '@backstage/BackstagePlugin',\n version: 'v1',\n id: options.id,\n routes: options.routes ?? ({} as TRoutes),\n externalRoutes: options.externalRoutes ?? ({} as TExternalRoutes),\n featureFlags: options.featureFlags ?? [],\n extensions,\n getExtension(id) {\n return extensionDefinitionsById.get(id);\n },\n toString() {\n return `Plugin{id=${options.id}}`;\n },\n withOverrides(overrides) {\n const overriddenExtensionIds = new Set(\n overrides.extensions.map(\n e => resolveExtensionDefinition(e, { namespace: options.id }).id,\n ),\n );\n const nonOverriddenExtensions = (options.extensions ?? []).filter(\n e =>\n !overriddenExtensionIds.has(\n resolveExtensionDefinition(e, { namespace: options.id }).id,\n ),\n );\n return createPlugin({\n ...options,\n extensions: [...nonOverriddenExtensions, ...overrides.extensions],\n });\n },\n } as InternalBackstagePlugin<TRoutes, TExternalRoutes>;\n}\n\n/** @internal */\nexport function toInternalBackstagePlugin(\n plugin: BackstagePlugin,\n): InternalBackstagePlugin {\n const internal = plugin as InternalBackstagePlugin;\n if (internal.$$type !== '@backstage/BackstagePlugin') {\n throw new Error(`Invalid plugin instance, bad type '${internal.$$type}'`);\n }\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid plugin instance, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n"],"names":[],"mappings":";;;AAqIO,SAAS,0BACd,MACyB,EAAA;AACzB,EAAA,MAAM,QAAW,GAAA,MAAA,CAAA;AACjB,EAAI,IAAA,QAAA,CAAS,WAAW,4BAA8B,EAAA;AACpD,IAAA,MAAM,IAAI,KAAA,CAAM,CAAsC,mCAAA,EAAA,QAAA,CAAS,MAAM,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GAC1E;AACA,EAAI,IAAA,QAAA,CAAS,YAAY,IAAM,EAAA;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,sCAAA,EAAyC,SAAS,OAAO,CAAA,CAAA,CAAA;AAAA,KAC3D,CAAA;AAAA,GACF;AACA,EAAO,OAAA,QAAA,CAAA;AACT;;;;"}
|
|
@@ -15,7 +15,13 @@ function toInternalExtension(overrides) {
|
|
|
15
15
|
}
|
|
16
16
|
function resolveExtensionDefinition(definition, context) {
|
|
17
17
|
const internalDefinition = toInternalExtensionDefinition(definition);
|
|
18
|
-
const {
|
|
18
|
+
const {
|
|
19
|
+
name,
|
|
20
|
+
kind,
|
|
21
|
+
namespace: _skip1,
|
|
22
|
+
override: _skip2,
|
|
23
|
+
...rest
|
|
24
|
+
} = internalDefinition;
|
|
19
25
|
const namespace = internalDefinition.namespace ?? context?.namespace;
|
|
20
26
|
const namePart = name && namespace ? `${namespace}/${name}` : namespace || name;
|
|
21
27
|
if (!namePart) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveExtensionDefinition.esm.js","sources":["../../../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts"],"sourcesContent":["/*\n * Copyright 2023 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 { AppNode } from '../apis';\nimport {\n AnyExtensionDataMap,\n AnyExtensionInputMap,\n ExtensionDataValues,\n ExtensionDefinition,\n ResolvedExtensionInputs,\n toInternalExtensionDefinition,\n} from './createExtension';\nimport { PortableSchema } from '../schema';\nimport { ExtensionInput } from './createExtensionInput';\nimport {\n AnyExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\n\n/** @public */\nexport interface Extension<TConfig, TConfigInput = TConfig> {\n $$type: '@backstage/Extension';\n readonly id: string;\n readonly attachTo: { id: string; input: string };\n readonly disabled: boolean;\n readonly configSchema?: PortableSchema<TConfig, TConfigInput>;\n}\n\n/** @internal */\nexport type InternalExtension<TConfig, TConfigInput> = Extension<\n TConfig,\n TConfigInput\n> &\n (\n | {\n readonly version: 'v1';\n readonly inputs: AnyExtensionInputMap;\n readonly output: AnyExtensionDataMap;\n factory(options: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<AnyExtensionInputMap>;\n }): ExtensionDataValues<any>;\n }\n | {\n readonly version: 'v2';\n readonly inputs: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n readonly output: Array<AnyExtensionDataRef>;\n factory(options: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n }>;\n }): Iterable<ExtensionDataValue<any, any>>;\n }\n );\n\n/** @internal */\nexport function toInternalExtension<TConfig, TConfigInput>(\n overrides: Extension<TConfig, TConfigInput>,\n): InternalExtension<TConfig, TConfigInput> {\n const internal = overrides as InternalExtension<TConfig, TConfigInput>;\n if (internal.$$type !== '@backstage/Extension') {\n throw new Error(\n `Invalid extension instance, bad type '${internal.$$type}'`,\n );\n }\n const version = internal.version;\n if (version !== 'v1' && version !== 'v2') {\n throw new Error(`Invalid extension instance, bad version '${version}'`);\n }\n return internal;\n}\n\n/** @internal */\nexport function resolveExtensionDefinition<TConfig, TConfigInput>(\n definition: ExtensionDefinition<TConfig, TConfigInput>,\n context?: { namespace?: string },\n): Extension<TConfig, TConfigInput> {\n const internalDefinition = toInternalExtensionDefinition(definition);\n const {
|
|
1
|
+
{"version":3,"file":"resolveExtensionDefinition.esm.js","sources":["../../../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts"],"sourcesContent":["/*\n * Copyright 2023 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 { AppNode } from '../apis';\nimport {\n AnyExtensionDataMap,\n AnyExtensionInputMap,\n ExtensionDataValues,\n ExtensionDefinition,\n ResolvedExtensionInputs,\n toInternalExtensionDefinition,\n} from './createExtension';\nimport { PortableSchema } from '../schema';\nimport { ExtensionInput } from './createExtensionInput';\nimport {\n AnyExtensionDataRef,\n ExtensionDataValue,\n} from './createExtensionDataRef';\n\n/** @public */\nexport interface Extension<TConfig, TConfigInput = TConfig> {\n $$type: '@backstage/Extension';\n readonly id: string;\n readonly attachTo: { id: string; input: string };\n readonly disabled: boolean;\n readonly configSchema?: PortableSchema<TConfig, TConfigInput>;\n}\n\n/** @internal */\nexport type InternalExtension<TConfig, TConfigInput> = Extension<\n TConfig,\n TConfigInput\n> &\n (\n | {\n readonly version: 'v1';\n readonly inputs: AnyExtensionInputMap;\n readonly output: AnyExtensionDataMap;\n factory(options: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<AnyExtensionInputMap>;\n }): ExtensionDataValues<any>;\n }\n | {\n readonly version: 'v2';\n readonly inputs: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n };\n readonly output: Array<AnyExtensionDataRef>;\n factory(options: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n }>;\n }): Iterable<ExtensionDataValue<any, any>>;\n }\n );\n\n/** @internal */\nexport function toInternalExtension<TConfig, TConfigInput>(\n overrides: Extension<TConfig, TConfigInput>,\n): InternalExtension<TConfig, TConfigInput> {\n const internal = overrides as InternalExtension<TConfig, TConfigInput>;\n if (internal.$$type !== '@backstage/Extension') {\n throw new Error(\n `Invalid extension instance, bad type '${internal.$$type}'`,\n );\n }\n const version = internal.version;\n if (version !== 'v1' && version !== 'v2') {\n throw new Error(`Invalid extension instance, bad version '${version}'`);\n }\n return internal;\n}\n\n/** @ignore */\nexport type ResolveExtensionId<\n TExtension extends ExtensionDefinition<any>,\n TDefaultNamespace extends string | undefined,\n> = TExtension extends ExtensionDefinition<\n any,\n any,\n any,\n any,\n infer IKind,\n infer INamespace,\n infer IName\n>\n ? [string | undefined] extends [IKind | INamespace | IName]\n ? never\n : (\n (\n undefined extends TDefaultNamespace ? INamespace : TDefaultNamespace\n ) extends infer ISelectedNamespace extends string\n ? undefined extends IName\n ? ISelectedNamespace\n : `${ISelectedNamespace}/${IName}`\n : IName\n ) extends infer INamePart extends string\n ? IKind extends string\n ? `${IKind}:${INamePart}`\n : INamePart\n : never\n : never;\n\n/** @internal */\nexport function resolveExtensionDefinition<TConfig, TConfigInput>(\n definition: ExtensionDefinition<TConfig, TConfigInput>,\n context?: { namespace?: string },\n): Extension<TConfig, TConfigInput> {\n const internalDefinition = toInternalExtensionDefinition(definition);\n const {\n name,\n kind,\n namespace: _skip1,\n override: _skip2,\n ...rest\n } = internalDefinition;\n const namespace = internalDefinition.namespace ?? context?.namespace;\n\n const namePart =\n name && namespace ? `${namespace}/${name}` : namespace || name;\n if (!namePart) {\n throw new Error(\n `Extension must declare an explicit namespace or name as it could not be resolved from context, kind=${kind} namespace=${namespace} name=${name}`,\n );\n }\n\n const id = kind ? `${kind}:${namePart}` : namePart;\n\n return {\n ...rest,\n $$type: '@backstage/Extension',\n version: internalDefinition.version,\n id,\n toString() {\n return `Extension{id=${id}}`;\n },\n } as InternalExtension<TConfig, TConfigInput>;\n}\n"],"names":[],"mappings":";;AAgFO,SAAS,oBACd,SAC0C,EAAA;AAC1C,EAAA,MAAM,QAAW,GAAA,SAAA,CAAA;AACjB,EAAI,IAAA,QAAA,CAAS,WAAW,sBAAwB,EAAA;AAC9C,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,sCAAA,EAAyC,SAAS,MAAM,CAAA,CAAA,CAAA;AAAA,KAC1D,CAAA;AAAA,GACF;AACA,EAAA,MAAM,UAAU,QAAS,CAAA,OAAA,CAAA;AACzB,EAAI,IAAA,OAAA,KAAY,IAAQ,IAAA,OAAA,KAAY,IAAM,EAAA;AACxC,IAAA,MAAM,IAAI,KAAA,CAAM,CAA4C,yCAAA,EAAA,OAAO,CAAG,CAAA,CAAA,CAAA,CAAA;AAAA,GACxE;AACA,EAAO,OAAA,QAAA,CAAA;AACT,CAAA;AAiCgB,SAAA,0BAAA,CACd,YACA,OACkC,EAAA;AAClC,EAAM,MAAA,kBAAA,GAAqB,8BAA8B,UAAU,CAAA,CAAA;AACnE,EAAM,MAAA;AAAA,IACJ,IAAA;AAAA,IACA,IAAA;AAAA,IACA,SAAW,EAAA,MAAA;AAAA,IACX,QAAU,EAAA,MAAA;AAAA,IACV,GAAG,IAAA;AAAA,GACD,GAAA,kBAAA,CAAA;AACJ,EAAM,MAAA,SAAA,GAAY,kBAAmB,CAAA,SAAA,IAAa,OAAS,EAAA,SAAA,CAAA;AAE3D,EAAM,MAAA,QAAA,GACJ,QAAQ,SAAY,GAAA,CAAA,EAAG,SAAS,CAAI,CAAA,EAAA,IAAI,KAAK,SAAa,IAAA,IAAA,CAAA;AAC5D,EAAA,IAAI,CAAC,QAAU,EAAA;AACb,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAuG,oGAAA,EAAA,IAAI,CAAc,WAAA,EAAA,SAAS,SAAS,IAAI,CAAA,CAAA;AAAA,KACjJ,CAAA;AAAA,GACF;AAEA,EAAA,MAAM,KAAK,IAAO,GAAA,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,QAAQ,CAAK,CAAA,GAAA,QAAA,CAAA;AAE1C,EAAO,OAAA;AAAA,IACL,GAAG,IAAA;AAAA,IACH,MAAQ,EAAA,sBAAA;AAAA,IACR,SAAS,kBAAmB,CAAA,OAAA;AAAA,IAC5B,EAAA;AAAA,IACA,QAAW,GAAA;AACT,MAAA,OAAO,gBAAgB,EAAE,CAAA,CAAA,CAAA,CAAA;AAAA,KAC3B;AAAA,GACF,CAAA;AACF;;;;"}
|
package/dist/index.d.ts
CHANGED
|
@@ -28,7 +28,7 @@ type PartialKeys<Map extends {
|
|
|
28
28
|
type TargetRouteMap<ExternalRoutes extends {
|
|
29
29
|
[name: string]: ExternalRouteRef;
|
|
30
30
|
}> = {
|
|
31
|
-
[name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef<infer Params
|
|
31
|
+
[name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef<infer Params> ? RouteRef<Params> | SubRouteRef<Params> : never;
|
|
32
32
|
};
|
|
33
33
|
/**
|
|
34
34
|
* A function that can bind from external routes of a given plugin, to concrete
|
|
@@ -38,7 +38,7 @@ type TargetRouteMap<ExternalRoutes extends {
|
|
|
38
38
|
*/
|
|
39
39
|
type CreateAppRouteBinder = <TExternalRoutes extends {
|
|
40
40
|
[name: string]: ExternalRouteRef;
|
|
41
|
-
}>(externalRoutes: TExternalRoutes, targetRoutes: PartialKeys<TargetRouteMap<TExternalRoutes>, KeysWithType<TExternalRoutes, ExternalRouteRef<any
|
|
41
|
+
}>(externalRoutes: TExternalRoutes, targetRoutes: PartialKeys<TargetRouteMap<TExternalRoutes>, KeysWithType<TExternalRoutes, ExternalRouteRef<any>>>) => void;
|
|
42
42
|
|
|
43
43
|
/**
|
|
44
44
|
* A source of dynamically loaded frontend features.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"RouteResolver.esm.js","sources":["../../src/routing/RouteResolver.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 { generatePath, matchRoutes } from 'react-router-dom';\nimport {\n RouteRef,\n ExternalRouteRef,\n SubRouteRef,\n AnyRouteRefParams,\n RouteFunc,\n RouteResolutionApiResolveOptions,\n RouteResolutionApi,\n} from '@backstage/frontend-plugin-api';\nimport mapValues from 'lodash/mapValues';\nimport { AnyRouteRef, BackstageRouteObject } from './types';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { isRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n isSubRouteRef,\n toInternalSubRouteRef,\n} from '../../../frontend-plugin-api/src/routing/SubRouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { isExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef';\n\n// Joins a list of paths together, avoiding trailing and duplicate slashes\nexport function joinPaths(...paths: string[]): string {\n const normalized = paths.join('/').replace(/\\/\\/+/g, '/');\n if (normalized !== '/' && normalized.endsWith('/')) {\n return normalized.slice(0, -1);\n }\n return normalized;\n}\n\n/**\n * Resolves the absolute route ref that our target route ref is pointing pointing to, as well\n * as the relative target path.\n *\n * Returns an undefined target ref if one could not be fully resolved.\n */\nfunction resolveTargetRef(\n anyRouteRef: AnyRouteRef,\n routePaths: Map<RouteRef, string>,\n routeBindings: Map<AnyRouteRef, AnyRouteRef | undefined>,\n): readonly [RouteRef | undefined, string] {\n // First we figure out which absolute route ref we're dealing with, an if there was an sub route path to append.\n // For sub routes it will be the parent path, while for external routes it will be the bound route.\n let targetRef: RouteRef;\n let subRoutePath = '';\n if (isRouteRef(anyRouteRef)) {\n targetRef = anyRouteRef;\n } else if (isSubRouteRef(anyRouteRef)) {\n const internal = toInternalSubRouteRef(anyRouteRef);\n targetRef = internal.getParent();\n subRoutePath = internal.path;\n } else if (isExternalRouteRef(anyRouteRef)) {\n const resolvedRoute = routeBindings.get(anyRouteRef);\n if (!resolvedRoute) {\n return [undefined, ''];\n }\n if (isRouteRef(resolvedRoute)) {\n targetRef = resolvedRoute;\n } else if (isSubRouteRef(resolvedRoute)) {\n const internal = toInternalSubRouteRef(resolvedRoute);\n targetRef = internal.getParent();\n subRoutePath = resolvedRoute.path;\n } else {\n throw new Error(\n `ExternalRouteRef was bound to invalid target, ${resolvedRoute}`,\n );\n }\n } else {\n throw new Error(`Unknown object passed to useRouteRef, got ${anyRouteRef}`);\n }\n\n // Bail if no absolute path could be resolved\n if (!targetRef) {\n return [undefined, ''];\n }\n\n // Find the path that our target route is bound to\n const resolvedPath = routePaths.get(targetRef);\n if (resolvedPath === undefined) {\n return [undefined, ''];\n }\n\n // SubRouteRefs join the path from the parent route with its own path\n const targetPath = joinPaths(resolvedPath, subRoutePath);\n return [targetRef, targetPath];\n}\n\n/**\n * Resolves the complete base path for navigating to the target RouteRef.\n */\nfunction resolveBasePath(\n targetRef: RouteRef,\n sourceLocation: Parameters<typeof matchRoutes>[1],\n routePaths: Map<RouteRef, string>,\n routeParents: Map<RouteRef, RouteRef | undefined>,\n routeObjects: BackstageRouteObject[],\n) {\n // While traversing the app element tree we build up the routeObjects structure\n // used here. It is the same kind of structure that react-router creates, with the\n // addition that associated route refs are stored throughout the tree. This lets\n // us look up all route refs that can be reached from our source location.\n // Because of the similar route object structure, we can use `matchRoutes` from\n // react-router to do the lookup of our current location.\n const match = matchRoutes(routeObjects, sourceLocation) ?? [];\n\n // While we search for a common routing root between our current location and\n // the target route, we build a list of all route refs we find that we need\n // to traverse to reach the target.\n const refDiffList = Array<RouteRef>();\n\n let matchIndex = -1;\n for (\n let targetSearchRef: RouteRef | undefined = targetRef;\n targetSearchRef;\n targetSearchRef = routeParents.get(targetSearchRef)\n ) {\n // The match contains a list of all ancestral route refs present at our current location\n // Starting at the desired target ref and traversing back through its parents, we search\n // for a target ref that is present in the match for our current location. When a match\n // is found it means we have found a common base to resolve the route from.\n matchIndex = match.findIndex(m =>\n (m.route as BackstageRouteObject).routeRefs.has(targetSearchRef!),\n );\n if (matchIndex !== -1) {\n break;\n }\n\n // Every time we move a step up in the ancestry of the target ref, we add the current ref\n // to the diff list, which ends up being the list of route refs to traverse form the common base\n // in order to reach our target.\n refDiffList.unshift(targetSearchRef);\n }\n\n // If our target route is present in the initial match we need to construct the final path\n // from the parent of the matched route segment. That's to allow the caller of the route\n // function to supply their own params.\n if (refDiffList.length === 0) {\n matchIndex -= 1;\n }\n\n // This is the part of the route tree that the target and source locations have in common.\n // We re-use the existing pathname directly along with all params.\n const parentPath = matchIndex === -1 ? '' : match[matchIndex].pathname;\n\n // This constructs the mid section of the path using paths resolved from all route refs\n // we need to traverse to reach our target except for the very last one. None of these\n // paths are allowed to require any parameters, as the caller would have no way of knowing\n // what parameters those are.\n const diffPaths = refDiffList.slice(0, -1).map(ref => {\n const path = routePaths.get(ref);\n if (path === undefined) {\n throw new Error(`No path for ${ref}`);\n }\n if (path.includes(':')) {\n throw new Error(\n `Cannot route to ${targetRef} with parent ${ref} as it has parameters`,\n );\n }\n return path;\n });\n\n return `${joinPaths(parentPath, ...diffPaths)}/`;\n}\n\nexport class RouteResolver implements RouteResolutionApi {\n constructor(\n private readonly routePaths: Map<RouteRef, string>,\n private readonly routeParents: Map<RouteRef, RouteRef | undefined>,\n private readonly routeObjects: BackstageRouteObject[],\n private readonly routeBindings: Map<\n ExternalRouteRef,\n RouteRef | SubRouteRef\n >,\n private readonly appBasePath: string, // base path without a trailing slash\n ) {}\n\n resolve<TParams extends AnyRouteRefParams>(\n anyRouteRef:\n | RouteRef<TParams>\n | SubRouteRef<TParams>\n | ExternalRouteRef<TParams, any>,\n options?: RouteResolutionApiResolveOptions,\n ): RouteFunc<TParams> | undefined {\n // First figure out what our target absolute ref is, as well as our target path.\n const [targetRef, targetPath] = resolveTargetRef(\n anyRouteRef,\n this.routePaths,\n this.routeBindings,\n );\n if (!targetRef) {\n return undefined;\n }\n\n // The location that we get passed in uses the full path, so start by trimming off\n // the app base path prefix in case we're running the app on a sub-path.\n const relativeSourceLocation = this.trimPath(options?.sourcePath ?? '');\n\n // Next we figure out the base path, which is the combination of the common parent path\n // between our current location and our target location, as well as the additional path\n // that is the difference between the parent path and the base of our target location.\n const basePath = resolveBasePath(\n targetRef,\n relativeSourceLocation,\n this.routePaths,\n this.routeParents,\n this.routeObjects,\n );\n\n const routeFunc: RouteFunc<TParams> = (...[params]) => {\n // We selectively encode some some known-dangerous characters in the\n // params. The reason that we don't perform a blanket `encodeURIComponent`\n // here is that this encoding was added defensively long after the initial\n // release of this code. There's likely to be many users of this code that\n // already encode their parameters knowing that this code didn't do this\n // for them in the past. Therefore, we are extra careful NOT to include\n // the percent character in this set, even though that might seem like a\n // bad idea.\n const encodedParams =\n params &&\n mapValues(params, value => {\n if (typeof value === 'string') {\n return value.replaceAll(/[&?#;\\/]/g, c => encodeURIComponent(c));\n }\n return value;\n });\n return joinPaths(basePath, generatePath(targetPath, encodedParams));\n };\n return routeFunc;\n }\n\n private trimPath(targetPath: string) {\n if (!targetPath) {\n return targetPath;\n }\n\n if (targetPath.startsWith(this.appBasePath)) {\n return targetPath.slice(this.appBasePath.length);\n }\n return targetPath;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"RouteResolver.esm.js","sources":["../../src/routing/RouteResolver.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 { generatePath, matchRoutes } from 'react-router-dom';\nimport {\n RouteRef,\n ExternalRouteRef,\n SubRouteRef,\n AnyRouteRefParams,\n RouteFunc,\n RouteResolutionApiResolveOptions,\n RouteResolutionApi,\n} from '@backstage/frontend-plugin-api';\nimport mapValues from 'lodash/mapValues';\nimport { AnyRouteRef, BackstageRouteObject } from './types';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { isRouteRef } from '../../../frontend-plugin-api/src/routing/RouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport {\n isSubRouteRef,\n toInternalSubRouteRef,\n} from '../../../frontend-plugin-api/src/routing/SubRouteRef';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { isExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef';\n\n// Joins a list of paths together, avoiding trailing and duplicate slashes\nexport function joinPaths(...paths: string[]): string {\n const normalized = paths.join('/').replace(/\\/\\/+/g, '/');\n if (normalized !== '/' && normalized.endsWith('/')) {\n return normalized.slice(0, -1);\n }\n return normalized;\n}\n\n/**\n * Resolves the absolute route ref that our target route ref is pointing pointing to, as well\n * as the relative target path.\n *\n * Returns an undefined target ref if one could not be fully resolved.\n */\nfunction resolveTargetRef(\n anyRouteRef: AnyRouteRef,\n routePaths: Map<RouteRef, string>,\n routeBindings: Map<AnyRouteRef, AnyRouteRef | undefined>,\n): readonly [RouteRef | undefined, string] {\n // First we figure out which absolute route ref we're dealing with, an if there was an sub route path to append.\n // For sub routes it will be the parent path, while for external routes it will be the bound route.\n let targetRef: RouteRef;\n let subRoutePath = '';\n if (isRouteRef(anyRouteRef)) {\n targetRef = anyRouteRef;\n } else if (isSubRouteRef(anyRouteRef)) {\n const internal = toInternalSubRouteRef(anyRouteRef);\n targetRef = internal.getParent();\n subRoutePath = internal.path;\n } else if (isExternalRouteRef(anyRouteRef)) {\n const resolvedRoute = routeBindings.get(anyRouteRef);\n if (!resolvedRoute) {\n return [undefined, ''];\n }\n if (isRouteRef(resolvedRoute)) {\n targetRef = resolvedRoute;\n } else if (isSubRouteRef(resolvedRoute)) {\n const internal = toInternalSubRouteRef(resolvedRoute);\n targetRef = internal.getParent();\n subRoutePath = resolvedRoute.path;\n } else {\n throw new Error(\n `ExternalRouteRef was bound to invalid target, ${resolvedRoute}`,\n );\n }\n } else {\n throw new Error(`Unknown object passed to useRouteRef, got ${anyRouteRef}`);\n }\n\n // Bail if no absolute path could be resolved\n if (!targetRef) {\n return [undefined, ''];\n }\n\n // Find the path that our target route is bound to\n const resolvedPath = routePaths.get(targetRef);\n if (resolvedPath === undefined) {\n return [undefined, ''];\n }\n\n // SubRouteRefs join the path from the parent route with its own path\n const targetPath = joinPaths(resolvedPath, subRoutePath);\n return [targetRef, targetPath];\n}\n\n/**\n * Resolves the complete base path for navigating to the target RouteRef.\n */\nfunction resolveBasePath(\n targetRef: RouteRef,\n sourceLocation: Parameters<typeof matchRoutes>[1],\n routePaths: Map<RouteRef, string>,\n routeParents: Map<RouteRef, RouteRef | undefined>,\n routeObjects: BackstageRouteObject[],\n) {\n // While traversing the app element tree we build up the routeObjects structure\n // used here. It is the same kind of structure that react-router creates, with the\n // addition that associated route refs are stored throughout the tree. This lets\n // us look up all route refs that can be reached from our source location.\n // Because of the similar route object structure, we can use `matchRoutes` from\n // react-router to do the lookup of our current location.\n const match = matchRoutes(routeObjects, sourceLocation) ?? [];\n\n // While we search for a common routing root between our current location and\n // the target route, we build a list of all route refs we find that we need\n // to traverse to reach the target.\n const refDiffList = Array<RouteRef>();\n\n let matchIndex = -1;\n for (\n let targetSearchRef: RouteRef | undefined = targetRef;\n targetSearchRef;\n targetSearchRef = routeParents.get(targetSearchRef)\n ) {\n // The match contains a list of all ancestral route refs present at our current location\n // Starting at the desired target ref and traversing back through its parents, we search\n // for a target ref that is present in the match for our current location. When a match\n // is found it means we have found a common base to resolve the route from.\n matchIndex = match.findIndex(m =>\n (m.route as BackstageRouteObject).routeRefs.has(targetSearchRef!),\n );\n if (matchIndex !== -1) {\n break;\n }\n\n // Every time we move a step up in the ancestry of the target ref, we add the current ref\n // to the diff list, which ends up being the list of route refs to traverse form the common base\n // in order to reach our target.\n refDiffList.unshift(targetSearchRef);\n }\n\n // If our target route is present in the initial match we need to construct the final path\n // from the parent of the matched route segment. That's to allow the caller of the route\n // function to supply their own params.\n if (refDiffList.length === 0) {\n matchIndex -= 1;\n }\n\n // This is the part of the route tree that the target and source locations have in common.\n // We re-use the existing pathname directly along with all params.\n const parentPath = matchIndex === -1 ? '' : match[matchIndex].pathname;\n\n // This constructs the mid section of the path using paths resolved from all route refs\n // we need to traverse to reach our target except for the very last one. None of these\n // paths are allowed to require any parameters, as the caller would have no way of knowing\n // what parameters those are.\n const diffPaths = refDiffList.slice(0, -1).map(ref => {\n const path = routePaths.get(ref);\n if (path === undefined) {\n throw new Error(`No path for ${ref}`);\n }\n if (path.includes(':')) {\n throw new Error(\n `Cannot route to ${targetRef} with parent ${ref} as it has parameters`,\n );\n }\n return path;\n });\n\n return `${joinPaths(parentPath, ...diffPaths)}/`;\n}\n\nexport class RouteResolver implements RouteResolutionApi {\n constructor(\n private readonly routePaths: Map<RouteRef, string>,\n private readonly routeParents: Map<RouteRef, RouteRef | undefined>,\n private readonly routeObjects: BackstageRouteObject[],\n private readonly routeBindings: Map<\n ExternalRouteRef,\n RouteRef | SubRouteRef\n >,\n private readonly appBasePath: string, // base path without a trailing slash\n ) {}\n\n resolve<TParams extends AnyRouteRefParams>(\n anyRouteRef:\n | RouteRef<TParams>\n | SubRouteRef<TParams>\n | ExternalRouteRef<TParams>,\n options?: RouteResolutionApiResolveOptions,\n ): RouteFunc<TParams> | undefined {\n // First figure out what our target absolute ref is, as well as our target path.\n const [targetRef, targetPath] = resolveTargetRef(\n anyRouteRef,\n this.routePaths,\n this.routeBindings,\n );\n if (!targetRef) {\n return undefined;\n }\n\n // The location that we get passed in uses the full path, so start by trimming off\n // the app base path prefix in case we're running the app on a sub-path.\n const relativeSourceLocation = this.trimPath(options?.sourcePath ?? '');\n\n // Next we figure out the base path, which is the combination of the common parent path\n // between our current location and our target location, as well as the additional path\n // that is the difference between the parent path and the base of our target location.\n const basePath = resolveBasePath(\n targetRef,\n relativeSourceLocation,\n this.routePaths,\n this.routeParents,\n this.routeObjects,\n );\n\n const routeFunc: RouteFunc<TParams> = (...[params]) => {\n // We selectively encode some some known-dangerous characters in the\n // params. The reason that we don't perform a blanket `encodeURIComponent`\n // here is that this encoding was added defensively long after the initial\n // release of this code. There's likely to be many users of this code that\n // already encode their parameters knowing that this code didn't do this\n // for them in the past. Therefore, we are extra careful NOT to include\n // the percent character in this set, even though that might seem like a\n // bad idea.\n const encodedParams =\n params &&\n mapValues(params, value => {\n if (typeof value === 'string') {\n return value.replaceAll(/[&?#;\\/]/g, c => encodeURIComponent(c));\n }\n return value;\n });\n return joinPaths(basePath, generatePath(targetPath, encodedParams));\n };\n return routeFunc;\n }\n\n private trimPath(targetPath: string) {\n if (!targetPath) {\n return targetPath;\n }\n\n if (targetPath.startsWith(this.appBasePath)) {\n return targetPath.slice(this.appBasePath.length);\n }\n return targetPath;\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -9,11 +9,6 @@ function resolveRouteBindings(bindRoutes, config, routesById) {
|
|
|
9
9
|
if (!externalRoute) {
|
|
10
10
|
throw new Error(`Key ${key} is not an existing external route`);
|
|
11
11
|
}
|
|
12
|
-
if (!value && !externalRoute.optional) {
|
|
13
|
-
throw new Error(
|
|
14
|
-
`External route ${key} is required but was undefined`
|
|
15
|
-
);
|
|
16
|
-
}
|
|
17
12
|
if (value) {
|
|
18
13
|
result.set(externalRoute, value);
|
|
19
14
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveRouteBindings.esm.js","sources":["../../src/routing/resolveRouteBindings.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 SubRouteRef,\n ExternalRouteRef,\n} from '@backstage/frontend-plugin-api';\nimport { RouteRefsById } from './collectRouteIds';\nimport { Config } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef';\n\n/**\n * Extracts a union of the keys in a map whose value extends the given type\n *\n * @ignore\n */\ntype KeysWithType<Obj extends { [key in string]: any }, Type> = {\n [key in keyof Obj]: Obj[key] extends Type ? key : never;\n}[keyof Obj];\n\n/**\n * Takes a map Map required values and makes all keys matching Keys optional\n *\n * @ignore\n */\ntype PartialKeys<\n Map extends { [name in string]: any },\n Keys extends keyof Map,\n> = Partial<Pick<Map, Keys>> & Required<Omit<Map, Keys>>;\n\n/**\n * Creates a map of target routes with matching parameters based on a map of external routes.\n *\n * @ignore\n */\ntype TargetRouteMap<\n ExternalRoutes extends { [name: string]: ExternalRouteRef },\n> = {\n [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef<\n infer Params
|
|
1
|
+
{"version":3,"file":"resolveRouteBindings.esm.js","sources":["../../src/routing/resolveRouteBindings.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 SubRouteRef,\n ExternalRouteRef,\n} from '@backstage/frontend-plugin-api';\nimport { RouteRefsById } from './collectRouteIds';\nimport { Config } from '@backstage/config';\nimport { JsonObject } from '@backstage/types';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExternalRouteRef } from '../../../frontend-plugin-api/src/routing/ExternalRouteRef';\n\n/**\n * Extracts a union of the keys in a map whose value extends the given type\n *\n * @ignore\n */\ntype KeysWithType<Obj extends { [key in string]: any }, Type> = {\n [key in keyof Obj]: Obj[key] extends Type ? key : never;\n}[keyof Obj];\n\n/**\n * Takes a map Map required values and makes all keys matching Keys optional\n *\n * @ignore\n */\ntype PartialKeys<\n Map extends { [name in string]: any },\n Keys extends keyof Map,\n> = Partial<Pick<Map, Keys>> & Required<Omit<Map, Keys>>;\n\n/**\n * Creates a map of target routes with matching parameters based on a map of external routes.\n *\n * @ignore\n */\ntype TargetRouteMap<\n ExternalRoutes extends { [name: string]: ExternalRouteRef },\n> = {\n [name in keyof ExternalRoutes]: ExternalRoutes[name] extends ExternalRouteRef<\n infer Params\n >\n ? RouteRef<Params> | SubRouteRef<Params>\n : never;\n};\n\n/**\n * A function that can bind from external routes of a given plugin, to concrete\n * routes of other plugins. See {@link createApp}.\n *\n * @public\n */\nexport type CreateAppRouteBinder = <\n TExternalRoutes extends { [name: string]: ExternalRouteRef },\n>(\n externalRoutes: TExternalRoutes,\n targetRoutes: PartialKeys<\n TargetRouteMap<TExternalRoutes>,\n KeysWithType<TExternalRoutes, ExternalRouteRef<any>>\n >,\n) => void;\n\n/** @internal */\nexport function resolveRouteBindings(\n bindRoutes: ((context: { bind: CreateAppRouteBinder }) => void) | undefined,\n config: Config,\n routesById: RouteRefsById,\n): Map<ExternalRouteRef, RouteRef | SubRouteRef> {\n const result = new Map<ExternalRouteRef, RouteRef | SubRouteRef>();\n\n // Perform callback bindings first with highest priority\n if (bindRoutes) {\n const bind: CreateAppRouteBinder = (\n externalRoutes,\n targetRoutes: { [name: string]: RouteRef | SubRouteRef },\n ) => {\n for (const [key, value] of Object.entries(targetRoutes)) {\n const externalRoute = externalRoutes[key];\n if (!externalRoute) {\n throw new Error(`Key ${key} is not an existing external route`);\n }\n if (value) {\n result.set(externalRoute, value);\n }\n }\n };\n bindRoutes({ bind });\n }\n\n // Then perform config based bindings with lower priority\n const bindings = config\n .getOptionalConfig('app.routes.bindings')\n ?.get<JsonObject>();\n const disabledExternalRefs = new Set<ExternalRouteRef>();\n if (bindings) {\n for (const [externalRefId, targetRefId] of Object.entries(bindings)) {\n if (!isValidTargetRefId(targetRefId)) {\n throw new Error(\n `Invalid config at app.routes.bindings['${externalRefId}'], value must be a non-empty string or false`,\n );\n }\n\n const externalRef = routesById.externalRoutes.get(externalRefId);\n if (!externalRef) {\n throw new Error(\n `Invalid config at app.routes.bindings, '${externalRefId}' is not a valid external route`,\n );\n }\n\n if (targetRefId === false) {\n disabledExternalRefs.add(externalRef);\n\n result.delete(externalRef);\n } else if (!result.has(externalRef)) {\n const targetRef = routesById.routes.get(targetRefId);\n if (!targetRef) {\n throw new Error(\n `Invalid config at app.routes.bindings['${externalRefId}'], '${targetRefId}' is not a valid route`,\n );\n }\n\n result.set(externalRef, targetRef);\n }\n }\n }\n\n // Finally fall back to attempting to map defaults, at lowest priority\n for (const externalRef of routesById.externalRoutes.values()) {\n if (!result.has(externalRef) && !disabledExternalRefs.has(externalRef)) {\n const defaultRefId =\n toInternalExternalRouteRef(externalRef).getDefaultTarget();\n if (defaultRefId) {\n const defaultRef = routesById.routes.get(defaultRefId);\n if (defaultRef) {\n result.set(externalRef, defaultRef);\n }\n }\n }\n }\n\n return result;\n}\n\nfunction isValidTargetRefId(value: unknown): value is string | false {\n if (value === false) {\n return true;\n }\n\n if (typeof value === 'string' && value) {\n return true;\n }\n\n return false;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -34,6 +34,15 @@ function resolveInputDataContainer(extensionData, attachment, inputName) {
|
|
|
34
34
|
node: attachment,
|
|
35
35
|
get(ref) {
|
|
36
36
|
return dataMap.get(ref.id);
|
|
37
|
+
},
|
|
38
|
+
*[Symbol.iterator]() {
|
|
39
|
+
for (const [id, value] of dataMap) {
|
|
40
|
+
yield {
|
|
41
|
+
$$type: "@backstage/ExtensionDataValue",
|
|
42
|
+
id,
|
|
43
|
+
value
|
|
44
|
+
};
|
|
45
|
+
}
|
|
37
46
|
}
|
|
38
47
|
};
|
|
39
48
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instantiateAppNodeTree.esm.js","sources":["../../src/tree/instantiateAppNodeTree.ts"],"sourcesContent":["/*\n * Copyright 2023 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 AnyExtensionDataMap,\n AnyExtensionDataRef,\n AnyExtensionInputMap,\n ExtensionDataContainer,\n ExtensionDataRef,\n ExtensionInput,\n ResolvedExtensionInputs,\n} from '@backstage/frontend-plugin-api';\nimport mapValues from 'lodash/mapValues';\nimport { AppNode, AppNodeInstance } from '@backstage/frontend-plugin-api';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExtension } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nfunction resolveInputDataMap(\n dataMap: AnyExtensionDataMap,\n attachment: AppNode,\n inputName: string,\n) {\n return mapValues(dataMap, ref => {\n const value = attachment.instance?.getData(ref);\n if (value === undefined && !ref.config.optional) {\n const expected = Object.values(dataMap)\n .filter(r => !r.config.optional)\n .map(r => `'${r.id}'`)\n .join(', ');\n\n const provided = [...(attachment.instance?.getDataRefs() ?? [])]\n .map(r => `'${r.id}'`)\n .join(', ');\n\n throw new Error(\n `extension '${attachment.spec.id}' could not be attached because its output data (${provided}) does not match what the input '${inputName}' requires (${expected})`,\n );\n }\n return value;\n });\n}\n\nfunction resolveInputDataContainer(\n extensionData: Array<AnyExtensionDataRef>,\n attachment: AppNode,\n inputName: string,\n): { node: AppNode } & ExtensionDataContainer<AnyExtensionDataRef> {\n const dataMap = new Map<string, unknown>();\n\n for (const ref of extensionData) {\n if (dataMap.has(ref.id)) {\n throw new Error(`Unexpected duplicate input data '${ref.id}'`);\n }\n const value = attachment.instance?.getData(ref);\n if (value === undefined && !ref.config.optional) {\n const expected = extensionData\n .filter(r => !r.config.optional)\n .map(r => `'${r.id}'`)\n .join(', ');\n\n const provided = [...(attachment.instance?.getDataRefs() ?? [])]\n .map(r => `'${r.id}'`)\n .join(', ');\n\n throw new Error(\n `extension '${attachment.spec.id}' could not be attached because its output data (${provided}) does not match what the input '${inputName}' requires (${expected})`,\n );\n }\n\n dataMap.set(ref.id, value);\n }\n\n return {\n node: attachment,\n get(ref) {\n return dataMap.get(ref.id);\n },\n } as { node: AppNode } & ExtensionDataContainer<AnyExtensionDataRef>;\n}\n\nfunction reportUndeclaredAttachments(\n id: string,\n inputMap: { [name in string]: unknown },\n attachments: ReadonlyMap<string, AppNode[]>,\n) {\n const undeclaredAttachments = Array.from(attachments.entries()).filter(\n ([inputName]) => inputMap[inputName] === undefined,\n );\n\n const inputNames = Object.keys(inputMap);\n\n for (const [name, nodes] of undeclaredAttachments) {\n const pl = nodes.length > 1;\n // eslint-disable-next-line no-console\n console.warn(\n [\n `The extension${pl ? 's' : ''} '${nodes\n .map(n => n.spec.id)\n .join(\"', '\")}' ${pl ? 'are' : 'is'}`,\n `attached to the input '${name}' of the extension '${id}', but it`,\n inputNames.length === 0\n ? 'has no inputs'\n : `has no such input (candidates are '${inputNames.join(\"', '\")}')`,\n ].join(' '),\n );\n }\n}\n\nfunction resolveV1Inputs(\n inputMap: AnyExtensionInputMap,\n attachments: ReadonlyMap<string, AppNode[]>,\n): ResolvedExtensionInputs<AnyExtensionInputMap> {\n return mapValues(inputMap, (input, inputName) => {\n const attachedNodes = attachments.get(inputName) ?? [];\n\n if (input.config.singleton) {\n if (attachedNodes.length > 1) {\n const attachedNodeIds = attachedNodes.map(e => e.spec.id);\n throw Error(\n `expected ${\n input.config.optional ? 'at most' : 'exactly'\n } one '${inputName}' input but received multiple: '${attachedNodeIds.join(\n \"', '\",\n )}'`,\n );\n } else if (attachedNodes.length === 0) {\n if (input.config.optional) {\n return undefined;\n }\n throw Error(`input '${inputName}' is required but was not received`);\n }\n return {\n node: attachedNodes[0],\n output: resolveInputDataMap(\n input.extensionData,\n attachedNodes[0],\n inputName,\n ),\n };\n }\n\n return attachedNodes.map(attachment => ({\n node: attachment,\n output: resolveInputDataMap(input.extensionData, attachment, inputName),\n }));\n }) as ResolvedExtensionInputs<AnyExtensionInputMap>;\n}\n\nfunction resolveV2Inputs(\n inputMap: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n attachments: ReadonlyMap<string, AppNode[]>,\n): ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n}> {\n return mapValues(inputMap, (input, inputName) => {\n const attachedNodes = attachments.get(inputName) ?? [];\n\n if (input.config.singleton) {\n if (attachedNodes.length > 1) {\n const attachedNodeIds = attachedNodes.map(e => e.spec.id);\n throw Error(\n `expected ${\n input.config.optional ? 'at most' : 'exactly'\n } one '${inputName}' input but received multiple: '${attachedNodeIds.join(\n \"', '\",\n )}'`,\n );\n } else if (attachedNodes.length === 0) {\n if (input.config.optional) {\n return undefined;\n }\n throw Error(`input '${inputName}' is required but was not received`);\n }\n return resolveInputDataContainer(\n input.extensionData,\n attachedNodes[0],\n inputName,\n );\n }\n\n return attachedNodes.map(attachment =>\n resolveInputDataContainer(input.extensionData, attachment, inputName),\n );\n }) as ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n }>;\n}\n\n/** @internal */\nexport function createAppNodeInstance(options: {\n node: AppNode;\n attachments: ReadonlyMap<string, AppNode[]>;\n}): AppNodeInstance {\n const { node, attachments } = options;\n const { id, extension, config } = node.spec;\n const extensionData = new Map<string, unknown>();\n const extensionDataRefs = new Set<ExtensionDataRef<unknown>>();\n\n let parsedConfig: unknown;\n try {\n parsedConfig = extension.configSchema?.parse(config ?? {});\n } catch (e) {\n throw new Error(\n `Invalid configuration for extension '${id}'; caused by ${e}`,\n );\n }\n\n try {\n const internalExtension = toInternalExtension(extension);\n\n if (process.env.NODE_ENV !== 'production') {\n reportUndeclaredAttachments(id, internalExtension.inputs, attachments);\n }\n\n if (internalExtension.version === 'v1') {\n const namedOutputs = internalExtension.factory({\n node,\n config: parsedConfig,\n inputs: resolveV1Inputs(internalExtension.inputs, attachments),\n });\n\n for (const [name, output] of Object.entries(namedOutputs)) {\n const ref = internalExtension.output[name];\n if (!ref) {\n throw new Error(`unknown output provided via '${name}'`);\n }\n if (extensionData.has(ref.id)) {\n throw new Error(\n `duplicate extension data '${ref.id}' received via output '${name}'`,\n );\n }\n extensionData.set(ref.id, output);\n extensionDataRefs.add(ref);\n }\n } else if (internalExtension.version === 'v2') {\n const outputDataValues = internalExtension.factory({\n node,\n config: parsedConfig,\n inputs: resolveV2Inputs(internalExtension.inputs, attachments),\n });\n\n const outputDataMap = new Map<string, unknown>();\n for (const value of outputDataValues) {\n if (outputDataMap.has(value.id)) {\n throw new Error(`duplicate extension data output '${value.id}'`);\n }\n outputDataMap.set(value.id, value.value);\n }\n\n for (const ref of internalExtension.output) {\n const value = outputDataMap.get(ref.id);\n outputDataMap.delete(ref.id);\n if (value === undefined) {\n if (!ref.config.optional) {\n throw new Error(\n `missing required extension data output '${ref.id}'`,\n );\n }\n } else {\n extensionData.set(ref.id, value);\n extensionDataRefs.add(ref);\n }\n }\n\n if (outputDataMap.size > 0) {\n throw new Error(\n `unexpected output '${Array.from(outputDataMap.keys()).join(\n \"', '\",\n )}'`,\n );\n }\n } else {\n throw new Error(\n `unexpected extension version '${(internalExtension as any).version}'`,\n );\n }\n } catch (e) {\n throw new Error(\n `Failed to instantiate extension '${id}'${\n e.name === 'Error' ? `, ${e.message}` : `; caused by ${e.stack}`\n }`,\n );\n }\n\n return {\n getDataRefs() {\n return extensionDataRefs.values();\n },\n getData<T>(ref: ExtensionDataRef<T>): T | undefined {\n return extensionData.get(ref.id) as T | undefined;\n },\n };\n}\n\n/**\n * Starting at the provided node, instantiate all reachable nodes in the tree that have not been disabled.\n * @internal\n */\nexport function instantiateAppNodeTree(rootNode: AppNode): void {\n function createInstance(node: AppNode): AppNodeInstance | undefined {\n if (node.instance) {\n return node.instance;\n }\n if (node.spec.disabled) {\n return undefined;\n }\n\n const instantiatedAttachments = new Map<string, AppNode[]>();\n\n for (const [input, children] of node.edges.attachments) {\n const instantiatedChildren = children.flatMap(child => {\n const childInstance = createInstance(child);\n if (!childInstance) {\n return [];\n }\n return [child];\n });\n if (instantiatedChildren.length > 0) {\n instantiatedAttachments.set(input, instantiatedChildren);\n }\n }\n\n (node as Mutable<AppNode>).instance = createAppNodeInstance({\n node,\n attachments: instantiatedAttachments,\n });\n\n return node.instance;\n }\n\n createInstance(rootNode);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"instantiateAppNodeTree.esm.js","sources":["../../src/tree/instantiateAppNodeTree.ts"],"sourcesContent":["/*\n * Copyright 2023 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 AnyExtensionDataMap,\n AnyExtensionDataRef,\n AnyExtensionInputMap,\n ExtensionDataContainer,\n ExtensionDataRef,\n ExtensionInput,\n ResolvedExtensionInputs,\n} from '@backstage/frontend-plugin-api';\nimport mapValues from 'lodash/mapValues';\nimport { AppNode, AppNodeInstance } from '@backstage/frontend-plugin-api';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExtension } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';\n\ntype Mutable<T> = {\n -readonly [P in keyof T]: T[P];\n};\n\nfunction resolveInputDataMap(\n dataMap: AnyExtensionDataMap,\n attachment: AppNode,\n inputName: string,\n) {\n return mapValues(dataMap, ref => {\n const value = attachment.instance?.getData(ref);\n if (value === undefined && !ref.config.optional) {\n const expected = Object.values(dataMap)\n .filter(r => !r.config.optional)\n .map(r => `'${r.id}'`)\n .join(', ');\n\n const provided = [...(attachment.instance?.getDataRefs() ?? [])]\n .map(r => `'${r.id}'`)\n .join(', ');\n\n throw new Error(\n `extension '${attachment.spec.id}' could not be attached because its output data (${provided}) does not match what the input '${inputName}' requires (${expected})`,\n );\n }\n return value;\n });\n}\n\nfunction resolveInputDataContainer(\n extensionData: Array<AnyExtensionDataRef>,\n attachment: AppNode,\n inputName: string,\n): { node: AppNode } & ExtensionDataContainer<AnyExtensionDataRef> {\n const dataMap = new Map<string, unknown>();\n\n for (const ref of extensionData) {\n if (dataMap.has(ref.id)) {\n throw new Error(`Unexpected duplicate input data '${ref.id}'`);\n }\n const value = attachment.instance?.getData(ref);\n if (value === undefined && !ref.config.optional) {\n const expected = extensionData\n .filter(r => !r.config.optional)\n .map(r => `'${r.id}'`)\n .join(', ');\n\n const provided = [...(attachment.instance?.getDataRefs() ?? [])]\n .map(r => `'${r.id}'`)\n .join(', ');\n\n throw new Error(\n `extension '${attachment.spec.id}' could not be attached because its output data (${provided}) does not match what the input '${inputName}' requires (${expected})`,\n );\n }\n\n dataMap.set(ref.id, value);\n }\n\n return {\n node: attachment,\n get(ref) {\n return dataMap.get(ref.id);\n },\n *[Symbol.iterator]() {\n for (const [id, value] of dataMap) {\n // TODO: Would be better to be able to create a new instance using the ref here instead\n yield {\n $$type: '@backstage/ExtensionDataValue',\n id,\n value,\n };\n }\n },\n } as { node: AppNode } & ExtensionDataContainer<AnyExtensionDataRef>;\n}\n\nfunction reportUndeclaredAttachments(\n id: string,\n inputMap: { [name in string]: unknown },\n attachments: ReadonlyMap<string, AppNode[]>,\n) {\n const undeclaredAttachments = Array.from(attachments.entries()).filter(\n ([inputName]) => inputMap[inputName] === undefined,\n );\n\n const inputNames = Object.keys(inputMap);\n\n for (const [name, nodes] of undeclaredAttachments) {\n const pl = nodes.length > 1;\n // eslint-disable-next-line no-console\n console.warn(\n [\n `The extension${pl ? 's' : ''} '${nodes\n .map(n => n.spec.id)\n .join(\"', '\")}' ${pl ? 'are' : 'is'}`,\n `attached to the input '${name}' of the extension '${id}', but it`,\n inputNames.length === 0\n ? 'has no inputs'\n : `has no such input (candidates are '${inputNames.join(\"', '\")}')`,\n ].join(' '),\n );\n }\n}\n\nfunction resolveV1Inputs(\n inputMap: AnyExtensionInputMap,\n attachments: ReadonlyMap<string, AppNode[]>,\n): ResolvedExtensionInputs<AnyExtensionInputMap> {\n return mapValues(inputMap, (input, inputName) => {\n const attachedNodes = attachments.get(inputName) ?? [];\n\n if (input.config.singleton) {\n if (attachedNodes.length > 1) {\n const attachedNodeIds = attachedNodes.map(e => e.spec.id);\n throw Error(\n `expected ${\n input.config.optional ? 'at most' : 'exactly'\n } one '${inputName}' input but received multiple: '${attachedNodeIds.join(\n \"', '\",\n )}'`,\n );\n } else if (attachedNodes.length === 0) {\n if (input.config.optional) {\n return undefined;\n }\n throw Error(`input '${inputName}' is required but was not received`);\n }\n return {\n node: attachedNodes[0],\n output: resolveInputDataMap(\n input.extensionData,\n attachedNodes[0],\n inputName,\n ),\n };\n }\n\n return attachedNodes.map(attachment => ({\n node: attachment,\n output: resolveInputDataMap(input.extensionData, attachment, inputName),\n }));\n }) as ResolvedExtensionInputs<AnyExtensionInputMap>;\n}\n\nfunction resolveV2Inputs(\n inputMap: {\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n },\n attachments: ReadonlyMap<string, AppNode[]>,\n): ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n}> {\n return mapValues(inputMap, (input, inputName) => {\n const attachedNodes = attachments.get(inputName) ?? [];\n\n if (input.config.singleton) {\n if (attachedNodes.length > 1) {\n const attachedNodeIds = attachedNodes.map(e => e.spec.id);\n throw Error(\n `expected ${\n input.config.optional ? 'at most' : 'exactly'\n } one '${inputName}' input but received multiple: '${attachedNodeIds.join(\n \"', '\",\n )}'`,\n );\n } else if (attachedNodes.length === 0) {\n if (input.config.optional) {\n return undefined;\n }\n throw Error(`input '${inputName}' is required but was not received`);\n }\n return resolveInputDataContainer(\n input.extensionData,\n attachedNodes[0],\n inputName,\n );\n }\n\n return attachedNodes.map(attachment =>\n resolveInputDataContainer(input.extensionData, attachment, inputName),\n );\n }) as ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput<\n AnyExtensionDataRef,\n { optional: boolean; singleton: boolean }\n >;\n }>;\n}\n\n/** @internal */\nexport function createAppNodeInstance(options: {\n node: AppNode;\n attachments: ReadonlyMap<string, AppNode[]>;\n}): AppNodeInstance {\n const { node, attachments } = options;\n const { id, extension, config } = node.spec;\n const extensionData = new Map<string, unknown>();\n const extensionDataRefs = new Set<ExtensionDataRef<unknown>>();\n\n let parsedConfig: unknown;\n try {\n parsedConfig = extension.configSchema?.parse(config ?? {});\n } catch (e) {\n throw new Error(\n `Invalid configuration for extension '${id}'; caused by ${e}`,\n );\n }\n\n try {\n const internalExtension = toInternalExtension(extension);\n\n if (process.env.NODE_ENV !== 'production') {\n reportUndeclaredAttachments(id, internalExtension.inputs, attachments);\n }\n\n if (internalExtension.version === 'v1') {\n const namedOutputs = internalExtension.factory({\n node,\n config: parsedConfig,\n inputs: resolveV1Inputs(internalExtension.inputs, attachments),\n });\n\n for (const [name, output] of Object.entries(namedOutputs)) {\n const ref = internalExtension.output[name];\n if (!ref) {\n throw new Error(`unknown output provided via '${name}'`);\n }\n if (extensionData.has(ref.id)) {\n throw new Error(\n `duplicate extension data '${ref.id}' received via output '${name}'`,\n );\n }\n extensionData.set(ref.id, output);\n extensionDataRefs.add(ref);\n }\n } else if (internalExtension.version === 'v2') {\n const outputDataValues = internalExtension.factory({\n node,\n config: parsedConfig,\n inputs: resolveV2Inputs(internalExtension.inputs, attachments),\n });\n\n const outputDataMap = new Map<string, unknown>();\n for (const value of outputDataValues) {\n if (outputDataMap.has(value.id)) {\n throw new Error(`duplicate extension data output '${value.id}'`);\n }\n outputDataMap.set(value.id, value.value);\n }\n\n for (const ref of internalExtension.output) {\n const value = outputDataMap.get(ref.id);\n outputDataMap.delete(ref.id);\n if (value === undefined) {\n if (!ref.config.optional) {\n throw new Error(\n `missing required extension data output '${ref.id}'`,\n );\n }\n } else {\n extensionData.set(ref.id, value);\n extensionDataRefs.add(ref);\n }\n }\n\n if (outputDataMap.size > 0) {\n throw new Error(\n `unexpected output '${Array.from(outputDataMap.keys()).join(\n \"', '\",\n )}'`,\n );\n }\n } else {\n throw new Error(\n `unexpected extension version '${(internalExtension as any).version}'`,\n );\n }\n } catch (e) {\n throw new Error(\n `Failed to instantiate extension '${id}'${\n e.name === 'Error' ? `, ${e.message}` : `; caused by ${e.stack}`\n }`,\n );\n }\n\n return {\n getDataRefs() {\n return extensionDataRefs.values();\n },\n getData<T>(ref: ExtensionDataRef<T>): T | undefined {\n return extensionData.get(ref.id) as T | undefined;\n },\n };\n}\n\n/**\n * Starting at the provided node, instantiate all reachable nodes in the tree that have not been disabled.\n * @internal\n */\nexport function instantiateAppNodeTree(rootNode: AppNode): void {\n function createInstance(node: AppNode): AppNodeInstance | undefined {\n if (node.instance) {\n return node.instance;\n }\n if (node.spec.disabled) {\n return undefined;\n }\n\n const instantiatedAttachments = new Map<string, AppNode[]>();\n\n for (const [input, children] of node.edges.attachments) {\n const instantiatedChildren = children.flatMap(child => {\n const childInstance = createInstance(child);\n if (!childInstance) {\n return [];\n }\n return [child];\n });\n if (instantiatedChildren.length > 0) {\n instantiatedAttachments.set(input, instantiatedChildren);\n }\n }\n\n (node as Mutable<AppNode>).instance = createAppNodeInstance({\n node,\n attachments: instantiatedAttachments,\n });\n\n return node.instance;\n }\n\n createInstance(rootNode);\n}\n"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@backstage/frontend-app-api",
|
|
3
|
-
"version": "0.7.5-next.
|
|
3
|
+
"version": "0.7.5-next.3",
|
|
4
4
|
"backstage": {
|
|
5
5
|
"role": "web-library"
|
|
6
6
|
},
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"@backstage/core-components": "^0.14.10-next.0",
|
|
38
38
|
"@backstage/core-plugin-api": "^1.9.3",
|
|
39
39
|
"@backstage/errors": "^1.2.4",
|
|
40
|
-
"@backstage/frontend-plugin-api": "^0.
|
|
40
|
+
"@backstage/frontend-plugin-api": "^0.7.0-next.3",
|
|
41
41
|
"@backstage/theme": "^0.5.6",
|
|
42
42
|
"@backstage/types": "^1.1.1",
|
|
43
43
|
"@backstage/version-bridge": "^1.0.8",
|
|
@@ -47,8 +47,8 @@
|
|
|
47
47
|
"lodash": "^4.17.21"
|
|
48
48
|
},
|
|
49
49
|
"devDependencies": {
|
|
50
|
-
"@backstage/cli": "^0.27.0-next.
|
|
51
|
-
"@backstage/test-utils": "^1.5.10-next.
|
|
50
|
+
"@backstage/cli": "^0.27.0-next.4",
|
|
51
|
+
"@backstage/test-utils": "^1.5.10-next.2",
|
|
52
52
|
"@testing-library/jest-dom": "^6.0.0",
|
|
53
53
|
"@testing-library/react": "^15.0.0"
|
|
54
54
|
},
|