@backstage/frontend-app-api 0.7.4 → 0.7.5-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,15 +1,37 @@
1
1
  # @backstage/frontend-app-api
2
2
 
3
- ## 0.7.4
3
+ ## 0.7.5-next.1
4
4
 
5
5
  ### Patch Changes
6
6
 
7
+ - 3be9aeb: Added support for v2 extensions, which declare their inputs and outputs without using a data map.
8
+ - 6349099: Added config input type to the extensions
7
9
  - Updated dependencies
8
- - @backstage/core-app-api@1.14.1
9
- - @backstage/core-components@0.14.9
10
+ - @backstage/frontend-plugin-api@0.6.8-next.1
11
+ - @backstage/config@1.2.0
12
+ - @backstage/core-app-api@1.14.2-next.0
13
+ - @backstage/core-components@0.14.10-next.0
10
14
  - @backstage/core-plugin-api@1.9.3
11
- - @backstage/frontend-plugin-api@0.6.7
15
+ - @backstage/errors@1.2.4
16
+ - @backstage/theme@0.5.6
17
+ - @backstage/types@1.1.1
18
+ - @backstage/version-bridge@1.0.8
19
+
20
+ ## 0.7.4-next.0
21
+
22
+ ### Patch Changes
23
+
24
+ - 7777b5f: Support icon overriding with the new `IconBundleBlueprint` API.
25
+ - Updated dependencies
26
+ - @backstage/frontend-plugin-api@0.6.8-next.0
27
+ - @backstage/core-components@0.14.10-next.0
28
+ - @backstage/core-app-api@1.14.1-next.0
12
29
  - @backstage/config@1.2.0
30
+ - @backstage/core-plugin-api@1.9.3
31
+ - @backstage/errors@1.2.4
32
+ - @backstage/theme@0.5.6
33
+ - @backstage/types@1.1.1
34
+ - @backstage/version-bridge@1.0.8
13
35
 
14
36
  ## 0.7.3
15
37
 
@@ -1,5 +1,5 @@
1
1
  import React from 'react';
2
- import { createExtension, createExtensionInput, createApiExtension, createThemeExtension, createComponentExtension, createTranslationExtension, coreExtensionData, ExtensionBoundary } from '@backstage/frontend-plugin-api';
2
+ import { createExtension, createExtensionInput, createApiExtension, createThemeExtension, createComponentExtension, createTranslationExtension, IconBundleBlueprint, coreExtensionData, ExtensionBoundary } from '@backstage/frontend-plugin-api';
3
3
 
4
4
  const App = createExtension({
5
5
  namespace: "app",
@@ -18,6 +18,9 @@ const App = createExtension({
18
18
  translations: createExtensionInput({
19
19
  translation: createTranslationExtension.translationDataRef
20
20
  }),
21
+ icons: createExtensionInput({
22
+ icon: IconBundleBlueprint.dataRefs.icons
23
+ }),
21
24
  root: createExtensionInput(
22
25
  {
23
26
  element: coreExtensionData.reactElement
@@ -1 +1 @@
1
- {"version":3,"file":"App.esm.js","sources":["../../src/extensions/App.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 ExtensionBoundary,\n coreExtensionData,\n createApiExtension,\n createComponentExtension,\n createExtension,\n createExtensionInput,\n createThemeExtension,\n createTranslationExtension,\n} from '@backstage/frontend-plugin-api';\n\nexport const App = createExtension({\n namespace: 'app',\n attachTo: { id: 'root', input: 'default' }, // ignored\n inputs: {\n apis: createExtensionInput({\n api: createApiExtension.factoryDataRef,\n }),\n themes: createExtensionInput({\n theme: createThemeExtension.themeDataRef,\n }),\n components: createExtensionInput({\n component: createComponentExtension.componentDataRef,\n }),\n translations: createExtensionInput({\n translation: createTranslationExtension.translationDataRef,\n }),\n root: createExtensionInput(\n {\n element: coreExtensionData.reactElement,\n },\n { singleton: true },\n ),\n },\n output: {\n root: coreExtensionData.reactElement,\n },\n factory({ node, inputs }) {\n return {\n root: (\n <ExtensionBoundary node={node}>\n {inputs.root.output.element}\n </ExtensionBoundary>\n ),\n };\n },\n});\n"],"names":[],"mappings":";;;AA4BO,MAAM,MAAM,eAAgB,CAAA;AAAA,EACjC,SAAW,EAAA,KAAA;AAAA,EACX,QAAU,EAAA,EAAE,EAAI,EAAA,MAAA,EAAQ,OAAO,SAAU,EAAA;AAAA;AAAA,EACzC,MAAQ,EAAA;AAAA,IACN,MAAM,oBAAqB,CAAA;AAAA,MACzB,KAAK,kBAAmB,CAAA,cAAA;AAAA,KACzB,CAAA;AAAA,IACD,QAAQ,oBAAqB,CAAA;AAAA,MAC3B,OAAO,oBAAqB,CAAA,YAAA;AAAA,KAC7B,CAAA;AAAA,IACD,YAAY,oBAAqB,CAAA;AAAA,MAC/B,WAAW,wBAAyB,CAAA,gBAAA;AAAA,KACrC,CAAA;AAAA,IACD,cAAc,oBAAqB,CAAA;AAAA,MACjC,aAAa,0BAA2B,CAAA,kBAAA;AAAA,KACzC,CAAA;AAAA,IACD,IAAM,EAAA,oBAAA;AAAA,MACJ;AAAA,QACE,SAAS,iBAAkB,CAAA,YAAA;AAAA,OAC7B;AAAA,MACA,EAAE,WAAW,IAAK,EAAA;AAAA,KACpB;AAAA,GACF;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,MAAM,iBAAkB,CAAA,YAAA;AAAA,GAC1B;AAAA,EACA,OAAQ,CAAA,EAAE,IAAM,EAAA,MAAA,EAAU,EAAA;AACxB,IAAO,OAAA;AAAA,MACL,sBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,QAChB,MAAO,CAAA,IAAA,CAAK,OAAO,OACtB,CAAA;AAAA,KAEJ,CAAA;AAAA,GACF;AACF,CAAC;;;;"}
1
+ {"version":3,"file":"App.esm.js","sources":["../../src/extensions/App.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 ExtensionBoundary,\n coreExtensionData,\n createApiExtension,\n createComponentExtension,\n createExtension,\n createExtensionInput,\n createThemeExtension,\n createTranslationExtension,\n IconBundleBlueprint,\n} from '@backstage/frontend-plugin-api';\n\nexport const App = createExtension({\n namespace: 'app',\n attachTo: { id: 'root', input: 'default' }, // ignored\n inputs: {\n apis: createExtensionInput({\n api: createApiExtension.factoryDataRef,\n }),\n themes: createExtensionInput({\n theme: createThemeExtension.themeDataRef,\n }),\n components: createExtensionInput({\n component: createComponentExtension.componentDataRef,\n }),\n translations: createExtensionInput({\n translation: createTranslationExtension.translationDataRef,\n }),\n icons: createExtensionInput({\n icon: IconBundleBlueprint.dataRefs.icons,\n }),\n root: createExtensionInput(\n {\n element: coreExtensionData.reactElement,\n },\n { singleton: true },\n ),\n },\n output: {\n root: coreExtensionData.reactElement,\n },\n factory({ node, inputs }) {\n return {\n root: (\n <ExtensionBoundary node={node}>\n {inputs.root.output.element}\n </ExtensionBoundary>\n ),\n };\n },\n});\n"],"names":[],"mappings":";;;AA6BO,MAAM,MAAM,eAAgB,CAAA;AAAA,EACjC,SAAW,EAAA,KAAA;AAAA,EACX,QAAU,EAAA,EAAE,EAAI,EAAA,MAAA,EAAQ,OAAO,SAAU,EAAA;AAAA;AAAA,EACzC,MAAQ,EAAA;AAAA,IACN,MAAM,oBAAqB,CAAA;AAAA,MACzB,KAAK,kBAAmB,CAAA,cAAA;AAAA,KACzB,CAAA;AAAA,IACD,QAAQ,oBAAqB,CAAA;AAAA,MAC3B,OAAO,oBAAqB,CAAA,YAAA;AAAA,KAC7B,CAAA;AAAA,IACD,YAAY,oBAAqB,CAAA;AAAA,MAC/B,WAAW,wBAAyB,CAAA,gBAAA;AAAA,KACrC,CAAA;AAAA,IACD,cAAc,oBAAqB,CAAA;AAAA,MACjC,aAAa,0BAA2B,CAAA,kBAAA;AAAA,KACzC,CAAA;AAAA,IACD,OAAO,oBAAqB,CAAA;AAAA,MAC1B,IAAA,EAAM,oBAAoB,QAAS,CAAA,KAAA;AAAA,KACpC,CAAA;AAAA,IACD,IAAM,EAAA,oBAAA;AAAA,MACJ;AAAA,QACE,SAAS,iBAAkB,CAAA,YAAA;AAAA,OAC7B;AAAA,MACA,EAAE,WAAW,IAAK,EAAA;AAAA,KACpB;AAAA,GACF;AAAA,EACA,MAAQ,EAAA;AAAA,IACN,MAAM,iBAAkB,CAAA,YAAA;AAAA,GAC1B;AAAA,EACA,OAAQ,CAAA,EAAE,IAAM,EAAA,MAAA,EAAU,EAAA;AACxB,IAAO,OAAA;AAAA,MACL,sBACG,KAAA,CAAA,aAAA,CAAA,iBAAA,EAAA,EAAkB,QAChB,MAAO,CAAA,IAAA,CAAK,OAAO,OACtB,CAAA;AAAA,KAEJ,CAAA;AAAA,GACF;AACF,CAAC;;;;"}
@@ -1,3 +1,6 @@
1
+ import 'zod';
2
+ import 'zod-to-json-schema';
3
+
1
4
  function toInternalExtensionDefinition(overrides) {
2
5
  const internal = overrides;
3
6
  if (internal.$$type !== "@backstage/ExtensionDefinition") {
@@ -5,9 +8,10 @@ function toInternalExtensionDefinition(overrides) {
5
8
  `Invalid extension definition instance, bad type '${internal.$$type}'`
6
9
  );
7
10
  }
8
- if (internal.version !== "v1") {
11
+ const version = internal.version;
12
+ if (version !== "v1" && version !== "v2") {
9
13
  throw new Error(
10
- `Invalid extension definition instance, bad version '${internal.version}'`
14
+ `Invalid extension definition instance, bad version '${version}'`
11
15
  );
12
16
  }
13
17
  return internal;
@@ -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 } from '../schema';\nimport { Expand } from '../types';\nimport { ExtensionDataRef } from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\n\n/** @public */\nexport type AnyExtensionDataMap = {\n [name in string]: ExtensionDataRef<unknown, { optional?: true }>;\n};\n\n/** @public */\nexport type AnyExtensionInputMap = {\n [inputName in string]: ExtensionInput<\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 */\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<TExtensionData extends AnyExtensionDataMap> =\n {\n node: AppNode;\n output: ExtensionDataValues<TExtensionData>;\n };\n\n/**\n * Converts an extension input map into a matching collection of resolved inputs.\n * @public\n */\nexport type ResolvedExtensionInputs<\n TInputs extends { [name in string]: ExtensionInput<any, any> },\n> = {\n [InputName in keyof TInputs]: false extends TInputs[InputName]['config']['singleton']\n ? Array<Expand<ResolvedExtensionInput<TInputs[InputName]['extensionData']>>>\n : false extends TInputs[InputName]['config']['optional']\n ? Expand<ResolvedExtensionInput<TInputs[InputName]['extensionData']>>\n : Expand<\n ResolvedExtensionInput<TInputs[InputName]['extensionData']> | undefined\n >;\n};\n\n/** @public */\nexport interface CreateExtensionOptions<\n TOutput extends AnyExtensionDataMap,\n TInputs extends AnyExtensionInputMap,\n TConfig,\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>;\n factory(options: {\n node: AppNode;\n config: TConfig;\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Expand<ExtensionDataValues<TOutput>>;\n}\n\n/** @public */\nexport interface ExtensionDefinition<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>;\n}\n\n/** @internal */\nexport interface InternalExtensionDefinition<TConfig>\n extends ExtensionDefinition<TConfig> {\n readonly version: 'v1';\n readonly inputs: AnyExtensionInputMap;\n readonly output: AnyExtensionDataMap;\n factory(options: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<any>;\n }): ExtensionDataValues<any>;\n}\n\n/** @internal */\nexport function toInternalExtensionDefinition<TConfig>(\n overrides: ExtensionDefinition<TConfig>,\n): InternalExtensionDefinition<TConfig> {\n const internal = overrides as InternalExtensionDefinition<TConfig>;\n if (internal.$$type !== '@backstage/ExtensionDefinition') {\n throw new Error(\n `Invalid extension definition instance, bad type '${internal.$$type}'`,\n );\n }\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid extension definition instance, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n\n/** @public */\nexport function createExtension<\n TOutput extends AnyExtensionDataMap,\n TInputs extends AnyExtensionInputMap,\n TConfig = never,\n>(\n options: CreateExtensionOptions<TOutput, TInputs, TConfig>,\n): ExtensionDefinition<TConfig> {\n return {\n $$type: '@backstage/ExtensionDefinition',\n version: '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: options.configSchema,\n factory({ inputs, ...rest }) {\n // TODO: Simplify this, but TS wouldn't infer the input type for some reason\n return options.factory({\n inputs: inputs as Expand<ResolvedExtensionInputs<TInputs>>,\n ...rest,\n });\n },\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<TConfig>;\n}\n"],"names":[],"mappings":"AA6HO,SAAS,8BACd,SACsC,EAAA;AACtC,EAAA,MAAM,QAAW,GAAA,SAAA,CAAA;AACjB,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,EAAI,IAAA,QAAA,CAAS,YAAY,IAAM,EAAA;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,oDAAA,EAAuD,SAAS,OAAO,CAAA,CAAA,CAAA;AAAA,KACzE,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 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,3 +1,6 @@
1
+ import 'zod';
2
+ import 'zod-to-json-schema';
3
+
1
4
  function toInternalExtensionOverrides(overrides) {
2
5
  const internal = overrides;
3
6
  if (internal.$$type !== "@backstage/ExtensionOverrides") {
@@ -1 +1 @@
1
- {"version":3,"file":"createExtensionOverrides.esm.js","sources":["../../../../../frontend-plugin-api/src/wiring/createExtensionOverrides.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 { ExtensionOverrides, FeatureFlagConfig } from './types';\n\n/** @public */\nexport interface ExtensionOverridesOptions {\n extensions: ExtensionDefinition<unknown>[];\n featureFlags?: FeatureFlagConfig[];\n}\n\n/** @internal */\nexport interface InternalExtensionOverrides extends ExtensionOverrides {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n}\n\n/** @public */\nexport function createExtensionOverrides(\n options: ExtensionOverridesOptions,\n): ExtensionOverrides {\n const extensions = options.extensions.map(def =>\n resolveExtensionDefinition(def),\n );\n const featureFlags = options.featureFlags ?? [];\n return {\n $$type: '@backstage/ExtensionOverrides',\n version: 'v1',\n extensions,\n featureFlags,\n toString() {\n const ex = extensions.map(String).join(',');\n const ff = featureFlags.map(f => f.name).join(',');\n return `ExtensionOverrides{extensions=[${ex}],featureFlags=[${ff}]}`;\n },\n } as InternalExtensionOverrides;\n}\n\n/** @internal */\nexport function toInternalExtensionOverrides(\n overrides: ExtensionOverrides,\n): InternalExtensionOverrides {\n const internal = overrides as InternalExtensionOverrides;\n if (internal.$$type !== '@backstage/ExtensionOverrides') {\n throw new Error(\n `Invalid extension overrides instance, bad type '${internal.$$type}'`,\n );\n }\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid extension overrides instance, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n"],"names":[],"mappings":"AA0DO,SAAS,6BACd,SAC4B,EAAA;AAC5B,EAAA,MAAM,QAAW,GAAA,SAAA,CAAA;AACjB,EAAI,IAAA,QAAA,CAAS,WAAW,+BAAiC,EAAA;AACvD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,gDAAA,EAAmD,SAAS,MAAM,CAAA,CAAA,CAAA;AAAA,KACpE,CAAA;AAAA,GACF;AACA,EAAI,IAAA,QAAA,CAAS,YAAY,IAAM,EAAA;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,mDAAA,EAAsD,SAAS,OAAO,CAAA,CAAA,CAAA;AAAA,KACxE,CAAA;AAAA,GACF;AACA,EAAO,OAAA,QAAA,CAAA;AACT;;;;"}
1
+ {"version":3,"file":"createExtensionOverrides.esm.js","sources":["../../../../../frontend-plugin-api/src/wiring/createExtensionOverrides.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 { ExtensionOverrides, FeatureFlagConfig } from './types';\n\n/** @public */\nexport interface ExtensionOverridesOptions {\n extensions: ExtensionDefinition<any, any>[];\n featureFlags?: FeatureFlagConfig[];\n}\n\n/** @internal */\nexport interface InternalExtensionOverrides extends ExtensionOverrides {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n}\n\n/** @public */\nexport function createExtensionOverrides(\n options: ExtensionOverridesOptions,\n): ExtensionOverrides {\n const extensions = options.extensions.map(def =>\n resolveExtensionDefinition(def),\n );\n const featureFlags = options.featureFlags ?? [];\n return {\n $$type: '@backstage/ExtensionOverrides',\n version: 'v1',\n extensions,\n featureFlags,\n toString() {\n const ex = extensions.map(String).join(',');\n const ff = featureFlags.map(f => f.name).join(',');\n return `ExtensionOverrides{extensions=[${ex}],featureFlags=[${ff}]}`;\n },\n } as InternalExtensionOverrides;\n}\n\n/** @internal */\nexport function toInternalExtensionOverrides(\n overrides: ExtensionOverrides,\n): InternalExtensionOverrides {\n const internal = overrides as InternalExtensionOverrides;\n if (internal.$$type !== '@backstage/ExtensionOverrides') {\n throw new Error(\n `Invalid extension overrides instance, bad type '${internal.$$type}'`,\n );\n }\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid extension overrides instance, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n"],"names":[],"mappings":";;;AA0DO,SAAS,6BACd,SAC4B,EAAA;AAC5B,EAAA,MAAM,QAAW,GAAA,SAAA,CAAA;AACjB,EAAI,IAAA,QAAA,CAAS,WAAW,+BAAiC,EAAA;AACvD,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,gDAAA,EAAmD,SAAS,MAAM,CAAA,CAAA,CAAA;AAAA,KACpE,CAAA;AAAA,GACF;AACA,EAAI,IAAA,QAAA,CAAS,YAAY,IAAM,EAAA;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,mDAAA,EAAsD,SAAS,OAAO,CAAA,CAAA,CAAA;AAAA,KACxE,CAAA;AAAA,GACF;AACA,EAAO,OAAA,QAAA,CAAA;AACT;;;;"}
@@ -1,3 +1,6 @@
1
+ import 'zod';
2
+ import 'zod-to-json-schema';
3
+
1
4
  function toInternalBackstagePlugin(plugin) {
2
5
  const internal = plugin;
3
6
  if (internal.$$type !== "@backstage/BackstagePlugin") {
@@ -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 Routes extends AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes,\n> {\n id: string;\n routes?: Routes;\n externalRoutes?: ExternalRoutes;\n extensions?: ExtensionDefinition<unknown>[];\n featureFlags?: FeatureFlagConfig[];\n}\n\n/** @public */\nexport interface InternalBackstagePlugin<\n Routes extends AnyRoutes = AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,\n> extends BackstagePlugin<Routes, ExternalRoutes> {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n}\n\n/** @public */\nexport function createPlugin<\n Routes extends AnyRoutes = {},\n ExternalRoutes extends AnyExternalRoutes = {},\n>(\n options: PluginOptions<Routes, ExternalRoutes>,\n): BackstagePlugin<Routes, ExternalRoutes> {\n const extensions = (options.extensions ?? []).map(def =>\n resolveExtensionDefinition(def, { namespace: options.id }),\n );\n\n const extensionIds = extensions.map(e => e.id);\n if (extensionIds.length !== new Set(extensionIds).size) {\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 Routes),\n externalRoutes: options.externalRoutes ?? ({} as ExternalRoutes),\n featureFlags: options.featureFlags ?? [],\n extensions,\n toString() {\n return `Plugin{id=${options.id}}`;\n },\n } as InternalBackstagePlugin<Routes, ExternalRoutes>;\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":"AA2FO,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;;;;"}
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 Routes extends AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes,\n> {\n id: string;\n routes?: Routes;\n externalRoutes?: ExternalRoutes;\n extensions?: ExtensionDefinition<any, any>[];\n featureFlags?: FeatureFlagConfig[];\n}\n\n/** @public */\nexport interface InternalBackstagePlugin<\n Routes extends AnyRoutes = AnyRoutes,\n ExternalRoutes extends AnyExternalRoutes = AnyExternalRoutes,\n> extends BackstagePlugin<Routes, ExternalRoutes> {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n}\n\n/** @public */\nexport function createPlugin<\n Routes extends AnyRoutes = {},\n ExternalRoutes extends AnyExternalRoutes = {},\n>(\n options: PluginOptions<Routes, ExternalRoutes>,\n): BackstagePlugin<Routes, ExternalRoutes> {\n const extensions = (options.extensions ?? []).map(def =>\n resolveExtensionDefinition(def, { namespace: options.id }),\n );\n\n const extensionIds = extensions.map(e => e.id);\n if (extensionIds.length !== new Set(extensionIds).size) {\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 Routes),\n externalRoutes: options.externalRoutes ?? ({} as ExternalRoutes),\n featureFlags: options.featureFlags ?? [],\n extensions,\n toString() {\n return `Plugin{id=${options.id}}`;\n },\n } as InternalBackstagePlugin<Routes, ExternalRoutes>;\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":";;;AA2FO,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;;;;"}
@@ -7,10 +7,9 @@ function toInternalExtension(overrides) {
7
7
  `Invalid extension instance, bad type '${internal.$$type}'`
8
8
  );
9
9
  }
10
- if (internal.version !== "v1") {
11
- throw new Error(
12
- `Invalid extension instance, bad version '${internal.version}'`
13
- );
10
+ const version = internal.version;
11
+ if (version !== "v1" && version !== "v2") {
12
+ throw new Error(`Invalid extension instance, bad version '${version}'`);
14
13
  }
15
14
  return internal;
16
15
  }
@@ -28,7 +27,7 @@ function resolveExtensionDefinition(definition, context) {
28
27
  return {
29
28
  ...rest,
30
29
  $$type: "@backstage/Extension",
31
- version: "v1",
30
+ version: internalDefinition.version,
32
31
  id,
33
32
  toString() {
34
33
  return `Extension{id=${id}}`;
@@ -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';\n\n/** @public */\nexport interface Extension<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>;\n}\n\n/** @internal */\nexport interface InternalExtension<TConfig> extends Extension<TConfig> {\n readonly version: 'v1';\n readonly inputs: AnyExtensionInputMap;\n readonly output: AnyExtensionDataMap;\n factory(options: {\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<any>;\n }): ExtensionDataValues<any>;\n}\n\n/** @internal */\nexport function toInternalExtension<TConfig>(\n overrides: Extension<TConfig>,\n): InternalExtension<TConfig> {\n const internal = overrides as InternalExtension<TConfig>;\n if (internal.$$type !== '@backstage/Extension') {\n throw new Error(\n `Invalid extension instance, bad type '${internal.$$type}'`,\n );\n }\n if (internal.version !== 'v1') {\n throw new Error(\n `Invalid extension instance, bad version '${internal.version}'`,\n );\n }\n return internal;\n}\n\n/** @internal */\nexport function resolveExtensionDefinition<TConfig>(\n definition: ExtensionDefinition<TConfig>,\n context?: { namespace?: string },\n): Extension<TConfig> {\n const internalDefinition = toInternalExtensionDefinition(definition);\n const { name, kind, namespace: _, ...rest } = 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: 'v1',\n id,\n toString() {\n return `Extension{id=${id}}`;\n },\n } as Extension<TConfig>;\n}\n"],"names":[],"mappings":";;AAiDO,SAAS,oBACd,SAC4B,EAAA;AAC5B,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,EAAI,IAAA,QAAA,CAAS,YAAY,IAAM,EAAA;AAC7B,IAAA,MAAM,IAAI,KAAA;AAAA,MACR,CAAA,yCAAA,EAA4C,SAAS,OAAO,CAAA,CAAA,CAAA;AAAA,KAC9D,CAAA;AAAA,GACF;AACA,EAAO,OAAA,QAAA,CAAA;AACT,CAAA;AAGgB,SAAA,0BAAA,CACd,YACA,OACoB,EAAA;AACpB,EAAM,MAAA,kBAAA,GAAqB,8BAA8B,UAAU,CAAA,CAAA;AACnE,EAAA,MAAM,EAAE,IAAM,EAAA,IAAA,EAAM,WAAW,CAAG,EAAA,GAAG,MAAS,GAAA,kBAAA,CAAA;AAC9C,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,OAAS,EAAA,IAAA;AAAA,IACT,EAAA;AAAA,IACA,QAAW,GAAA;AACT,MAAA,OAAO,gBAAgB,EAAE,CAAA,CAAA,CAAA,CAAA;AAAA,KAC3B;AAAA,GACF,CAAA;AACF;;;;"}
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 { name, kind, namespace: _, ...rest } = 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;AAGgB,SAAA,0BAAA,CACd,YACA,OACkC,EAAA;AAClC,EAAM,MAAA,kBAAA,GAAqB,8BAA8B,UAAU,CAAA,CAAA;AACnE,EAAA,MAAM,EAAE,IAAM,EAAA,IAAA,EAAM,WAAW,CAAG,EAAA,GAAG,MAAS,GAAA,kBAAA,CAAA;AAC9C,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
@@ -61,6 +61,7 @@ interface CreateAppFeatureLoader {
61
61
  }
62
62
  /** @public */
63
63
  declare function createApp(options?: {
64
+ /** @deprecated - Please use {@link @backstage/frontend-plugin-api#IconBundleBlueprint} to make new icon bundles which can be installed in the app seperately */
64
65
  icons?: {
65
66
  [key in string]: IconComponent;
66
67
  };
@@ -88,6 +89,7 @@ declare function createApp(options?: {
88
89
  * @public
89
90
  */
90
91
  declare function createSpecializedApp(options?: {
92
+ /** @deprecated - Please use {@link @backstage/frontend-plugin-api#IconBundleBlueprint} to make new icon bundles which can be installed in the app seperately */
91
93
  icons?: {
92
94
  [key in string]: IconComponent;
93
95
  };
@@ -1 +1 @@
1
- {"version":3,"file":"createAppTree.esm.js","sources":["../../src/tree/createAppTree.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 { Extension, FrontendFeature } from '@backstage/frontend-plugin-api';\nimport { readAppExtensionsConfig } from './readAppExtensionsConfig';\nimport { resolveAppTree } from './resolveAppTree';\nimport { resolveAppNodeSpecs } from './resolveAppNodeSpecs';\nimport { AppTree } from '@backstage/frontend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { instantiateAppNodeTree } from './instantiateAppNodeTree';\n\n/** @internal */\nexport interface CreateAppTreeOptions {\n features: FrontendFeature[];\n builtinExtensions: Extension<unknown>[];\n config: Config;\n}\n\n/** @internal */\nexport function createAppTree(options: CreateAppTreeOptions): AppTree {\n const tree = resolveAppTree(\n 'app',\n resolveAppNodeSpecs({\n features: options.features,\n builtinExtensions: options.builtinExtensions,\n parameters: readAppExtensionsConfig(options.config),\n forbidden: new Set(['app']),\n }),\n );\n instantiateAppNodeTree(tree.root);\n return tree;\n}\n"],"names":[],"mappings":";;;;;AAgCO,SAAS,cAAc,OAAwC,EAAA;AACpE,EAAA,MAAM,IAAO,GAAA,cAAA;AAAA,IACX,KAAA;AAAA,IACA,mBAAoB,CAAA;AAAA,MAClB,UAAU,OAAQ,CAAA,QAAA;AAAA,MAClB,mBAAmB,OAAQ,CAAA,iBAAA;AAAA,MAC3B,UAAA,EAAY,uBAAwB,CAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,MAClD,SAAW,kBAAA,IAAI,GAAI,CAAA,CAAC,KAAK,CAAC,CAAA;AAAA,KAC3B,CAAA;AAAA,GACH,CAAA;AACA,EAAA,sBAAA,CAAuB,KAAK,IAAI,CAAA,CAAA;AAChC,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
1
+ {"version":3,"file":"createAppTree.esm.js","sources":["../../src/tree/createAppTree.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 { Extension, FrontendFeature } from '@backstage/frontend-plugin-api';\nimport { readAppExtensionsConfig } from './readAppExtensionsConfig';\nimport { resolveAppTree } from './resolveAppTree';\nimport { resolveAppNodeSpecs } from './resolveAppNodeSpecs';\nimport { AppTree } from '@backstage/frontend-plugin-api';\nimport { Config } from '@backstage/config';\nimport { instantiateAppNodeTree } from './instantiateAppNodeTree';\n\n/** @internal */\nexport interface CreateAppTreeOptions {\n features: FrontendFeature[];\n builtinExtensions: Extension<any, any>[];\n config: Config;\n}\n\n/** @internal */\nexport function createAppTree(options: CreateAppTreeOptions): AppTree {\n const tree = resolveAppTree(\n 'app',\n resolveAppNodeSpecs({\n features: options.features,\n builtinExtensions: options.builtinExtensions,\n parameters: readAppExtensionsConfig(options.config),\n forbidden: new Set(['app']),\n }),\n );\n instantiateAppNodeTree(tree.root);\n return tree;\n}\n"],"names":[],"mappings":";;;;;AAgCO,SAAS,cAAc,OAAwC,EAAA;AACpE,EAAA,MAAM,IAAO,GAAA,cAAA;AAAA,IACX,KAAA;AAAA,IACA,mBAAoB,CAAA;AAAA,MAClB,UAAU,OAAQ,CAAA,QAAA;AAAA,MAClB,mBAAmB,OAAQ,CAAA,iBAAA;AAAA,MAC3B,UAAA,EAAY,uBAAwB,CAAA,OAAA,CAAQ,MAAM,CAAA;AAAA,MAClD,SAAW,kBAAA,IAAI,GAAI,CAAA,CAAC,KAAK,CAAC,CAAA;AAAA,KAC3B,CAAA;AAAA,GACH,CAAA;AACA,EAAA,sBAAA,CAAuB,KAAK,IAAI,CAAA,CAAA;AAChC,EAAO,OAAA,IAAA,CAAA;AACT;;;;"}
@@ -1,7 +1,7 @@
1
1
  import mapValues from 'lodash/mapValues';
2
2
  import { toInternalExtension } from '../frontend-plugin-api/src/wiring/resolveExtensionDefinition.esm.js';
3
3
 
4
- function resolveInputData(dataMap, attachment, inputName) {
4
+ function resolveInputDataMap(dataMap, attachment, inputName) {
5
5
  return mapValues(dataMap, (ref) => {
6
6
  const value = attachment.instance?.getData(ref);
7
7
  if (value === void 0 && !ref.config.optional) {
@@ -14,23 +14,46 @@ function resolveInputData(dataMap, attachment, inputName) {
14
14
  return value;
15
15
  });
16
16
  }
17
- function resolveInputs(id, inputMap, attachments) {
17
+ function resolveInputDataContainer(extensionData, attachment, inputName) {
18
+ const dataMap = /* @__PURE__ */ new Map();
19
+ for (const ref of extensionData) {
20
+ if (dataMap.has(ref.id)) {
21
+ throw new Error(`Unexpected duplicate input data '${ref.id}'`);
22
+ }
23
+ const value = attachment.instance?.getData(ref);
24
+ if (value === void 0 && !ref.config.optional) {
25
+ const expected = extensionData.filter((r) => !r.config.optional).map((r) => `'${r.id}'`).join(", ");
26
+ const provided = [...attachment.instance?.getDataRefs() ?? []].map((r) => `'${r.id}'`).join(", ");
27
+ throw new Error(
28
+ `extension '${attachment.spec.id}' could not be attached because its output data (${provided}) does not match what the input '${inputName}' requires (${expected})`
29
+ );
30
+ }
31
+ dataMap.set(ref.id, value);
32
+ }
33
+ return {
34
+ node: attachment,
35
+ get(ref) {
36
+ return dataMap.get(ref.id);
37
+ }
38
+ };
39
+ }
40
+ function reportUndeclaredAttachments(id, inputMap, attachments) {
18
41
  const undeclaredAttachments = Array.from(attachments.entries()).filter(
19
42
  ([inputName]) => inputMap[inputName] === void 0
20
43
  );
21
- if (process.env.NODE_ENV !== "production") {
22
- const inputNames = Object.keys(inputMap);
23
- for (const [name, nodes] of undeclaredAttachments) {
24
- const pl = nodes.length > 1;
25
- console.warn(
26
- [
27
- `The extension${pl ? "s" : ""} '${nodes.map((n) => n.spec.id).join("', '")}' ${pl ? "are" : "is"}`,
28
- `attached to the input '${name}' of the extension '${id}', but it`,
29
- inputNames.length === 0 ? "has no inputs" : `has no such input (candidates are '${inputNames.join("', '")}')`
30
- ].join(" ")
31
- );
32
- }
44
+ const inputNames = Object.keys(inputMap);
45
+ for (const [name, nodes] of undeclaredAttachments) {
46
+ const pl = nodes.length > 1;
47
+ console.warn(
48
+ [
49
+ `The extension${pl ? "s" : ""} '${nodes.map((n) => n.spec.id).join("', '")}' ${pl ? "are" : "is"}`,
50
+ `attached to the input '${name}' of the extension '${id}', but it`,
51
+ inputNames.length === 0 ? "has no inputs" : `has no such input (candidates are '${inputNames.join("', '")}')`
52
+ ].join(" ")
53
+ );
33
54
  }
55
+ }
56
+ function resolveV1Inputs(inputMap, attachments) {
34
57
  return mapValues(inputMap, (input, inputName) => {
35
58
  const attachedNodes = attachments.get(inputName) ?? [];
36
59
  if (input.config.singleton) {
@@ -49,7 +72,7 @@ function resolveInputs(id, inputMap, attachments) {
49
72
  }
50
73
  return {
51
74
  node: attachedNodes[0],
52
- output: resolveInputData(
75
+ output: resolveInputDataMap(
53
76
  input.extensionData,
54
77
  attachedNodes[0],
55
78
  inputName
@@ -58,10 +81,38 @@ function resolveInputs(id, inputMap, attachments) {
58
81
  }
59
82
  return attachedNodes.map((attachment) => ({
60
83
  node: attachment,
61
- output: resolveInputData(input.extensionData, attachment, inputName)
84
+ output: resolveInputDataMap(input.extensionData, attachment, inputName)
62
85
  }));
63
86
  });
64
87
  }
88
+ function resolveV2Inputs(inputMap, attachments) {
89
+ return mapValues(inputMap, (input, inputName) => {
90
+ const attachedNodes = attachments.get(inputName) ?? [];
91
+ if (input.config.singleton) {
92
+ if (attachedNodes.length > 1) {
93
+ const attachedNodeIds = attachedNodes.map((e) => e.spec.id);
94
+ throw Error(
95
+ `expected ${input.config.optional ? "at most" : "exactly"} one '${inputName}' input but received multiple: '${attachedNodeIds.join(
96
+ "', '"
97
+ )}'`
98
+ );
99
+ } else if (attachedNodes.length === 0) {
100
+ if (input.config.optional) {
101
+ return void 0;
102
+ }
103
+ throw Error(`input '${inputName}' is required but was not received`);
104
+ }
105
+ return resolveInputDataContainer(
106
+ input.extensionData,
107
+ attachedNodes[0],
108
+ inputName
109
+ );
110
+ }
111
+ return attachedNodes.map(
112
+ (attachment) => resolveInputDataContainer(input.extensionData, attachment, inputName)
113
+ );
114
+ });
115
+ }
65
116
  function createAppNodeInstance(options) {
66
117
  const { node, attachments } = options;
67
118
  const { id, extension, config } = node.spec;
@@ -77,23 +128,66 @@ function createAppNodeInstance(options) {
77
128
  }
78
129
  try {
79
130
  const internalExtension = toInternalExtension(extension);
80
- const namedOutputs = internalExtension.factory({
81
- node,
82
- config: parsedConfig,
83
- inputs: resolveInputs(id, internalExtension.inputs, attachments)
84
- });
85
- for (const [name, output] of Object.entries(namedOutputs)) {
86
- const ref = internalExtension.output[name];
87
- if (!ref) {
88
- throw new Error(`unknown output provided via '${name}'`);
131
+ if (process.env.NODE_ENV !== "production") {
132
+ reportUndeclaredAttachments(id, internalExtension.inputs, attachments);
133
+ }
134
+ if (internalExtension.version === "v1") {
135
+ const namedOutputs = internalExtension.factory({
136
+ node,
137
+ config: parsedConfig,
138
+ inputs: resolveV1Inputs(internalExtension.inputs, attachments)
139
+ });
140
+ for (const [name, output] of Object.entries(namedOutputs)) {
141
+ const ref = internalExtension.output[name];
142
+ if (!ref) {
143
+ throw new Error(`unknown output provided via '${name}'`);
144
+ }
145
+ if (extensionData.has(ref.id)) {
146
+ throw new Error(
147
+ `duplicate extension data '${ref.id}' received via output '${name}'`
148
+ );
149
+ }
150
+ extensionData.set(ref.id, output);
151
+ extensionDataRefs.add(ref);
152
+ }
153
+ } else if (internalExtension.version === "v2") {
154
+ const outputDataValues = internalExtension.factory({
155
+ node,
156
+ config: parsedConfig,
157
+ inputs: resolveV2Inputs(internalExtension.inputs, attachments)
158
+ });
159
+ const outputDataMap = /* @__PURE__ */ new Map();
160
+ for (const value of outputDataValues) {
161
+ if (outputDataMap.has(value.id)) {
162
+ throw new Error(`duplicate extension data output '${value.id}'`);
163
+ }
164
+ outputDataMap.set(value.id, value.value);
89
165
  }
90
- if (extensionData.has(ref.id)) {
166
+ for (const ref of internalExtension.output) {
167
+ const value = outputDataMap.get(ref.id);
168
+ outputDataMap.delete(ref.id);
169
+ if (value === void 0) {
170
+ if (!ref.config.optional) {
171
+ throw new Error(
172
+ `missing required extension data output '${ref.id}'`
173
+ );
174
+ }
175
+ } else {
176
+ extensionData.set(ref.id, value);
177
+ extensionDataRefs.add(ref);
178
+ }
179
+ }
180
+ if (outputDataMap.size > 0) {
91
181
  throw new Error(
92
- `duplicate extension data '${ref.id}' received via output '${name}'`
182
+ `unexpected output '${Array.from(outputDataMap.keys()).join(
183
+ "', '"
184
+ )}'`
93
185
  );
94
186
  }
95
- extensionData.set(ref.id, output);
96
- extensionDataRefs.add(ref);
187
+ } else {
188
+ throw new Error(
189
+ `unexpected extension version '${internalExtension.version}'`
190
+ );
97
191
  }
98
192
  } catch (e) {
99
193
  throw new Error(
@@ -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 AnyExtensionInputMap,\n ExtensionDataRef,\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 resolveInputData(\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 resolveInputs(\n id: string,\n inputMap: AnyExtensionInputMap,\n attachments: ReadonlyMap<string, AppNode[]>,\n): ResolvedExtensionInputs<AnyExtensionInputMap> {\n const undeclaredAttachments = Array.from(attachments.entries()).filter(\n ([inputName]) => inputMap[inputName] === undefined,\n );\n\n if (process.env.NODE_ENV !== 'production') {\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\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: resolveInputData(\n input.extensionData,\n attachedNodes[0],\n inputName,\n ),\n };\n }\n\n return attachedNodes.map(attachment => ({\n node: attachment,\n output: resolveInputData(input.extensionData, attachment, inputName),\n }));\n }) as ResolvedExtensionInputs<AnyExtensionInputMap>;\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 const namedOutputs = internalExtension.factory({\n node,\n config: parsedConfig,\n inputs: resolveInputs(id, 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 } 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 } 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,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { ConfigReader } from '@backstage/config';
3
- import { createApiExtension, coreExtensionData, createThemeExtension, createTranslationExtension, appTreeApiRef, routeResolutionApiRef, componentsApiRef, iconsApiRef } from '@backstage/frontend-plugin-api';
3
+ import { createApiExtension, coreExtensionData, createThemeExtension, createTranslationExtension, IconBundleBlueprint, appTreeApiRef, routeResolutionApiRef, componentsApiRef, iconsApiRef } from '@backstage/frontend-plugin-api';
4
4
  import { App } from '../extensions/App.esm.js';
5
5
  import { AppRoutes } from '../extensions/AppRoutes.esm.js';
6
6
  import { AppLayout } from '../extensions/AppLayout.esm.js';
@@ -202,6 +202,7 @@ function createApiHolder(tree, configApi, appIdentityProxy, routeResolutionApi,
202
202
  ).filter(
203
203
  (x) => !!x
204
204
  ) ?? [];
205
+ const extensionIcons = tree.root.edges.attachments.get("icons")?.map((e) => e.instance?.getData(IconBundleBlueprint.dataRefs.icons)).reduce((acc, bundle) => ({ ...acc, ...bundle }), {});
205
206
  for (const factory of pluginApis) {
206
207
  factoryRegistry.register("default", factory);
207
208
  }
@@ -235,7 +236,7 @@ function createApiHolder(tree, configApi, appIdentityProxy, routeResolutionApi,
235
236
  factoryRegistry.register("static", {
236
237
  api: iconsApiRef,
237
238
  deps: {},
238
- factory: () => new DefaultIconsApi({ ...icons, ...icons$1 })
239
+ factory: () => new DefaultIconsApi({ ...icons, ...extensionIcons, ...icons$1 })
239
240
  });
240
241
  factoryRegistry.register("static", {
241
242
  api: appThemeApiRef,
@@ -1 +1 @@
1
- {"version":3,"file":"createApp.esm.js","sources":["../../src/wiring/createApp.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, { JSX, ReactNode } from 'react';\nimport { ConfigReader } from '@backstage/config';\nimport {\n AppTree,\n appTreeApiRef,\n componentsApiRef,\n coreExtensionData,\n createApiExtension,\n createThemeExtension,\n createTranslationExtension,\n FrontendFeature,\n iconsApiRef,\n RouteResolutionApi,\n routeResolutionApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { App } from '../extensions/App';\nimport { AppRoutes } from '../extensions/AppRoutes';\nimport { AppLayout } from '../extensions/AppLayout';\nimport { AppNav } from '../extensions/AppNav';\nimport {\n AnyApiFactory,\n ApiHolder,\n appThemeApiRef,\n ConfigApi,\n configApiRef,\n IconComponent,\n featureFlagsApiRef,\n identityApiRef,\n AppTheme,\n errorApiRef,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\nimport { getAvailableFeatures } from './discovery';\nimport {\n ApiFactoryRegistry,\n ApiProvider,\n ApiResolver,\n AppThemeSelector,\n} from '@backstage/core-app-api';\n\n// TODO: Get rid of all of these\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { isProtectedApp } from '../../../core-app-api/src/app/isProtectedApp';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppThemeProvider } from '../../../core-app-api/src/app/AppThemeProvider';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { LocalStorageFeatureFlags } from '../../../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { defaultConfigLoaderSync } from '../../../core-app-api/src/app/defaultConfigLoader';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { overrideBaseUrlConfigs } from '../../../core-app-api/src/app/overrideBaseUrlConfigs';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppLanguageSelector } from '../../../core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { I18nextTranslationApi } from '../../../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { apis as defaultApis } from '../../../app-defaults/src/defaults';\nimport { DarkTheme, LightTheme } from '../extensions/themes';\nimport {\n oauthRequestDialogAppRootElement,\n alertDisplayAppRootElement,\n} from '../extensions/elements';\nimport { extractRouteInfoFromAppNode } from '../routing/extractRouteInfoFromAppNode';\nimport {\n appLanguageApiRef,\n translationApiRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { CreateAppRouteBinder } from '../routing';\nimport { RouteResolver } from '../routing/RouteResolver';\nimport { resolveRouteBindings } from '../routing/resolveRouteBindings';\nimport { collectRouteIds } from '../routing/collectRouteIds';\nimport { createAppTree } from '../tree';\nimport {\n DefaultProgressComponent,\n DefaultErrorBoundaryComponent,\n DefaultNotFoundErrorPageComponent,\n} from '../extensions/components';\nimport { InternalAppContext } from './InternalAppContext';\nimport { AppRoot } from '../extensions/AppRoot';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalBackstagePlugin } from '../../../frontend-plugin-api/src/wiring/createPlugin';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides';\nimport { DefaultComponentsApi } from '../apis/implementations/ComponentsApi';\nimport { DefaultIconsApi } from '../apis/implementations/IconsApi';\nimport { stringifyError } from '@backstage/errors';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { icons as defaultIcons } from '../../../app-defaults/src/defaults';\nimport { getBasePath } from '../routing/getBasePath';\n\nconst DefaultApis = defaultApis.map(factory => createApiExtension({ factory }));\n\nexport const builtinExtensions = [\n App,\n AppRoot,\n AppRoutes,\n AppNav,\n AppLayout,\n DefaultProgressComponent,\n DefaultErrorBoundaryComponent,\n DefaultNotFoundErrorPageComponent,\n LightTheme,\n DarkTheme,\n oauthRequestDialogAppRootElement,\n alertDisplayAppRootElement,\n ...DefaultApis,\n].map(def => resolveExtensionDefinition(def));\n\nfunction deduplicateFeatures(\n allFeatures: FrontendFeature[],\n): FrontendFeature[] {\n // Start by removing duplicates by reference\n const features = Array.from(new Set(allFeatures));\n\n // Plugins are deduplicated by ID, last one wins\n const seenIds = new Set<string>();\n return features\n .reverse()\n .filter(feature => {\n if (feature.$$type !== '@backstage/BackstagePlugin') {\n return true;\n }\n if (seenIds.has(feature.id)) {\n return false;\n }\n seenIds.add(feature.id);\n return true;\n })\n .reverse();\n}\n\n/**\n * A source of dynamically loaded frontend features.\n *\n * @public\n */\nexport interface CreateAppFeatureLoader {\n /**\n * Returns name of this loader. suitable for showing to users.\n */\n getLoaderName(): string;\n\n /**\n * Loads a number of features dynamically.\n */\n load(options: { config: ConfigApi }): Promise<{\n features: FrontendFeature[];\n }>;\n}\n\n/** @public */\nexport function createApp(options?: {\n icons?: { [key in string]: IconComponent };\n features?: (FrontendFeature | CreateAppFeatureLoader)[];\n configLoader?: () => Promise<{ config: ConfigApi }>;\n bindRoutes?(context: { bind: CreateAppRouteBinder }): void;\n /**\n * The component to render while loading the app (waiting for config, features, etc)\n *\n * Is the text \"Loading...\" by default.\n * If set to \"null\" then no loading fallback component is rendered. *\n */\n loadingComponent?: ReactNode;\n}): {\n createRoot(): JSX.Element;\n} {\n let suspenseFallback = options?.loadingComponent;\n if (suspenseFallback === undefined) {\n suspenseFallback = 'Loading...';\n }\n\n async function appLoader() {\n const config =\n (await options?.configLoader?.().then(c => c.config)) ??\n ConfigReader.fromConfigs(\n overrideBaseUrlConfigs(defaultConfigLoaderSync()),\n );\n\n const discoveredFeatures = getAvailableFeatures(config);\n\n const providedFeatures: FrontendFeature[] = [];\n for (const entry of options?.features ?? []) {\n if ('load' in entry) {\n try {\n const result = await entry.load({ config });\n providedFeatures.push(...result.features);\n } catch (e) {\n throw new Error(\n `Failed to read frontend features from loader '${entry.getLoaderName()}', ${stringifyError(\n e,\n )}`,\n );\n }\n } else {\n providedFeatures.push(entry);\n }\n }\n\n const app = createSpecializedApp({\n icons: options?.icons,\n config,\n features: [...discoveredFeatures, ...providedFeatures],\n bindRoutes: options?.bindRoutes,\n }).createRoot();\n\n return { default: () => app };\n }\n\n return {\n createRoot() {\n const LazyApp = React.lazy(appLoader);\n return (\n <React.Suspense fallback={suspenseFallback}>\n <LazyApp />\n </React.Suspense>\n );\n },\n };\n}\n\n/**\n * Synchronous version of {@link createApp}, expecting all features and\n * config to have been loaded already.\n *\n * @public\n */\nexport function createSpecializedApp(options?: {\n icons?: { [key in string]: IconComponent };\n features?: FrontendFeature[];\n config?: ConfigApi;\n bindRoutes?(context: { bind: CreateAppRouteBinder }): void;\n}): { createRoot(): JSX.Element } {\n const {\n features: duplicatedFeatures = [],\n config = new ConfigReader({}, 'empty-config'),\n } = options ?? {};\n\n const features = deduplicateFeatures(duplicatedFeatures);\n\n const tree = createAppTree({\n features,\n builtinExtensions,\n config,\n });\n\n const routeInfo = extractRouteInfoFromAppNode(tree.root);\n const routeBindings = resolveRouteBindings(\n options?.bindRoutes,\n config,\n collectRouteIds(features),\n );\n\n const appIdentityProxy = new AppIdentityProxy();\n const apiHolder = createApiHolder(\n tree,\n config,\n appIdentityProxy,\n new RouteResolver(\n routeInfo.routePaths,\n routeInfo.routeParents,\n routeInfo.routeObjects,\n routeBindings,\n getBasePath(config),\n ),\n options?.icons,\n );\n\n if (isProtectedApp()) {\n const discoveryApi = apiHolder.get(discoveryApiRef);\n const errorApi = apiHolder.get(errorApiRef);\n const fetchApi = apiHolder.get(fetchApiRef);\n if (!discoveryApi || !errorApi || !fetchApi) {\n throw new Error(\n 'App is running in protected mode but missing required APIs',\n );\n }\n appIdentityProxy.enableCookieAuth({\n discoveryApi,\n errorApi,\n fetchApi,\n });\n }\n\n const featureFlagApi = apiHolder.get(featureFlagsApiRef);\n if (featureFlagApi) {\n for (const feature of features) {\n if (feature.$$type === '@backstage/BackstagePlugin') {\n toInternalBackstagePlugin(feature).featureFlags.forEach(flag =>\n featureFlagApi.registerFlag({\n name: flag.name,\n pluginId: feature.id,\n }),\n );\n }\n if (feature.$$type === '@backstage/ExtensionOverrides') {\n toInternalExtensionOverrides(feature).featureFlags.forEach(flag =>\n featureFlagApi.registerFlag({ name: flag.name, pluginId: '' }),\n );\n }\n }\n }\n\n const rootEl = tree.root.instance!.getData(coreExtensionData.reactElement);\n\n const AppComponent = () => (\n <ApiProvider apis={apiHolder}>\n <AppThemeProvider>\n <InternalAppContext.Provider\n value={{ appIdentityProxy, routeObjects: routeInfo.routeObjects }}\n >\n {rootEl}\n </InternalAppContext.Provider>\n </AppThemeProvider>\n </ApiProvider>\n );\n\n return {\n createRoot() {\n return <AppComponent />;\n },\n };\n}\n\nfunction createApiHolder(\n tree: AppTree,\n configApi: ConfigApi,\n appIdentityProxy: AppIdentityProxy,\n routeResolutionApi: RouteResolutionApi,\n icons?: { [key in string]: IconComponent },\n): ApiHolder {\n const factoryRegistry = new ApiFactoryRegistry();\n\n const pluginApis =\n tree.root.edges.attachments\n .get('apis')\n ?.map(e => e.instance?.getData(createApiExtension.factoryDataRef))\n .filter((x): x is AnyApiFactory => !!x) ?? [];\n\n const themeExtensions =\n tree.root.edges.attachments\n .get('themes')\n ?.map(e => e.instance?.getData(createThemeExtension.themeDataRef))\n .filter((x): x is AppTheme => !!x) ?? [];\n\n const translationResources =\n tree.root.edges.attachments\n .get('translations')\n ?.map(e =>\n e.instance?.getData(createTranslationExtension.translationDataRef),\n )\n .filter(\n (x): x is typeof createTranslationExtension.translationDataRef.T => !!x,\n ) ?? [];\n\n for (const factory of pluginApis) {\n factoryRegistry.register('default', factory);\n }\n\n // TODO: properly discovery feature flags, maybe rework the whole thing\n factoryRegistry.register('default', {\n api: featureFlagsApiRef,\n deps: {},\n factory: () => new LocalStorageFeatureFlags(),\n });\n\n factoryRegistry.register('static', {\n api: identityApiRef,\n deps: {},\n factory: () => appIdentityProxy,\n });\n\n factoryRegistry.register('static', {\n api: appTreeApiRef,\n deps: {},\n factory: () => ({\n getTree: () => ({ tree }),\n }),\n });\n\n factoryRegistry.register('static', {\n api: routeResolutionApiRef,\n deps: {},\n factory: () => routeResolutionApi,\n });\n\n factoryRegistry.register('static', {\n api: componentsApiRef,\n deps: {},\n factory: () => DefaultComponentsApi.fromTree(tree),\n });\n\n factoryRegistry.register('static', {\n api: iconsApiRef,\n deps: {},\n factory: () => new DefaultIconsApi({ ...defaultIcons, ...icons }),\n });\n\n factoryRegistry.register('static', {\n api: appThemeApiRef,\n deps: {},\n // TODO: add extension for registering themes\n factory: () => AppThemeSelector.createWithStorage(themeExtensions),\n });\n\n factoryRegistry.register('static', {\n api: appLanguageApiRef,\n deps: {},\n factory: () => AppLanguageSelector.createWithStorage(),\n });\n\n factoryRegistry.register('static', {\n api: configApiRef,\n deps: {},\n factory: () => configApi,\n });\n\n factoryRegistry.register('static', {\n api: appLanguageApiRef,\n deps: {},\n factory: () => AppLanguageSelector.createWithStorage(),\n });\n\n factoryRegistry.register('static', {\n api: translationApiRef,\n deps: { languageApi: appLanguageApiRef },\n factory: ({ languageApi }) =>\n I18nextTranslationApi.create({\n languageApi,\n resources: translationResources,\n }),\n });\n\n ApiResolver.validateFactories(factoryRegistry, factoryRegistry.getAllApis());\n\n return new ApiResolver(factoryRegistry);\n}\n"],"names":["defaultApis","icons","defaultIcons"],"mappings":"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"}
1
+ {"version":3,"file":"createApp.esm.js","sources":["../../src/wiring/createApp.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, { JSX, ReactNode } from 'react';\nimport { ConfigReader } from '@backstage/config';\nimport {\n AppTree,\n appTreeApiRef,\n componentsApiRef,\n coreExtensionData,\n createApiExtension,\n createThemeExtension,\n createTranslationExtension,\n FrontendFeature,\n IconBundleBlueprint,\n iconsApiRef,\n RouteResolutionApi,\n routeResolutionApiRef,\n} from '@backstage/frontend-plugin-api';\nimport { App } from '../extensions/App';\nimport { AppRoutes } from '../extensions/AppRoutes';\nimport { AppLayout } from '../extensions/AppLayout';\nimport { AppNav } from '../extensions/AppNav';\nimport {\n AnyApiFactory,\n ApiHolder,\n appThemeApiRef,\n ConfigApi,\n configApiRef,\n IconComponent,\n featureFlagsApiRef,\n identityApiRef,\n AppTheme,\n errorApiRef,\n discoveryApiRef,\n fetchApiRef,\n} from '@backstage/core-plugin-api';\nimport { getAvailableFeatures } from './discovery';\nimport {\n ApiFactoryRegistry,\n ApiProvider,\n ApiResolver,\n AppThemeSelector,\n} from '@backstage/core-app-api';\n\n// TODO: Get rid of all of these\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { isProtectedApp } from '../../../core-app-api/src/app/isProtectedApp';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppThemeProvider } from '../../../core-app-api/src/app/AppThemeProvider';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppIdentityProxy } from '../../../core-app-api/src/apis/implementations/IdentityApi/AppIdentityProxy';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { LocalStorageFeatureFlags } from '../../../core-app-api/src/apis/implementations/FeatureFlagsApi/LocalStorageFeatureFlags';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { defaultConfigLoaderSync } from '../../../core-app-api/src/app/defaultConfigLoader';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { overrideBaseUrlConfigs } from '../../../core-app-api/src/app/overrideBaseUrlConfigs';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { AppLanguageSelector } from '../../../core-app-api/src/apis/implementations/AppLanguageApi/AppLanguageSelector';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { I18nextTranslationApi } from '../../../core-app-api/src/apis/implementations/TranslationApi/I18nextTranslationApi';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { resolveExtensionDefinition } from '../../../frontend-plugin-api/src/wiring/resolveExtensionDefinition';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { apis as defaultApis } from '../../../app-defaults/src/defaults';\nimport { DarkTheme, LightTheme } from '../extensions/themes';\nimport {\n oauthRequestDialogAppRootElement,\n alertDisplayAppRootElement,\n} from '../extensions/elements';\nimport { extractRouteInfoFromAppNode } from '../routing/extractRouteInfoFromAppNode';\nimport {\n appLanguageApiRef,\n translationApiRef,\n} from '@backstage/core-plugin-api/alpha';\nimport { CreateAppRouteBinder } from '../routing';\nimport { RouteResolver } from '../routing/RouteResolver';\nimport { resolveRouteBindings } from '../routing/resolveRouteBindings';\nimport { collectRouteIds } from '../routing/collectRouteIds';\nimport { createAppTree } from '../tree';\nimport {\n DefaultProgressComponent,\n DefaultErrorBoundaryComponent,\n DefaultNotFoundErrorPageComponent,\n} from '../extensions/components';\nimport { InternalAppContext } from './InternalAppContext';\nimport { AppRoot } from '../extensions/AppRoot';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalBackstagePlugin } from '../../../frontend-plugin-api/src/wiring/createPlugin';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { toInternalExtensionOverrides } from '../../../frontend-plugin-api/src/wiring/createExtensionOverrides';\nimport { DefaultComponentsApi } from '../apis/implementations/ComponentsApi';\nimport { DefaultIconsApi } from '../apis/implementations/IconsApi';\nimport { stringifyError } from '@backstage/errors';\n// eslint-disable-next-line @backstage/no-relative-monorepo-imports\nimport { icons as defaultIcons } from '../../../app-defaults/src/defaults';\nimport { getBasePath } from '../routing/getBasePath';\n\nconst DefaultApis = defaultApis.map(factory => createApiExtension({ factory }));\n\nexport const builtinExtensions = [\n App,\n AppRoot,\n AppRoutes,\n AppNav,\n AppLayout,\n DefaultProgressComponent,\n DefaultErrorBoundaryComponent,\n DefaultNotFoundErrorPageComponent,\n LightTheme,\n DarkTheme,\n oauthRequestDialogAppRootElement,\n alertDisplayAppRootElement,\n ...DefaultApis,\n].map(def => resolveExtensionDefinition(def));\n\nfunction deduplicateFeatures(\n allFeatures: FrontendFeature[],\n): FrontendFeature[] {\n // Start by removing duplicates by reference\n const features = Array.from(new Set(allFeatures));\n\n // Plugins are deduplicated by ID, last one wins\n const seenIds = new Set<string>();\n return features\n .reverse()\n .filter(feature => {\n if (feature.$$type !== '@backstage/BackstagePlugin') {\n return true;\n }\n if (seenIds.has(feature.id)) {\n return false;\n }\n seenIds.add(feature.id);\n return true;\n })\n .reverse();\n}\n\n/**\n * A source of dynamically loaded frontend features.\n *\n * @public\n */\nexport interface CreateAppFeatureLoader {\n /**\n * Returns name of this loader. suitable for showing to users.\n */\n getLoaderName(): string;\n\n /**\n * Loads a number of features dynamically.\n */\n load(options: { config: ConfigApi }): Promise<{\n features: FrontendFeature[];\n }>;\n}\n\n/** @public */\nexport function createApp(options?: {\n /** @deprecated - Please use {@link @backstage/frontend-plugin-api#IconBundleBlueprint} to make new icon bundles which can be installed in the app seperately */\n icons?: { [key in string]: IconComponent };\n features?: (FrontendFeature | CreateAppFeatureLoader)[];\n configLoader?: () => Promise<{ config: ConfigApi }>;\n bindRoutes?(context: { bind: CreateAppRouteBinder }): void;\n /**\n * The component to render while loading the app (waiting for config, features, etc)\n *\n * Is the text \"Loading...\" by default.\n * If set to \"null\" then no loading fallback component is rendered. *\n */\n loadingComponent?: ReactNode;\n}): {\n createRoot(): JSX.Element;\n} {\n let suspenseFallback = options?.loadingComponent;\n if (suspenseFallback === undefined) {\n suspenseFallback = 'Loading...';\n }\n\n async function appLoader() {\n const config =\n (await options?.configLoader?.().then(c => c.config)) ??\n ConfigReader.fromConfigs(\n overrideBaseUrlConfigs(defaultConfigLoaderSync()),\n );\n\n const discoveredFeatures = getAvailableFeatures(config);\n\n const providedFeatures: FrontendFeature[] = [];\n for (const entry of options?.features ?? []) {\n if ('load' in entry) {\n try {\n const result = await entry.load({ config });\n providedFeatures.push(...result.features);\n } catch (e) {\n throw new Error(\n `Failed to read frontend features from loader '${entry.getLoaderName()}', ${stringifyError(\n e,\n )}`,\n );\n }\n } else {\n providedFeatures.push(entry);\n }\n }\n\n const app = createSpecializedApp({\n icons: options?.icons,\n config,\n features: [...discoveredFeatures, ...providedFeatures],\n bindRoutes: options?.bindRoutes,\n }).createRoot();\n\n return { default: () => app };\n }\n\n return {\n createRoot() {\n const LazyApp = React.lazy(appLoader);\n return (\n <React.Suspense fallback={suspenseFallback}>\n <LazyApp />\n </React.Suspense>\n );\n },\n };\n}\n\n/**\n * Synchronous version of {@link createApp}, expecting all features and\n * config to have been loaded already.\n *\n * @public\n */\nexport function createSpecializedApp(options?: {\n /** @deprecated - Please use {@link @backstage/frontend-plugin-api#IconBundleBlueprint} to make new icon bundles which can be installed in the app seperately */\n icons?: { [key in string]: IconComponent };\n features?: FrontendFeature[];\n config?: ConfigApi;\n bindRoutes?(context: { bind: CreateAppRouteBinder }): void;\n}): { createRoot(): JSX.Element } {\n const {\n features: duplicatedFeatures = [],\n config = new ConfigReader({}, 'empty-config'),\n } = options ?? {};\n\n const features = deduplicateFeatures(duplicatedFeatures);\n\n const tree = createAppTree({\n features,\n builtinExtensions,\n config,\n });\n\n const routeInfo = extractRouteInfoFromAppNode(tree.root);\n const routeBindings = resolveRouteBindings(\n options?.bindRoutes,\n config,\n collectRouteIds(features),\n );\n\n const appIdentityProxy = new AppIdentityProxy();\n const apiHolder = createApiHolder(\n tree,\n config,\n appIdentityProxy,\n new RouteResolver(\n routeInfo.routePaths,\n routeInfo.routeParents,\n routeInfo.routeObjects,\n routeBindings,\n getBasePath(config),\n ),\n options?.icons,\n );\n\n if (isProtectedApp()) {\n const discoveryApi = apiHolder.get(discoveryApiRef);\n const errorApi = apiHolder.get(errorApiRef);\n const fetchApi = apiHolder.get(fetchApiRef);\n if (!discoveryApi || !errorApi || !fetchApi) {\n throw new Error(\n 'App is running in protected mode but missing required APIs',\n );\n }\n appIdentityProxy.enableCookieAuth({\n discoveryApi,\n errorApi,\n fetchApi,\n });\n }\n\n const featureFlagApi = apiHolder.get(featureFlagsApiRef);\n if (featureFlagApi) {\n for (const feature of features) {\n if (feature.$$type === '@backstage/BackstagePlugin') {\n toInternalBackstagePlugin(feature).featureFlags.forEach(flag =>\n featureFlagApi.registerFlag({\n name: flag.name,\n pluginId: feature.id,\n }),\n );\n }\n if (feature.$$type === '@backstage/ExtensionOverrides') {\n toInternalExtensionOverrides(feature).featureFlags.forEach(flag =>\n featureFlagApi.registerFlag({ name: flag.name, pluginId: '' }),\n );\n }\n }\n }\n\n const rootEl = tree.root.instance!.getData(coreExtensionData.reactElement);\n\n const AppComponent = () => (\n <ApiProvider apis={apiHolder}>\n <AppThemeProvider>\n <InternalAppContext.Provider\n value={{ appIdentityProxy, routeObjects: routeInfo.routeObjects }}\n >\n {rootEl}\n </InternalAppContext.Provider>\n </AppThemeProvider>\n </ApiProvider>\n );\n\n return {\n createRoot() {\n return <AppComponent />;\n },\n };\n}\n\nfunction createApiHolder(\n tree: AppTree,\n configApi: ConfigApi,\n appIdentityProxy: AppIdentityProxy,\n routeResolutionApi: RouteResolutionApi,\n icons?: { [key in string]: IconComponent },\n): ApiHolder {\n const factoryRegistry = new ApiFactoryRegistry();\n\n const pluginApis =\n tree.root.edges.attachments\n .get('apis')\n ?.map(e => e.instance?.getData(createApiExtension.factoryDataRef))\n .filter((x): x is AnyApiFactory => !!x) ?? [];\n\n const themeExtensions =\n tree.root.edges.attachments\n .get('themes')\n ?.map(e => e.instance?.getData(createThemeExtension.themeDataRef))\n .filter((x): x is AppTheme => !!x) ?? [];\n\n const translationResources =\n tree.root.edges.attachments\n .get('translations')\n ?.map(e =>\n e.instance?.getData(createTranslationExtension.translationDataRef),\n )\n .filter(\n (x): x is typeof createTranslationExtension.translationDataRef.T => !!x,\n ) ?? [];\n\n const extensionIcons = tree.root.edges.attachments\n .get('icons')\n ?.map(e => e.instance?.getData(IconBundleBlueprint.dataRefs.icons))\n .reduce((acc, bundle) => ({ ...acc, ...bundle }), {});\n\n for (const factory of pluginApis) {\n factoryRegistry.register('default', factory);\n }\n\n // TODO: properly discovery feature flags, maybe rework the whole thing\n factoryRegistry.register('default', {\n api: featureFlagsApiRef,\n deps: {},\n factory: () => new LocalStorageFeatureFlags(),\n });\n\n factoryRegistry.register('static', {\n api: identityApiRef,\n deps: {},\n factory: () => appIdentityProxy,\n });\n\n factoryRegistry.register('static', {\n api: appTreeApiRef,\n deps: {},\n factory: () => ({\n getTree: () => ({ tree }),\n }),\n });\n\n factoryRegistry.register('static', {\n api: routeResolutionApiRef,\n deps: {},\n factory: () => routeResolutionApi,\n });\n\n factoryRegistry.register('static', {\n api: componentsApiRef,\n deps: {},\n factory: () => DefaultComponentsApi.fromTree(tree),\n });\n\n factoryRegistry.register('static', {\n api: iconsApiRef,\n deps: {},\n factory: () =>\n new DefaultIconsApi({ ...defaultIcons, ...extensionIcons, ...icons }),\n });\n\n factoryRegistry.register('static', {\n api: appThemeApiRef,\n deps: {},\n // TODO: add extension for registering themes\n factory: () => AppThemeSelector.createWithStorage(themeExtensions),\n });\n\n factoryRegistry.register('static', {\n api: appLanguageApiRef,\n deps: {},\n factory: () => AppLanguageSelector.createWithStorage(),\n });\n\n factoryRegistry.register('static', {\n api: configApiRef,\n deps: {},\n factory: () => configApi,\n });\n\n factoryRegistry.register('static', {\n api: appLanguageApiRef,\n deps: {},\n factory: () => AppLanguageSelector.createWithStorage(),\n });\n\n factoryRegistry.register('static', {\n api: translationApiRef,\n deps: { languageApi: appLanguageApiRef },\n factory: ({ languageApi }) =>\n I18nextTranslationApi.create({\n languageApi,\n resources: translationResources,\n }),\n });\n\n ApiResolver.validateFactories(factoryRegistry, factoryRegistry.getAllApis());\n\n return new ApiResolver(factoryRegistry);\n}\n"],"names":["defaultApis","icons","defaultIcons"],"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.4",
3
+ "version": "0.7.5-next.1",
4
4
  "backstage": {
5
5
  "role": "web-library"
6
6
  },
@@ -33,11 +33,11 @@
33
33
  },
34
34
  "dependencies": {
35
35
  "@backstage/config": "^1.2.0",
36
- "@backstage/core-app-api": "^1.14.1",
37
- "@backstage/core-components": "^0.14.9",
36
+ "@backstage/core-app-api": "^1.14.2-next.0",
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.6.7",
40
+ "@backstage/frontend-plugin-api": "^0.6.8-next.1",
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.26.11",
51
- "@backstage/test-utils": "^1.5.9",
50
+ "@backstage/cli": "^0.27.0-next.1",
51
+ "@backstage/test-utils": "^1.5.10-next.1",
52
52
  "@testing-library/jest-dom": "^6.0.0",
53
53
  "@testing-library/react": "^15.0.0"
54
54
  },