@backstage/frontend-plugin-api 0.18.1 → 0.18.2-next.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +9 -0
- package/dist/alpha.d.ts +1 -1
- package/dist/analytics/AnalyticsContext.esm.js.map +1 -1
- package/dist/analytics/Tracker.esm.js.map +1 -1
- package/dist/analytics/useAnalytics.esm.js.map +1 -1
- package/dist/apis/definitions/AlertApi.esm.js.map +1 -1
- package/dist/apis/definitions/AnalyticsApi.esm.js.map +1 -1
- package/dist/apis/definitions/AppLanguageApi.esm.js.map +1 -1
- package/dist/apis/definitions/AppThemeApi.esm.js.map +1 -1
- package/dist/apis/definitions/AppTreeApi.esm.js.map +1 -1
- package/dist/apis/definitions/ConfigApi.esm.js.map +1 -1
- package/dist/apis/definitions/DialogApi.esm.js.map +1 -1
- package/dist/apis/definitions/DiscoveryApi.esm.js.map +1 -1
- package/dist/apis/definitions/ErrorApi.esm.js.map +1 -1
- package/dist/apis/definitions/FeatureFlagsApi.esm.js.map +1 -1
- package/dist/apis/definitions/FetchApi.esm.js.map +1 -1
- package/dist/apis/definitions/IconsApi.esm.js.map +1 -1
- package/dist/apis/definitions/IdentityApi.esm.js.map +1 -1
- package/dist/apis/definitions/OAuthRequestApi.esm.js.map +1 -1
- package/dist/apis/definitions/PluginHeaderActionsApi.esm.js.map +1 -1
- package/dist/apis/definitions/PluginWrapperApi.esm.js.map +1 -1
- package/dist/apis/definitions/RouteResolutionApi.esm.js.map +1 -1
- package/dist/apis/definitions/StorageApi.esm.js.map +1 -1
- package/dist/apis/definitions/SwappableComponentsApi.esm.js.map +1 -1
- package/dist/apis/definitions/ToastApi.esm.js.map +1 -1
- package/dist/apis/definitions/TranslationApi.esm.js.map +1 -1
- package/dist/apis/definitions/auth.esm.js.map +1 -1
- package/dist/apis/system/ApiRef.esm.js.map +1 -1
- package/dist/apis/system/helpers.esm.js.map +1 -1
- package/dist/apis/system/useApi.esm.js.map +1 -1
- package/dist/blueprints/AnalyticsImplementationBlueprint.esm.js.map +1 -1
- package/dist/blueprints/ApiBlueprint.esm.js.map +1 -1
- package/dist/blueprints/AppRootElementBlueprint.esm.js.map +1 -1
- package/dist/blueprints/PageBlueprint.esm.js.map +1 -1
- package/dist/blueprints/PluginHeaderActionBlueprint.esm.js.map +1 -1
- package/dist/blueprints/PluginWrapperBlueprint.esm.js.map +1 -1
- package/dist/blueprints/SubPageBlueprint.esm.js.map +1 -1
- package/dist/breadcrumbs/useBreadcrumbEntries.esm.js.map +1 -1
- package/dist/components/AppNodeProvider.esm.js.map +1 -1
- package/dist/components/DefaultSwappableComponents.esm.js.map +1 -1
- package/dist/components/ErrorApiBoundary.esm.js.map +1 -1
- package/dist/components/ErrorDisplayBoundary.esm.js.map +1 -1
- package/dist/components/ExtensionBoundary.esm.js.map +1 -1
- package/dist/components/PageLayout.esm.js.map +1 -1
- package/dist/components/createSwappableComponent.esm.js.map +1 -1
- package/dist/core-plugin-api/src/analytics/Tracker.esm.js.map +1 -1
- package/dist/frontend-internal/src/apis/OpaqueApiRef.esm.js.map +1 -1
- package/dist/frontend-internal/src/routing/OpaqueExternalRouteRef.esm.js.map +1 -1
- package/dist/frontend-internal/src/routing/OpaqueRouteRef.esm.js.map +1 -1
- package/dist/frontend-internal/src/routing/OpaqueSubRouteRef.esm.js.map +1 -1
- package/dist/frontend-internal/src/wiring/InternalExtensionDefinition.esm.js.map +1 -1
- package/dist/frontend-internal/src/wiring/InternalExtensionInput.esm.js.map +1 -1
- package/dist/frontend-internal/src/wiring/InternalFrontendPlugin.esm.js.map +1 -1
- package/dist/frontend-internal/src/wiring/InternalSwappableComponentRef.esm.js.map +1 -1
- package/dist/frontend-internal/src/wiring/createExtensionDataContainer.esm.js.map +1 -1
- package/dist/index.d.ts +75 -75
- package/dist/opaque-internal/src/OpaqueType.esm.js.map +1 -1
- package/dist/routing/ExternalRouteRef.esm.js.map +1 -1
- package/dist/routing/RouteRef.esm.js.map +1 -1
- package/dist/routing/SubRouteRef.esm.js.map +1 -1
- package/dist/routing/describeParentCallSite.esm.js.map +1 -1
- package/dist/routing/useRouteRef.esm.js.map +1 -1
- package/dist/routing/useRouteRefParams.esm.js.map +1 -1
- package/dist/schema/assertNoLegacyConfigSchema.esm.js.map +1 -1
- package/dist/schema/createPortableSchema.esm.js.map +1 -1
- package/dist/schema/optionalStringSchema.esm.js.map +1 -1
- package/dist/translation/TranslationMessages.esm.js.map +1 -1
- package/dist/translation/TranslationRef.esm.js.map +1 -1
- package/dist/translation/TranslationResource.esm.js.map +1 -1
- package/dist/translation/useTranslationRef.esm.js.map +1 -1
- package/dist/types/{alpha.d-DZG-WVJf.d.ts → alpha.d-BVLu8HlA.d.ts} +412 -412
- package/dist/wiring/constants.esm.js.map +1 -1
- package/dist/wiring/coreExtensionData.esm.js.map +1 -1
- package/dist/wiring/createExtension.esm.js.map +1 -1
- package/dist/wiring/createExtensionBlueprint.esm.js.map +1 -1
- package/dist/wiring/createExtensionDataRef.esm.js.map +1 -1
- package/dist/wiring/createExtensionInput.esm.js.map +1 -1
- package/dist/wiring/createFrontendFeatureLoader.esm.js.map +1 -1
- package/dist/wiring/createFrontendModule.esm.js.map +1 -1
- package/dist/wiring/createFrontendPlugin.esm.js.map +1 -1
- package/dist/wiring/resolveExtensionDefinition.esm.js.map +1 -1
- package/dist/wiring/resolveInputOverrides.esm.js.map +1 -1
- package/package.json +10 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.esm.js","sources":["../../src/wiring/constants.ts"],"sourcesContent":["/*\n * Copyright 2025 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\n// NOTE: changing any of these constants need to be reflected in\n// @backstage/backend-plugin-api/src/wiring/constants.ts as well\n\n/**\n * The pattern that IDs must match.\n *\n * @remarks\n * ids must only contain the letters `a` through `z` and digits, in groups separated by\n * dashes. Additionally, the very first character of the first group\n * must be a letter, not a digit\n *\n * @public\n */\nexport const ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/i;\n"],"names":[],"mappings":"AA6BO,MAAM,UAAA,GAAa
|
|
1
|
+
{"version":3,"file":"constants.esm.js","sources":["../../src/wiring/constants.ts"],"sourcesContent":["/*\n * Copyright 2025 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\n// NOTE: changing any of these constants need to be reflected in\n// @backstage/backend-plugin-api/src/wiring/constants.ts as well\n\n/**\n * The pattern that IDs must match.\n *\n * @remarks\n * ids must only contain the letters `a` through `z` and digits, in groups separated by\n * dashes. Additionally, the very first character of the first group\n * must be a letter, not a digit\n *\n * @public\n */\nexport const ID_PATTERN = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$/i;\n"],"names":[],"mappings":"AA6BO,MAAM,UAAA,GAAa;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"coreExtensionData.esm.js","sources":["../../src/wiring/coreExtensionData.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 { JSX } from 'react';\nimport { IconElement } from '../icons/types';\nimport { RouteRef } from '../routing/RouteRef';\nimport { createExtensionDataRef } from './createExtensionDataRef';\n\n/** @public */\nexport const coreExtensionData = {\n title: createExtensionDataRef<string>().with({ id: 'core.title' }),\n /** An icon element for the extension. Should be exactly 24x24 pixels. */\n icon: createExtensionDataRef<IconElement>().with({ id: 'core.icon' }),\n reactElement: createExtensionDataRef<JSX.Element>().with({\n id: 'core.reactElement',\n }),\n routePath: createExtensionDataRef<string>().with({ id: 'core.routing.path' }),\n routeRef: createExtensionDataRef<RouteRef>().with({ id: 'core.routing.ref' }),\n};\n"],"names":[],"mappings":";;AAsBO,MAAM,iBAAA,GAAoB;AAAA,EAC/B,OAAO,sBAAA,EAA+B,CAAE,KAAK,EAAE,EAAA,EAAI,cAAc,CAAA;AAAA;AAAA,EAEjE,MAAM,sBAAA,EAAoC,CAAE,KAAK,EAAE,EAAA,EAAI,aAAa,CAAA;AAAA,EACpE,YAAA,EAAc,sBAAA,EAAoC,CAAE,IAAA,CAAK;AAAA,IACvD,EAAA,EAAI;AAAA,GACL,CAAA;AAAA,EACD,WAAW,sBAAA,EAA+B,CAAE,KAAK,EAAE,EAAA,EAAI,qBAAqB,CAAA;AAAA,EAC5E,UAAU,sBAAA,EAAiC,CAAE,KAAK,EAAE,EAAA,EAAI,oBAAoB;AAC9E
|
|
1
|
+
{"version":3,"file":"coreExtensionData.esm.js","sources":["../../src/wiring/coreExtensionData.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 { JSX } from 'react';\nimport { IconElement } from '../icons/types';\nimport { RouteRef } from '../routing/RouteRef';\nimport { createExtensionDataRef } from './createExtensionDataRef';\n\n/** @public */\nexport const coreExtensionData = {\n title: createExtensionDataRef<string>().with({ id: 'core.title' }),\n /** An icon element for the extension. Should be exactly 24x24 pixels. */\n icon: createExtensionDataRef<IconElement>().with({ id: 'core.icon' }),\n reactElement: createExtensionDataRef<JSX.Element>().with({\n id: 'core.reactElement',\n }),\n routePath: createExtensionDataRef<string>().with({ id: 'core.routing.path' }),\n routeRef: createExtensionDataRef<RouteRef>().with({ id: 'core.routing.ref' }),\n};\n"],"names":[],"mappings":";;AAsBO,MAAM,iBAAA,GAAoB;AAAA,EAC/B,OAAO,sBAAA,EAA+B,CAAE,KAAK,EAAE,EAAA,EAAI,cAAc,CAAA;AAAA;AAAA,EAEjE,MAAM,sBAAA,EAAoC,CAAE,KAAK,EAAE,EAAA,EAAI,aAAa,CAAA;AAAA,EACpE,YAAA,EAAc,sBAAA,EAAoC,CAAE,IAAA,CAAK;AAAA,IACvD,EAAA,EAAI;AAAA,GACL,CAAA;AAAA,EACD,WAAW,sBAAA,EAA+B,CAAE,KAAK,EAAE,EAAA,EAAI,qBAAqB,CAAA;AAAA,EAC5E,UAAU,sBAAA,EAAiC,CAAE,KAAK,EAAE,EAAA,EAAI,oBAAoB;AAC9E;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createExtension.esm.js","sources":["../../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 { ApiHolder, AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport {\n ResolvedInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\nimport {\n createExtensionDataContainer,\n OpaqueExtensionInput,\n} from '@internal/frontend';\nimport { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\nimport { createConfigSchema } from '../schema/createPortableSchema';\nimport { type StandardSchemaV1 } from '@standard-schema/spec';\nimport { OpaqueExtensionDefinition } from '@internal/frontend';\nimport { ExtensionDataContainer } from './types';\nimport {\n ExtensionBlueprint,\n ExtensionBlueprintDefineParams,\n} from './createExtensionBlueprint';\nimport { FrontendPlugin } from './createFrontendPlugin';\nimport { FrontendModule } from './createFrontendModule';\nimport { FilterPredicate } from '@backstage/filter-predicates';\nimport { assertNoLegacyConfigSchema } from '../schema/assertNoLegacyConfigSchema';\n\n/**\n * This symbol is used to pass parameter overrides from the extension override to the blueprint factory\n * @internal\n */\nexport const ctxParamsSymbol = Symbol('params');\n\n/** @ignore */\ntype ResolvedExtensionInput<TExtensionInput extends ExtensionInput> =\n TExtensionInput['extensionData'] extends Array<ExtensionDataRef>\n ? {\n node: AppNode;\n } & ExtensionDataContainer<TExtensionInput['extensionData'][number]>\n : never;\n\n/**\n * Converts an extension input map into a matching collection of resolved inputs.\n *\n * @ignore\n */\nexport type ResolvedExtensionInputs<\n TInputs extends {\n [name in string]: ExtensionInput;\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\ntype ToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I,\n) => void\n ? I\n : never;\n\ntype PopUnion<U> = ToIntersection<\n U extends any ? () => U : never\n> extends () => infer R\n ? [rest: Exclude<U, R>, next: R]\n : undefined;\n\n/** @ignore */\ntype JoinStringUnion<\n U,\n TDiv extends string = ', ',\n TResult extends string = '',\n> = PopUnion<U> extends [infer IRest extends string, infer INext extends string]\n ? TResult extends ''\n ? JoinStringUnion<IRest, TDiv, INext>\n : JoinStringUnion<IRest, TDiv, `${TResult}${TDiv}${INext}`>\n : TResult;\n\n/** @ignore */\nexport type RequiredExtensionIds<UExtensionData extends ExtensionDataRef> =\n UExtensionData extends any\n ? UExtensionData['config']['optional'] extends true\n ? never\n : UExtensionData['id']\n : never;\n\n/** @ignore */\nexport type VerifyExtensionFactoryOutput<\n UDeclaredOutput extends ExtensionDataRef,\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = [RequiredExtensionIds<UDeclaredOutput>] extends [UFactoryOutput['id']]\n ? [UFactoryOutput['id']] extends [UDeclaredOutput['id']]\n ? {}\n : `Error: The extension factory has undeclared output(s): ${JoinStringUnion<\n Exclude<UFactoryOutput['id'], UDeclaredOutput['id']>\n >}`\n : `Error: The extension factory is missing the following output(s): ${JoinStringUnion<\n Exclude<RequiredExtensionIds<UDeclaredOutput>, UFactoryOutput['id']>\n >}`;\n\n/** @ignore */\nexport type VerifyExtensionAttachTo<\n UOutput extends ExtensionDataRef,\n UParentInput extends ExtensionDataRef,\n> = ExtensionDataRef extends UParentInput\n ? {}\n : [RequiredExtensionIds<UParentInput>] extends [RequiredExtensionIds<UOutput>]\n ? {}\n : `Error: This parent extension input requires the following extension data, but it is not declared as guaranteed output of this extension: ${JoinStringUnion<\n Exclude<RequiredExtensionIds<UParentInput>, RequiredExtensionIds<UOutput>>\n >}`;\n\n/**\n * Specifies where an extension should attach in the extension tree.\n *\n * @remarks\n *\n * A standard attachment point declaration will specify the ID of the parent extension, as well as the name of the input to attach to.\n *\n * There are two more advanced forms that are available for more complex use-cases:\n *\n * 1. Relative attachment points: using the `relative` property instead of `id`, the attachment point is resolved relative to the current plugin.\n * 2. Extension input references: using a reference in code to another extension's input in the same plugin. These references are always relative.\n *\n * @example\n * ```ts\n * // Attach to a specific extension by full ID\n * { id: 'app/routes', input: 'routes' }\n *\n * // Attach to an extension in the same plugin by kind\n * { relative: { kind: 'page' }, input: 'actions' }\n *\n * // Attach to a specific input of another extension\n * const page = ParentBlueprint.make({ ... });\n * const child = ChildBlueprint.make({ attachTo: page.inputs.children });\n * ```\n *\n * @public\n */\nexport type ExtensionDefinitionAttachTo<\n UParentInputs extends ExtensionDataRef = ExtensionDataRef,\n> =\n | { id: string; input: string; relative?: never }\n | { relative: { kind?: string; name?: string }; input: string; id?: never }\n | ExtensionInput<UParentInputs>;\n\n/** @public */\nexport type CreateExtensionOptions<\n TKind extends string | undefined,\n TName extends string | undefined,\n UOutput extends ExtensionDataRef,\n TInputs extends { [inputName in string]: ExtensionInput },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UParentInputs extends ExtensionDataRef,\n TNewConfigSchema extends { [key: string]: StandardSchemaV1 } = {},\n> = {\n kind?: TKind;\n name?: TName;\n attachTo: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<UOutput, UParentInputs>;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TInputs;\n output: Array<UOutput>;\n configSchema?: TNewConfigSchema;\n factory(context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Iterable<UFactoryOutput>;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport type ExtensionDefinitionParameters = {\n kind?: string;\n name?: string;\n configInput?: { [K in string]: any };\n config?: { [K in string]: any };\n output?: ExtensionDataRef;\n inputs?: { [KName in string]: ExtensionInput };\n params?: object | ExtensionBlueprintDefineParams;\n};\n\n/**\n * Same as the one in `createExtensionBlueprint`, but with `ParamsFactory` inlined.\n * It can't be exported because it breaks API reports.\n * @ignore\n */\ntype AnyParamsInput<TParams extends object | ExtensionBlueprintDefineParams> =\n TParams extends ExtensionBlueprintDefineParams<infer IParams>\n ? IParams | ((define: TParams) => ReturnType<TParams>)\n :\n | TParams\n | ((\n define: ExtensionBlueprintDefineParams<TParams, TParams>,\n ) => ReturnType<ExtensionBlueprintDefineParams<TParams, TParams>>);\n\n/** @public */\nexport interface ExtensionDefinition<\n TParams extends ExtensionDefinitionParameters = ExtensionDefinitionParameters,\n> {\n $$type: '@backstage/ExtensionDefinition';\n readonly T: TParams;\n}\n\n/** @public */\nexport interface OverridableExtensionDefinition<\n T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters,\n> extends ExtensionDefinition<T> {\n /**\n * References to the inputs of this extension, which can be used to attach child extensions.\n */\n readonly inputs: {\n [K in keyof T['inputs']]: ExtensionInput<\n T['inputs'][K] extends ExtensionInput<infer IData> ? IData : never\n >;\n };\n\n override<\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends ExtensionDataRef,\n TExtraInputs extends { [inputName in string]: ExtensionInput },\n TParamsInput extends AnyParamsInput<NonNullable<T['params']>>,\n UParentInputs extends ExtensionDataRef,\n TNewExtensionConfigSchema extends {\n [key in string]: StandardSchemaV1;\n } = {},\n >(\n args: Expand<\n {\n attachTo?: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<\n ExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UParentInputs\n >;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TExtraInputs & {\n [KName in keyof T['inputs']]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: never;\n configSchema?: TNewExtensionConfigSchema & {\n [KName in keyof T['config']]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n factory?(\n originalFactory: <\n TFactoryParamsReturn extends AnyParamsInput<\n NonNullable<T['params']>\n >,\n >(\n context?: Expand<\n {\n config?: T['config'];\n inputs?: ResolvedInputValueOverrides<NonNullable<T['inputs']>>;\n } & ([T['params']] extends [never]\n ? {}\n : {\n params?: TFactoryParamsReturn extends ExtensionBlueprintDefineParams\n ? TFactoryParamsReturn\n : T['params'] extends ExtensionBlueprintDefineParams\n ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams(<params>))`'\n : Partial<T['params']>;\n })\n >,\n ) => ExtensionDataContainer<NonNullable<T['output']>>,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: T['config'] & {\n [key in keyof TNewExtensionConfigSchema]: StandardSchemaV1.InferOutput<\n TNewExtensionConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n } & ([T['params']] extends [never]\n ? {}\n : {\n params?: TParamsInput extends ExtensionBlueprintDefineParams\n ? TParamsInput\n : T['params'] extends ExtensionBlueprintDefineParams\n ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams(<params>))`'\n : Partial<T['params']>;\n })\n > &\n VerifyExtensionFactoryOutput<\n ExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UFactoryOutput\n >,\n ): OverridableExtensionDefinition<{\n kind: T['kind'];\n name: T['name'];\n output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;\n inputs: T['inputs'] & TExtraInputs;\n config: T['config'] & {\n [key in keyof TNewExtensionConfigSchema]: StandardSchemaV1.InferOutput<\n TNewExtensionConfigSchema[key]\n >;\n };\n configInput: T['configInput'] & {\n [key in keyof TNewExtensionConfigSchema]?: StandardSchemaV1.InferInput<\n TNewExtensionConfigSchema[key]\n >;\n };\n }>;\n}\n\n/**\n * @internal\n */\nfunction bindInputs(\n inputs: { [inputName in string]: ExtensionInput } | undefined,\n kind?: string,\n name?: string,\n) {\n if (!inputs) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(inputs).map(([inputName, input]) => [\n inputName,\n OpaqueExtensionInput.toInternal(input).withContext?.({\n kind,\n name,\n input: inputName,\n }) ?? input,\n ]),\n );\n}\n\n/**\n * Creates a new extension definition for installation in a Backstage app.\n *\n * @remarks\n *\n * This is a low-level function for creation of extensions with arbitrary inputs\n * and outputs and is typically only intended to be used for advanced overrides\n * or framework-level extensions. For most extension creation needs, it is\n * recommended to use existing {@link ExtensionBlueprint}s instead. You can find\n * blueprints both in the `@backstage/frontend-plugin-api` package as well as\n * other plugin libraries. There is also a list of\n * {@link https://backstage.io/docs/frontend-system/building-plugins/common-extension-blueprints | commonly used blueprints}\n * in the frontend system documentation.\n *\n * Extension definitions that are created with this function can be installed in\n * a Backstage app via a {@link FrontendPlugin} or {@link FrontendModule}.\n *\n * For more details on how extensions work, see the\n * {@link https://backstage.io/docs/frontend-system/architecture/extensions | documentation for extensions}.\n *\n * @example\n *\n * ```ts\n * const myExtension = createExtension({\n * name: 'example',\n * attachTo: { id: 'app', input: 'root' },\n * output: [coreExtensionData.reactElement],\n * factory() {\n * return [coreExtensionData.reactElement(<h1>Hello, world!</h1>)];\n * },\n * });\n * ```\n *\n * @public\n */\nexport function createExtension<\n UOutput extends ExtensionDataRef,\n TInputs extends { [inputName in string]: ExtensionInput },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n const TKind extends string | undefined = undefined,\n const TName extends string | undefined = undefined,\n UParentInputs extends ExtensionDataRef = ExtensionDataRef,\n TNewConfigSchema extends { [key: string]: StandardSchemaV1 } = {},\n>(\n options: CreateExtensionOptions<\n TKind,\n TName,\n UOutput,\n TInputs,\n UFactoryOutput,\n UParentInputs,\n TNewConfigSchema\n >,\n): OverridableExtensionDefinition<{\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n configInput: {\n [key in keyof TNewConfigSchema]?: StandardSchemaV1.InferInput<\n TNewConfigSchema[key]\n >;\n };\n output: UOutput extends ExtensionDataRef<\n infer IData,\n infer IId,\n infer IConfig\n >\n ? ExtensionDataRef<IData, IId, IConfig>\n : never;\n inputs: TInputs;\n params: never;\n kind: string | undefined extends TKind ? undefined : TKind;\n name: string | undefined extends TName ? undefined : TName;\n}>;\n\n/** @internal */\nexport function createExtension(\n options: any,\n): OverridableExtensionDefinition<any> {\n assertNoLegacyConfigSchema(options);\n\n const resolvedConfigSchema = options.configSchema\n ? createConfigSchema(options.configSchema)\n : undefined;\n\n return OpaqueExtensionDefinition.createInstance('v2', {\n T: undefined as any,\n kind: options.kind,\n name: options.name,\n attachTo: options.attachTo,\n disabled: options.disabled ?? false,\n if: options.if,\n inputs: bindInputs(options.inputs, options.kind, options.name),\n output: options.output,\n configSchema: resolvedConfigSchema,\n factory: options.factory,\n toString() {\n const parts: string[] = [];\n if (options.kind) {\n parts.push(`kind=${options.kind}`);\n }\n if (options.name) {\n parts.push(`name=${options.name}`);\n }\n const attachTo = [options.attachTo]\n .flat()\n .map(aAny => {\n const a = aAny as ExtensionDefinitionAttachTo;\n if (OpaqueExtensionInput.isType(a)) {\n const { context } = OpaqueExtensionInput.toInternal(a);\n if (!context) {\n return '<detached-input>';\n }\n let id = '<plugin>';\n if (context?.kind) {\n id = `${context?.kind}:${id}`;\n }\n if (context?.name) {\n id = `${id}/${context?.name}`;\n }\n return `${id}@${context.input}`;\n }\n if ('relative' in a && a.relative) {\n let id = '<plugin>';\n if (a.relative.kind) {\n id = `${a.relative.kind}:${id}`;\n }\n if (a.relative.name) {\n id = `${id}/${a.relative.name}`;\n }\n return `${id}@${a.input}`;\n }\n if ('id' in a) {\n return `${a.id}@${a.input}`;\n }\n throw new Error('Invalid attachment point specification');\n })\n .join('+');\n parts.push(`attachTo=${attachTo}`);\n return `ExtensionDefinition{${parts.join(',')}}`;\n },\n override(overrideOptions: any) {\n assertNoLegacyConfigSchema(overrideOptions);\n\n if (!Array.isArray(options.output)) {\n throw new Error(\n 'Cannot override an extension that is not declared using the new format with outputs as an array',\n );\n }\n\n // TODO(Rugvip): Making this a type check would be optimal, but it seems\n // like it's tricky to add that and still have the type\n // inference work correctly for the factory output.\n if (overrideOptions.output && !overrideOptions.factory) {\n throw new Error(\n 'Refused to override output without also overriding factory',\n );\n }\n // TODO(Rugvip): Similar to above, would be nice to error during type checking, but don't want to complicate the types too much\n if (overrideOptions.params && overrideOptions.factory) {\n throw new Error(\n 'Refused to override params and factory at the same time',\n );\n }\n\n let ifPredicate = options.if;\n if ('if' in overrideOptions) {\n ifPredicate = overrideOptions.if;\n }\n\n return createExtension({\n kind: options.kind,\n name: options.name,\n attachTo: (overrideOptions.attachTo ??\n options.attachTo) as ExtensionDefinitionAttachTo,\n disabled: overrideOptions.disabled ?? options.disabled,\n if: ifPredicate,\n inputs: bindInputs(\n {\n ...(options.inputs ?? {}),\n ...(overrideOptions.inputs ?? {}),\n },\n options.kind,\n options.name,\n ),\n output: (overrideOptions.output ??\n options.output) as ExtensionDataRef[],\n configSchema:\n options.configSchema || overrideOptions.configSchema\n ? {\n ...options.configSchema,\n ...overrideOptions.configSchema,\n }\n : undefined,\n factory: ({ node, apis, config, inputs }) => {\n if (!overrideOptions.factory) {\n return options.factory({\n node,\n apis,\n config: config as any,\n inputs: inputs as any,\n [ctxParamsSymbol as any]: overrideOptions.params,\n });\n }\n const parentResult = overrideOptions.factory(\n (innerContext: any): ExtensionDataContainer<any> => {\n return createExtensionDataContainer<any>(\n options.factory({\n node,\n apis,\n config: (innerContext?.config ?? config) as any,\n inputs: resolveInputOverrides(\n options.inputs,\n inputs,\n innerContext?.inputs,\n ) as any,\n [ctxParamsSymbol as any]: innerContext?.params,\n }) as Iterable<any>,\n 'original extension factory',\n options.output,\n );\n },\n {\n node,\n apis,\n config: config as any,\n inputs: inputs as any,\n },\n );\n\n if (\n typeof parentResult !== 'object' ||\n !parentResult?.[Symbol.iterator]\n ) {\n throw new Error(\n 'extension factory override did not provide an iterable object',\n );\n }\n\n const deduplicatedResult = new Map<\n string,\n ExtensionDataValue<any, any>\n >();\n for (const item of parentResult) {\n deduplicatedResult.set(item.id, item);\n }\n\n return deduplicatedResult.values();\n },\n }) as OverridableExtensionDefinition<any>;\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createExtension.esm.js","sources":["../../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 { ApiHolder, AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport {\n ResolvedInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\nimport {\n createExtensionDataContainer,\n OpaqueExtensionInput,\n} from '@internal/frontend';\nimport { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\nimport { createConfigSchema } from '../schema/createPortableSchema';\nimport { type StandardSchemaV1 } from '@standard-schema/spec';\nimport { OpaqueExtensionDefinition } from '@internal/frontend';\nimport { ExtensionDataContainer } from './types';\nimport {\n ExtensionBlueprint,\n ExtensionBlueprintDefineParams,\n} from './createExtensionBlueprint';\nimport { FrontendPlugin } from './createFrontendPlugin';\nimport { FrontendModule } from './createFrontendModule';\nimport { FilterPredicate } from '@backstage/filter-predicates';\nimport { assertNoLegacyConfigSchema } from '../schema/assertNoLegacyConfigSchema';\n\n/**\n * This symbol is used to pass parameter overrides from the extension override to the blueprint factory\n * @internal\n */\nexport const ctxParamsSymbol = Symbol('params');\n\n/** @ignore */\ntype ResolvedExtensionInput<TExtensionInput extends ExtensionInput> =\n TExtensionInput['extensionData'] extends Array<ExtensionDataRef>\n ? {\n node: AppNode;\n } & ExtensionDataContainer<TExtensionInput['extensionData'][number]>\n : never;\n\n/**\n * Converts an extension input map into a matching collection of resolved inputs.\n *\n * @ignore\n */\nexport type ResolvedExtensionInputs<\n TInputs extends {\n [name in string]: ExtensionInput;\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\ntype ToIntersection<U> = (U extends any ? (k: U) => void : never) extends (\n k: infer I,\n) => void\n ? I\n : never;\n\ntype PopUnion<U> = ToIntersection<\n U extends any ? () => U : never\n> extends () => infer R\n ? [rest: Exclude<U, R>, next: R]\n : undefined;\n\n/** @ignore */\ntype JoinStringUnion<\n U,\n TDiv extends string = ', ',\n TResult extends string = '',\n> = PopUnion<U> extends [infer IRest extends string, infer INext extends string]\n ? TResult extends ''\n ? JoinStringUnion<IRest, TDiv, INext>\n : JoinStringUnion<IRest, TDiv, `${TResult}${TDiv}${INext}`>\n : TResult;\n\n/** @ignore */\nexport type RequiredExtensionIds<UExtensionData extends ExtensionDataRef> =\n UExtensionData extends any\n ? UExtensionData['config']['optional'] extends true\n ? never\n : UExtensionData['id']\n : never;\n\n/** @ignore */\nexport type VerifyExtensionFactoryOutput<\n UDeclaredOutput extends ExtensionDataRef,\n UFactoryOutput extends ExtensionDataValue<any, any>,\n> = [RequiredExtensionIds<UDeclaredOutput>] extends [UFactoryOutput['id']]\n ? [UFactoryOutput['id']] extends [UDeclaredOutput['id']]\n ? {}\n : `Error: The extension factory has undeclared output(s): ${JoinStringUnion<\n Exclude<UFactoryOutput['id'], UDeclaredOutput['id']>\n >}`\n : `Error: The extension factory is missing the following output(s): ${JoinStringUnion<\n Exclude<RequiredExtensionIds<UDeclaredOutput>, UFactoryOutput['id']>\n >}`;\n\n/** @ignore */\nexport type VerifyExtensionAttachTo<\n UOutput extends ExtensionDataRef,\n UParentInput extends ExtensionDataRef,\n> = ExtensionDataRef extends UParentInput\n ? {}\n : [RequiredExtensionIds<UParentInput>] extends [RequiredExtensionIds<UOutput>]\n ? {}\n : `Error: This parent extension input requires the following extension data, but it is not declared as guaranteed output of this extension: ${JoinStringUnion<\n Exclude<RequiredExtensionIds<UParentInput>, RequiredExtensionIds<UOutput>>\n >}`;\n\n/**\n * Specifies where an extension should attach in the extension tree.\n *\n * @remarks\n *\n * A standard attachment point declaration will specify the ID of the parent extension, as well as the name of the input to attach to.\n *\n * There are two more advanced forms that are available for more complex use-cases:\n *\n * 1. Relative attachment points: using the `relative` property instead of `id`, the attachment point is resolved relative to the current plugin.\n * 2. Extension input references: using a reference in code to another extension's input in the same plugin. These references are always relative.\n *\n * @example\n * ```ts\n * // Attach to a specific extension by full ID\n * { id: 'app/routes', input: 'routes' }\n *\n * // Attach to an extension in the same plugin by kind\n * { relative: { kind: 'page' }, input: 'actions' }\n *\n * // Attach to a specific input of another extension\n * const page = ParentBlueprint.make({ ... });\n * const child = ChildBlueprint.make({ attachTo: page.inputs.children });\n * ```\n *\n * @public\n */\nexport type ExtensionDefinitionAttachTo<\n UParentInputs extends ExtensionDataRef = ExtensionDataRef,\n> =\n | { id: string; input: string; relative?: never }\n | { relative: { kind?: string; name?: string }; input: string; id?: never }\n | ExtensionInput<UParentInputs>;\n\n/** @public */\nexport type CreateExtensionOptions<\n TKind extends string | undefined,\n TName extends string | undefined,\n UOutput extends ExtensionDataRef,\n TInputs extends { [inputName in string]: ExtensionInput },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UParentInputs extends ExtensionDataRef,\n TNewConfigSchema extends { [key: string]: StandardSchemaV1 } = {},\n> = {\n kind?: TKind;\n name?: TName;\n attachTo: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<UOutput, UParentInputs>;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TInputs;\n output: Array<UOutput>;\n configSchema?: TNewConfigSchema;\n factory(context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n }): Iterable<UFactoryOutput>;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport type ExtensionDefinitionParameters = {\n kind?: string;\n name?: string;\n configInput?: { [K in string]: any };\n config?: { [K in string]: any };\n output?: ExtensionDataRef;\n inputs?: { [KName in string]: ExtensionInput };\n params?: object | ExtensionBlueprintDefineParams;\n};\n\n/**\n * Same as the one in `createExtensionBlueprint`, but with `ParamsFactory` inlined.\n * It can't be exported because it breaks API reports.\n * @ignore\n */\ntype AnyParamsInput<TParams extends object | ExtensionBlueprintDefineParams> =\n TParams extends ExtensionBlueprintDefineParams<infer IParams>\n ? IParams | ((define: TParams) => ReturnType<TParams>)\n :\n | TParams\n | ((\n define: ExtensionBlueprintDefineParams<TParams, TParams>,\n ) => ReturnType<ExtensionBlueprintDefineParams<TParams, TParams>>);\n\n/** @public */\nexport interface ExtensionDefinition<\n TParams extends ExtensionDefinitionParameters = ExtensionDefinitionParameters,\n> {\n $$type: '@backstage/ExtensionDefinition';\n readonly T: TParams;\n}\n\n/** @public */\nexport interface OverridableExtensionDefinition<\n T extends ExtensionDefinitionParameters = ExtensionDefinitionParameters,\n> extends ExtensionDefinition<T> {\n /**\n * References to the inputs of this extension, which can be used to attach child extensions.\n */\n readonly inputs: {\n [K in keyof T['inputs']]: ExtensionInput<\n T['inputs'][K] extends ExtensionInput<infer IData> ? IData : never\n >;\n };\n\n override<\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends ExtensionDataRef,\n TExtraInputs extends { [inputName in string]: ExtensionInput },\n TParamsInput extends AnyParamsInput<NonNullable<T['params']>>,\n UParentInputs extends ExtensionDataRef,\n TNewExtensionConfigSchema extends {\n [key in string]: StandardSchemaV1;\n } = {},\n >(\n args: Expand<\n {\n attachTo?: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<\n ExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UParentInputs\n >;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TExtraInputs & {\n [KName in keyof T['inputs']]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: never;\n configSchema?: TNewExtensionConfigSchema & {\n [KName in keyof T['config']]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n factory?(\n originalFactory: <\n TFactoryParamsReturn extends AnyParamsInput<\n NonNullable<T['params']>\n >,\n >(\n context?: Expand<\n {\n config?: T['config'];\n inputs?: ResolvedInputValueOverrides<NonNullable<T['inputs']>>;\n } & ([T['params']] extends [never]\n ? {}\n : {\n params?: TFactoryParamsReturn extends ExtensionBlueprintDefineParams\n ? TFactoryParamsReturn\n : T['params'] extends ExtensionBlueprintDefineParams\n ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams(<params>))`'\n : Partial<T['params']>;\n })\n >,\n ) => ExtensionDataContainer<NonNullable<T['output']>>,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: T['config'] & {\n [key in keyof TNewExtensionConfigSchema]: StandardSchemaV1.InferOutput<\n TNewExtensionConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n } & ([T['params']] extends [never]\n ? {}\n : {\n params?: TParamsInput extends ExtensionBlueprintDefineParams\n ? TParamsInput\n : T['params'] extends ExtensionBlueprintDefineParams\n ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams(<params>))`'\n : Partial<T['params']>;\n })\n > &\n VerifyExtensionFactoryOutput<\n ExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UFactoryOutput\n >,\n ): OverridableExtensionDefinition<{\n kind: T['kind'];\n name: T['name'];\n output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;\n inputs: T['inputs'] & TExtraInputs;\n config: T['config'] & {\n [key in keyof TNewExtensionConfigSchema]: StandardSchemaV1.InferOutput<\n TNewExtensionConfigSchema[key]\n >;\n };\n configInput: T['configInput'] & {\n [key in keyof TNewExtensionConfigSchema]?: StandardSchemaV1.InferInput<\n TNewExtensionConfigSchema[key]\n >;\n };\n }>;\n}\n\n/**\n * @internal\n */\nfunction bindInputs(\n inputs: { [inputName in string]: ExtensionInput } | undefined,\n kind?: string,\n name?: string,\n) {\n if (!inputs) {\n return {};\n }\n\n return Object.fromEntries(\n Object.entries(inputs).map(([inputName, input]) => [\n inputName,\n OpaqueExtensionInput.toInternal(input).withContext?.({\n kind,\n name,\n input: inputName,\n }) ?? input,\n ]),\n );\n}\n\n/**\n * Creates a new extension definition for installation in a Backstage app.\n *\n * @remarks\n *\n * This is a low-level function for creation of extensions with arbitrary inputs\n * and outputs and is typically only intended to be used for advanced overrides\n * or framework-level extensions. For most extension creation needs, it is\n * recommended to use existing {@link ExtensionBlueprint}s instead. You can find\n * blueprints both in the `@backstage/frontend-plugin-api` package as well as\n * other plugin libraries. There is also a list of\n * {@link https://backstage.io/docs/frontend-system/building-plugins/common-extension-blueprints | commonly used blueprints}\n * in the frontend system documentation.\n *\n * Extension definitions that are created with this function can be installed in\n * a Backstage app via a {@link FrontendPlugin} or {@link FrontendModule}.\n *\n * For more details on how extensions work, see the\n * {@link https://backstage.io/docs/frontend-system/architecture/extensions | documentation for extensions}.\n *\n * @example\n *\n * ```ts\n * const myExtension = createExtension({\n * name: 'example',\n * attachTo: { id: 'app', input: 'root' },\n * output: [coreExtensionData.reactElement],\n * factory() {\n * return [coreExtensionData.reactElement(<h1>Hello, world!</h1>)];\n * },\n * });\n * ```\n *\n * @public\n */\nexport function createExtension<\n UOutput extends ExtensionDataRef,\n TInputs extends { [inputName in string]: ExtensionInput },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n const TKind extends string | undefined = undefined,\n const TName extends string | undefined = undefined,\n UParentInputs extends ExtensionDataRef = ExtensionDataRef,\n TNewConfigSchema extends { [key: string]: StandardSchemaV1 } = {},\n>(\n options: CreateExtensionOptions<\n TKind,\n TName,\n UOutput,\n TInputs,\n UFactoryOutput,\n UParentInputs,\n TNewConfigSchema\n >,\n): OverridableExtensionDefinition<{\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n configInput: {\n [key in keyof TNewConfigSchema]?: StandardSchemaV1.InferInput<\n TNewConfigSchema[key]\n >;\n };\n output: UOutput extends ExtensionDataRef<\n infer IData,\n infer IId,\n infer IConfig\n >\n ? ExtensionDataRef<IData, IId, IConfig>\n : never;\n inputs: TInputs;\n params: never;\n kind: string | undefined extends TKind ? undefined : TKind;\n name: string | undefined extends TName ? undefined : TName;\n}>;\n\n/** @internal */\nexport function createExtension(\n options: any,\n): OverridableExtensionDefinition<any> {\n assertNoLegacyConfigSchema(options);\n\n const resolvedConfigSchema = options.configSchema\n ? createConfigSchema(options.configSchema)\n : undefined;\n\n return OpaqueExtensionDefinition.createInstance('v2', {\n T: undefined as any,\n kind: options.kind,\n name: options.name,\n attachTo: options.attachTo,\n disabled: options.disabled ?? false,\n if: options.if,\n inputs: bindInputs(options.inputs, options.kind, options.name),\n output: options.output,\n configSchema: resolvedConfigSchema,\n factory: options.factory,\n toString() {\n const parts: string[] = [];\n if (options.kind) {\n parts.push(`kind=${options.kind}`);\n }\n if (options.name) {\n parts.push(`name=${options.name}`);\n }\n const attachTo = [options.attachTo]\n .flat()\n .map(aAny => {\n const a = aAny as ExtensionDefinitionAttachTo;\n if (OpaqueExtensionInput.isType(a)) {\n const { context } = OpaqueExtensionInput.toInternal(a);\n if (!context) {\n return '<detached-input>';\n }\n let id = '<plugin>';\n if (context?.kind) {\n id = `${context?.kind}:${id}`;\n }\n if (context?.name) {\n id = `${id}/${context?.name}`;\n }\n return `${id}@${context.input}`;\n }\n if ('relative' in a && a.relative) {\n let id = '<plugin>';\n if (a.relative.kind) {\n id = `${a.relative.kind}:${id}`;\n }\n if (a.relative.name) {\n id = `${id}/${a.relative.name}`;\n }\n return `${id}@${a.input}`;\n }\n if ('id' in a) {\n return `${a.id}@${a.input}`;\n }\n throw new Error('Invalid attachment point specification');\n })\n .join('+');\n parts.push(`attachTo=${attachTo}`);\n return `ExtensionDefinition{${parts.join(',')}}`;\n },\n override(overrideOptions: any) {\n assertNoLegacyConfigSchema(overrideOptions);\n\n if (!Array.isArray(options.output)) {\n throw new Error(\n 'Cannot override an extension that is not declared using the new format with outputs as an array',\n );\n }\n\n // TODO(Rugvip): Making this a type check would be optimal, but it seems\n // like it's tricky to add that and still have the type\n // inference work correctly for the factory output.\n if (overrideOptions.output && !overrideOptions.factory) {\n throw new Error(\n 'Refused to override output without also overriding factory',\n );\n }\n // TODO(Rugvip): Similar to above, would be nice to error during type checking, but don't want to complicate the types too much\n if (overrideOptions.params && overrideOptions.factory) {\n throw new Error(\n 'Refused to override params and factory at the same time',\n );\n }\n\n let ifPredicate = options.if;\n if ('if' in overrideOptions) {\n ifPredicate = overrideOptions.if;\n }\n\n return createExtension({\n kind: options.kind,\n name: options.name,\n attachTo: (overrideOptions.attachTo ??\n options.attachTo) as ExtensionDefinitionAttachTo,\n disabled: overrideOptions.disabled ?? options.disabled,\n if: ifPredicate,\n inputs: bindInputs(\n {\n ...(options.inputs ?? {}),\n ...(overrideOptions.inputs ?? {}),\n },\n options.kind,\n options.name,\n ),\n output: (overrideOptions.output ??\n options.output) as ExtensionDataRef[],\n configSchema:\n options.configSchema || overrideOptions.configSchema\n ? {\n ...options.configSchema,\n ...overrideOptions.configSchema,\n }\n : undefined,\n factory: ({ node, apis, config, inputs }) => {\n if (!overrideOptions.factory) {\n return options.factory({\n node,\n apis,\n config: config as any,\n inputs: inputs as any,\n [ctxParamsSymbol as any]: overrideOptions.params,\n });\n }\n const parentResult = overrideOptions.factory(\n (innerContext: any): ExtensionDataContainer<any> => {\n return createExtensionDataContainer<any>(\n options.factory({\n node,\n apis,\n config: (innerContext?.config ?? config) as any,\n inputs: resolveInputOverrides(\n options.inputs,\n inputs,\n innerContext?.inputs,\n ) as any,\n [ctxParamsSymbol as any]: innerContext?.params,\n }) as Iterable<any>,\n 'original extension factory',\n options.output,\n );\n },\n {\n node,\n apis,\n config: config as any,\n inputs: inputs as any,\n },\n );\n\n if (\n typeof parentResult !== 'object' ||\n !parentResult?.[Symbol.iterator]\n ) {\n throw new Error(\n 'extension factory override did not provide an iterable object',\n );\n }\n\n const deduplicatedResult = new Map<\n string,\n ExtensionDataValue<any, any>\n >();\n for (const item of parentResult) {\n deduplicatedResult.set(item.id, item);\n }\n\n return deduplicatedResult.values();\n },\n }) as OverridableExtensionDefinition<any>;\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createExtensionBlueprint.esm.js","sources":["../../src/wiring/createExtensionBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { ApiHolder, AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport { OpaqueType } from '@internal/opaque';\nimport {\n ExtensionDefinitionAttachTo,\n OverridableExtensionDefinition,\n ResolvedExtensionInputs,\n VerifyExtensionFactoryOutput,\n createExtension,\n ctxParamsSymbol,\n VerifyExtensionAttachTo,\n} from './createExtension';\nimport { ExtensionInput } from './createExtensionInput';\nimport { type StandardSchemaV1 } from '@standard-schema/spec';\nimport { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef';\nimport { createExtensionDataContainer } from '@internal/frontend';\nimport {\n ResolvedInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\nimport { ExtensionDataContainer } from './types';\nimport { PageBlueprint } from '../blueprints/PageBlueprint';\nimport { FilterPredicate } from '@backstage/filter-predicates';\nimport { assertNoLegacyConfigSchema } from '../schema/assertNoLegacyConfigSchema';\n\n/**\n * A function used to define a parameter mapping function in order to facilitate\n * advanced parameter typing for extension blueprints.\n *\n * @remarks\n *\n * This function is primarily intended to enable the use of inferred type\n * parameters for blueprint params, but it can also be used to transform the\n * params before they are handed to the blueprint.\n *\n * The function must return an object created with\n * {@link createExtensionBlueprintParams}.\n *\n * @public\n */\nexport type ExtensionBlueprintDefineParams<\n TParams extends object = object,\n TInput = any,\n> = (params: TInput) => ExtensionBlueprintParams<TParams>;\n\n/**\n * An opaque type that represents a set of parameters to be passed to a blueprint.\n *\n * @remarks\n *\n * Created with {@link createExtensionBlueprintParams}.\n *\n * @public\n */\nexport type ExtensionBlueprintParams<T extends object = object> = {\n $$type: '@backstage/BlueprintParams';\n T: T;\n};\n\nconst OpaqueBlueprintParams = OpaqueType.create<{\n public: ExtensionBlueprintParams;\n versions: {\n version: 'v1';\n params: object;\n };\n}>({\n type: '@backstage/BlueprintParams',\n versions: ['v1'],\n});\n\n/**\n * Wraps a plain blueprint parameter object in an opaque {@link ExtensionBlueprintParams} object.\n *\n * This is used in the definition of the `defineParams` option of {@link ExtensionBlueprint}.\n *\n * @public\n * @param params - The plain blueprint parameter object to wrap.\n * @returns The wrapped blueprint parameter object.\n */\nexport function createExtensionBlueprintParams<T extends object = object>(\n params: T,\n): ExtensionBlueprintParams<T> {\n return OpaqueBlueprintParams.createInstance('v1', { T: null as any, params });\n}\n\n/**\n * @public\n */\nexport type CreateExtensionBlueprintOptions<\n TKind extends string,\n TParams extends object | ExtensionBlueprintDefineParams,\n UOutput extends ExtensionDataRef,\n TInputs extends { [inputName in string]: ExtensionInput },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n TDataRefs extends { [name in string]: ExtensionDataRef },\n UParentInputs extends ExtensionDataRef,\n TNewConfigSchema extends { [key in string]: StandardSchemaV1 } = {},\n> = {\n kind: TKind;\n attachTo: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<UOutput, UParentInputs>;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TInputs;\n output: Array<UOutput>;\n configSchema?: TNewConfigSchema;\n /**\n * This option is used to further refine the blueprint params. When this\n * option is used, the blueprint will require params to be passed in callback\n * form. This function can both transform the params before they are handed to\n * the blueprint factory, but importantly it also allows you to define\n * inferred type parameters for your blueprint params.\n *\n * @example\n * Blueprint definition with inferred type parameters:\n * ```ts\n * const ExampleBlueprint = createExtensionBlueprint({\n * kind: 'example',\n * attachTo: { id: 'example', input: 'example' },\n * output: [exampleComponentDataRef, exampleFetcherDataRef],\n * defineParams<T>(params: {\n * component(props: ExampleProps<T>): JSX.Element | null\n * fetcher(options: FetchOptions): Promise<FetchResult<T>>\n * }) {\n * return createExtensionBlueprintParams(params);\n * },\n * *factory(params) {\n * yield exampleComponentDataRef(params.component)\n * yield exampleFetcherDataRef(params.fetcher)\n * },\n * });\n * ```\n *\n * @example\n * Usage of the above example blueprint:\n * ```ts\n * const example = ExampleBlueprint.make({\n * params: defineParams => defineParams({\n * component: ...,\n * fetcher: ...,\n * }),\n * });\n * ```\n */\n defineParams?: TParams extends ExtensionBlueprintDefineParams\n ? TParams\n : 'The defineParams option must be a function if provided, see the docs for details';\n factory(\n params: TParams extends ExtensionBlueprintDefineParams\n ? ReturnType<TParams>['T']\n : TParams,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n\n dataRefs?: TDataRefs;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport type ExtensionBlueprintParameters = {\n kind: string;\n params?: object | ExtensionBlueprintDefineParams;\n configInput?: { [K in string]: any };\n config?: { [K in string]: any };\n output?: ExtensionDataRef;\n inputs?: { [KName in string]: ExtensionInput };\n dataRefs?: { [name in string]: ExtensionDataRef };\n};\n\n/** @ignore */\ntype ParamsFactory<TDefiner extends ExtensionBlueprintDefineParams> = (\n defineParams: TDefiner,\n) => ReturnType<TDefiner>;\n\n/**\n * Represents any form of params input that can be passed to a blueprint.\n * This also includes the invalid form of passing a plain params object to a blueprint that uses a definition callback.\n *\n * @ignore\n */\ntype AnyParamsInput<TParams extends object | ExtensionBlueprintDefineParams> =\n TParams extends ExtensionBlueprintDefineParams<infer IParams>\n ? IParams | ParamsFactory<TParams>\n : TParams | ParamsFactory<ExtensionBlueprintDefineParams<TParams, TParams>>;\n\n/**\n * @public\n */\nexport interface ExtensionBlueprint<\n T extends ExtensionBlueprintParameters = ExtensionBlueprintParameters,\n> {\n dataRefs: T['dataRefs'];\n\n make<\n TName extends string | undefined,\n TParamsInput extends AnyParamsInput<NonNullable<T['params']>>,\n UParentInputs extends ExtensionDataRef,\n >(args: {\n name?: TName;\n attachTo?: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<NonNullable<T['output']>, UParentInputs>;\n disabled?: boolean;\n if?: FilterPredicate;\n params: TParamsInput extends ExtensionBlueprintDefineParams\n ? TParamsInput\n : T['params'] extends ExtensionBlueprintDefineParams\n ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `<blueprint>.make({ params: defineParams => defineParams(<params>) })`'\n : T['params'];\n }): OverridableExtensionDefinition<{\n kind: T['kind'];\n name: string | undefined extends TName ? undefined : TName;\n config: T['config'];\n configInput: T['configInput'];\n output: T['output'];\n inputs: T['inputs'];\n params: T['params'];\n }>;\n\n /**\n * Creates a new extension from the blueprint.\n *\n * You must either pass `params` directly, or define a `factory` that can\n * optionally call the original factory with the same params.\n */\n makeWithOverrides<\n TName extends string | undefined,\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends ExtensionDataRef,\n UParentInputs extends ExtensionDataRef,\n TExtraInputs extends { [inputName in string]: ExtensionInput } = {},\n TNewExtensionConfigSchema extends {\n [key in string]: StandardSchemaV1;\n } = {},\n >(args: {\n name?: TName;\n attachTo?: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<\n ExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UParentInputs\n >;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TExtraInputs & {\n [KName in keyof T['inputs']]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: never;\n configSchema?: TNewExtensionConfigSchema & {\n [KName in keyof T['config']]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n factory(\n originalFactory: <\n TParamsInput extends AnyParamsInput<NonNullable<T['params']>>,\n >(\n params: TParamsInput extends ExtensionBlueprintDefineParams\n ? TParamsInput\n : T['params'] extends ExtensionBlueprintDefineParams\n ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams(<params>))`'\n : T['params'],\n context?: {\n config?: T['config'];\n inputs?: ResolvedInputValueOverrides<NonNullable<T['inputs']>>;\n },\n ) => ExtensionDataContainer<NonNullable<T['output']>>,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: T['config'] & {\n [key in keyof TNewExtensionConfigSchema]: StandardSchemaV1.InferOutput<\n TNewExtensionConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput> &\n VerifyExtensionFactoryOutput<\n ExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UFactoryOutput\n >;\n }): OverridableExtensionDefinition<{\n config: Expand<\n {\n [key in keyof TNewExtensionConfigSchema]: StandardSchemaV1.InferOutput<\n TNewExtensionConfigSchema[key]\n >;\n } & T['config']\n >;\n configInput: Expand<\n {\n [key in keyof TNewExtensionConfigSchema]?: StandardSchemaV1.InferInput<\n TNewExtensionConfigSchema[key]\n >;\n } & T['configInput']\n >;\n output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;\n inputs: Expand<T['inputs'] & TExtraInputs>;\n kind: T['kind'];\n name: string | undefined extends TName ? undefined : TName;\n params: T['params'];\n }>;\n}\n\nfunction unwrapParamsFactory<TParams extends object>(\n // Allow `Function` because `typeof <object> === 'function'` allows it, but in practice this should always be a param factory\n params: ParamsFactory<ExtensionBlueprintDefineParams> | Function,\n defineParams: ExtensionBlueprintDefineParams,\n kind: string,\n): TParams {\n const paramDefinition = (\n params as ParamsFactory<ExtensionBlueprintDefineParams>\n )(defineParams);\n try {\n return OpaqueBlueprintParams.toInternal(paramDefinition).params as TParams;\n } catch (e) {\n throw new TypeError(\n `Invalid invocation of blueprint with kind '${kind}', the parameter definition callback function did not return a valid parameter definition object; Caused by: ${e.message}`,\n );\n }\n}\n\nfunction unwrapParams<TParams extends object>(\n params: object | ParamsFactory<ExtensionBlueprintDefineParams> | string,\n ctx: { node: AppNode; [ctxParamsSymbol]?: any },\n defineParams: ExtensionBlueprintDefineParams | undefined,\n kind: string,\n): TParams {\n const overrideParams = ctx[ctxParamsSymbol] as\n | object\n | ParamsFactory<ExtensionBlueprintDefineParams>\n | undefined;\n\n if (defineParams) {\n if (overrideParams) {\n if (typeof overrideParams !== 'function') {\n throw new TypeError(\n `Invalid extension override of blueprint with kind '${kind}', the override params were passed as a plain object, but this blueprint requires them to be passed in callback form`,\n );\n }\n return unwrapParamsFactory(overrideParams, defineParams, kind);\n }\n\n if (typeof params !== 'function') {\n throw new TypeError(\n `Invalid invocation of blueprint with kind '${kind}', the parameters where passed as a plain object, but this blueprint requires them to be passed in callback form`,\n );\n }\n return unwrapParamsFactory(params, defineParams, kind);\n }\n\n const base =\n typeof params === 'function'\n ? unwrapParamsFactory<TParams>(\n params,\n createExtensionBlueprintParams,\n kind,\n )\n : (params as TParams);\n const overrides =\n typeof overrideParams === 'function'\n ? unwrapParamsFactory<TParams>(\n overrideParams,\n createExtensionBlueprintParams,\n kind,\n )\n : (overrideParams as Partial<TParams>);\n\n return {\n ...base,\n ...overrides,\n };\n}\n\n/**\n * Creates a new extension blueprint that encapsulates the creation of\n * extensions of particular kinds.\n *\n * @remarks\n *\n * For details on how blueprints work, see the\n * {@link https://backstage.io/docs/frontend-system/architecture/extension-blueprints | documentation for extension blueprints}\n * in the frontend system documentation.\n *\n * Extension blueprints make it much easier for users to create new extensions\n * for your plugin. Rather than letting them use `createExtension`\n * directly, you can define a set of parameters and default factory for your\n * blueprint, removing a lot of the boilerplate and complexity that is otherwise\n * needed to create an extension.\n *\n * Each blueprint has its own `kind` that helps identify and group the\n * extensions that have been created with it. For example the\n * {@link PageBlueprint} has the kind `'page'`, and extensions created with it\n * will be given the ID `'page:<plugin-id>[/<name>]'`. Blueprints should always\n * be exported as `<PascalCaseKind>Blueprint`.\n *\n * When creating a blueprint the type of the parameters are inferred from the\n * `factory` function that you provide. The exception to that is when you need\n * your blueprint to include inferred type parameters, in which case you need to\n * use the `defineParams` option. See the documentation for the `defineParams`\n * option for more details on how that works.\n *\n * @example\n * ```tsx\n * // In your plugin library\n * export const GreetingBlueprint = createExtensionBlueprint({\n * kind: 'greeting',\n * attachTo: { id: 'example', input: 'greetings' },\n * output: [coreExtensionData.reactElement],\n * factory(params: { greeting: string }) {\n * return [coreExtensionData.reactElement(<h1>{params.greeting}</h1>)];\n * },\n * });\n *\n * // Someone using your blueprint in their plugin\n * const exampleGreeting = GreetingBlueprint.make({\n * params: {\n * greeting: 'Hello, world!',\n * },\n * });\n * ```\n * @public\n */\nexport function createExtensionBlueprint<\n TParams extends object | ExtensionBlueprintDefineParams,\n UOutput extends ExtensionDataRef,\n TInputs extends { [inputName in string]: ExtensionInput },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n TKind extends string,\n UParentInputs extends ExtensionDataRef,\n TDataRefs extends { [name in string]: ExtensionDataRef } = never,\n TNewConfigSchema extends { [key in string]: StandardSchemaV1 } = {},\n>(\n options: {\n kind: TKind;\n attachTo: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<UOutput, UParentInputs>;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TInputs;\n output: Array<UOutput>;\n configSchema?: TNewConfigSchema;\n defineParams?: TParams extends ExtensionBlueprintDefineParams\n ? TParams\n : 'The defineParams option must be a function if provided, see the docs for details';\n factory(\n params: TParams extends ExtensionBlueprintDefineParams\n ? ReturnType<TParams>['T']\n : TParams,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n dataRefs?: TDataRefs;\n } & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>,\n): ExtensionBlueprint<{\n kind: TKind;\n params: TParams;\n output: UOutput extends ExtensionDataRef<\n infer IData,\n infer IId,\n infer IConfig\n >\n ? ExtensionDataRef<IData, IId, IConfig>\n : never;\n inputs: string extends keyof TInputs ? {} : TInputs;\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n configInput: {\n [key in keyof TNewConfigSchema]?: StandardSchemaV1.InferInput<\n TNewConfigSchema[key]\n >;\n };\n dataRefs: TDataRefs;\n}>;\n\n/** @internal */\nexport function createExtensionBlueprint(options: any): any {\n assertNoLegacyConfigSchema(options);\n\n const defineParams = options.defineParams as\n | ExtensionBlueprintDefineParams\n | undefined;\n\n return {\n dataRefs: options.dataRefs,\n make(args) {\n return createExtension({\n kind: options.kind,\n name: args.name,\n attachTo: (args.attachTo ??\n options.attachTo) as ExtensionDefinitionAttachTo,\n disabled: args.disabled ?? options.disabled,\n if: args.if ?? options.if,\n inputs: options.inputs,\n output: options.output as ExtensionDataRef[],\n configSchema: options.configSchema as any,\n factory: ctx =>\n options.factory(\n unwrapParams(args.params, ctx, defineParams, options.kind),\n ctx as any,\n ) as Iterable<ExtensionDataValue<any, any>>,\n }) as OverridableExtensionDefinition;\n },\n makeWithOverrides(args: any) {\n assertNoLegacyConfigSchema(args);\n\n return createExtension({\n kind: options.kind,\n name: args.name,\n attachTo: (args.attachTo ??\n options.attachTo) as ExtensionDefinitionAttachTo,\n disabled: args.disabled ?? options.disabled,\n if: args.if ?? options.if,\n inputs: { ...args.inputs, ...options.inputs },\n output: (args.output ?? options.output) as ExtensionDataRef[],\n configSchema:\n options.configSchema || args.configSchema\n ? {\n ...options.configSchema,\n ...args.configSchema,\n }\n : (undefined as any),\n factory: ctx => {\n const { node, config, inputs, apis } = ctx;\n return args.factory(\n (innerParams: any, innerContext: any) => {\n return createExtensionDataContainer<any>(\n options.factory(\n unwrapParams(innerParams, ctx, defineParams, options.kind),\n {\n apis,\n node,\n config: (innerContext?.config ?? config) as any,\n inputs: resolveInputOverrides(\n options.inputs,\n inputs,\n innerContext?.inputs,\n ) as any,\n },\n ) as Iterable<any>,\n 'original blueprint factory',\n options.output,\n );\n },\n {\n apis,\n node,\n config: config as any,\n inputs: inputs as any,\n },\n ) as Iterable<ExtensionDataValue<any, any>>;\n },\n }) as OverridableExtensionDefinition;\n },\n } as ExtensionBlueprint<any>;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createExtensionBlueprint.esm.js","sources":["../../src/wiring/createExtensionBlueprint.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { ApiHolder, AppNode } from '../apis';\nimport { Expand } from '@backstage/types';\nimport { OpaqueType } from '@internal/opaque';\nimport {\n ExtensionDefinitionAttachTo,\n OverridableExtensionDefinition,\n ResolvedExtensionInputs,\n VerifyExtensionFactoryOutput,\n createExtension,\n ctxParamsSymbol,\n VerifyExtensionAttachTo,\n} from './createExtension';\nimport { ExtensionInput } from './createExtensionInput';\nimport { type StandardSchemaV1 } from '@standard-schema/spec';\nimport { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef';\nimport { createExtensionDataContainer } from '@internal/frontend';\nimport {\n ResolvedInputValueOverrides,\n resolveInputOverrides,\n} from './resolveInputOverrides';\nimport { ExtensionDataContainer } from './types';\nimport { PageBlueprint } from '../blueprints/PageBlueprint';\nimport { FilterPredicate } from '@backstage/filter-predicates';\nimport { assertNoLegacyConfigSchema } from '../schema/assertNoLegacyConfigSchema';\n\n/**\n * A function used to define a parameter mapping function in order to facilitate\n * advanced parameter typing for extension blueprints.\n *\n * @remarks\n *\n * This function is primarily intended to enable the use of inferred type\n * parameters for blueprint params, but it can also be used to transform the\n * params before they are handed to the blueprint.\n *\n * The function must return an object created with\n * {@link createExtensionBlueprintParams}.\n *\n * @public\n */\nexport type ExtensionBlueprintDefineParams<\n TParams extends object = object,\n TInput = any,\n> = (params: TInput) => ExtensionBlueprintParams<TParams>;\n\n/**\n * An opaque type that represents a set of parameters to be passed to a blueprint.\n *\n * @remarks\n *\n * Created with {@link createExtensionBlueprintParams}.\n *\n * @public\n */\nexport type ExtensionBlueprintParams<T extends object = object> = {\n $$type: '@backstage/BlueprintParams';\n T: T;\n};\n\nconst OpaqueBlueprintParams = OpaqueType.create<{\n public: ExtensionBlueprintParams;\n versions: {\n version: 'v1';\n params: object;\n };\n}>({\n type: '@backstage/BlueprintParams',\n versions: ['v1'],\n});\n\n/**\n * Wraps a plain blueprint parameter object in an opaque {@link ExtensionBlueprintParams} object.\n *\n * This is used in the definition of the `defineParams` option of {@link ExtensionBlueprint}.\n *\n * @public\n * @param params - The plain blueprint parameter object to wrap.\n * @returns The wrapped blueprint parameter object.\n */\nexport function createExtensionBlueprintParams<T extends object = object>(\n params: T,\n): ExtensionBlueprintParams<T> {\n return OpaqueBlueprintParams.createInstance('v1', { T: null as any, params });\n}\n\n/**\n * @public\n */\nexport type CreateExtensionBlueprintOptions<\n TKind extends string,\n TParams extends object | ExtensionBlueprintDefineParams,\n UOutput extends ExtensionDataRef,\n TInputs extends { [inputName in string]: ExtensionInput },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n TDataRefs extends { [name in string]: ExtensionDataRef },\n UParentInputs extends ExtensionDataRef,\n TNewConfigSchema extends { [key in string]: StandardSchemaV1 } = {},\n> = {\n kind: TKind;\n attachTo: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<UOutput, UParentInputs>;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TInputs;\n output: Array<UOutput>;\n configSchema?: TNewConfigSchema;\n /**\n * This option is used to further refine the blueprint params. When this\n * option is used, the blueprint will require params to be passed in callback\n * form. This function can both transform the params before they are handed to\n * the blueprint factory, but importantly it also allows you to define\n * inferred type parameters for your blueprint params.\n *\n * @example\n * Blueprint definition with inferred type parameters:\n * ```ts\n * const ExampleBlueprint = createExtensionBlueprint({\n * kind: 'example',\n * attachTo: { id: 'example', input: 'example' },\n * output: [exampleComponentDataRef, exampleFetcherDataRef],\n * defineParams<T>(params: {\n * component(props: ExampleProps<T>): JSX.Element | null\n * fetcher(options: FetchOptions): Promise<FetchResult<T>>\n * }) {\n * return createExtensionBlueprintParams(params);\n * },\n * *factory(params) {\n * yield exampleComponentDataRef(params.component)\n * yield exampleFetcherDataRef(params.fetcher)\n * },\n * });\n * ```\n *\n * @example\n * Usage of the above example blueprint:\n * ```ts\n * const example = ExampleBlueprint.make({\n * params: defineParams => defineParams({\n * component: ...,\n * fetcher: ...,\n * }),\n * });\n * ```\n */\n defineParams?: TParams extends ExtensionBlueprintDefineParams\n ? TParams\n : 'The defineParams option must be a function if provided, see the docs for details';\n factory(\n params: TParams extends ExtensionBlueprintDefineParams\n ? ReturnType<TParams>['T']\n : TParams,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n\n dataRefs?: TDataRefs;\n} & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>;\n\n/** @public */\nexport type ExtensionBlueprintParameters = {\n kind: string;\n params?: object | ExtensionBlueprintDefineParams;\n configInput?: { [K in string]: any };\n config?: { [K in string]: any };\n output?: ExtensionDataRef;\n inputs?: { [KName in string]: ExtensionInput };\n dataRefs?: { [name in string]: ExtensionDataRef };\n};\n\n/** @ignore */\ntype ParamsFactory<TDefiner extends ExtensionBlueprintDefineParams> = (\n defineParams: TDefiner,\n) => ReturnType<TDefiner>;\n\n/**\n * Represents any form of params input that can be passed to a blueprint.\n * This also includes the invalid form of passing a plain params object to a blueprint that uses a definition callback.\n *\n * @ignore\n */\ntype AnyParamsInput<TParams extends object | ExtensionBlueprintDefineParams> =\n TParams extends ExtensionBlueprintDefineParams<infer IParams>\n ? IParams | ParamsFactory<TParams>\n : TParams | ParamsFactory<ExtensionBlueprintDefineParams<TParams, TParams>>;\n\n/**\n * @public\n */\nexport interface ExtensionBlueprint<\n T extends ExtensionBlueprintParameters = ExtensionBlueprintParameters,\n> {\n dataRefs: T['dataRefs'];\n\n make<\n TName extends string | undefined,\n TParamsInput extends AnyParamsInput<NonNullable<T['params']>>,\n UParentInputs extends ExtensionDataRef,\n >(args: {\n name?: TName;\n attachTo?: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<NonNullable<T['output']>, UParentInputs>;\n disabled?: boolean;\n if?: FilterPredicate;\n params: TParamsInput extends ExtensionBlueprintDefineParams\n ? TParamsInput\n : T['params'] extends ExtensionBlueprintDefineParams\n ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `<blueprint>.make({ params: defineParams => defineParams(<params>) })`'\n : T['params'];\n }): OverridableExtensionDefinition<{\n kind: T['kind'];\n name: string | undefined extends TName ? undefined : TName;\n config: T['config'];\n configInput: T['configInput'];\n output: T['output'];\n inputs: T['inputs'];\n params: T['params'];\n }>;\n\n /**\n * Creates a new extension from the blueprint.\n *\n * You must either pass `params` directly, or define a `factory` that can\n * optionally call the original factory with the same params.\n */\n makeWithOverrides<\n TName extends string | undefined,\n UFactoryOutput extends ExtensionDataValue<any, any>,\n UNewOutput extends ExtensionDataRef,\n UParentInputs extends ExtensionDataRef,\n TExtraInputs extends { [inputName in string]: ExtensionInput } = {},\n TNewExtensionConfigSchema extends {\n [key in string]: StandardSchemaV1;\n } = {},\n >(args: {\n name?: TName;\n attachTo?: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<\n ExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UParentInputs\n >;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TExtraInputs & {\n [KName in keyof T['inputs']]?: `Error: Input '${KName &\n string}' is already defined in parent definition`;\n };\n output?: Array<UNewOutput>;\n config?: never;\n configSchema?: TNewExtensionConfigSchema & {\n [KName in keyof T['config']]?: `Error: Config key '${KName &\n string}' is already defined in parent schema`;\n };\n factory(\n originalFactory: <\n TParamsInput extends AnyParamsInput<NonNullable<T['params']>>,\n >(\n params: TParamsInput extends ExtensionBlueprintDefineParams\n ? TParamsInput\n : T['params'] extends ExtensionBlueprintDefineParams\n ? 'Error: This blueprint uses advanced parameter types and requires you to pass parameters as using the following callback syntax: `originalFactory(defineParams => defineParams(<params>))`'\n : T['params'],\n context?: {\n config?: T['config'];\n inputs?: ResolvedInputValueOverrides<NonNullable<T['inputs']>>;\n },\n ) => ExtensionDataContainer<NonNullable<T['output']>>,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: T['config'] & {\n [key in keyof TNewExtensionConfigSchema]: StandardSchemaV1.InferOutput<\n TNewExtensionConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<T['inputs'] & TExtraInputs>>;\n },\n ): Iterable<UFactoryOutput> &\n VerifyExtensionFactoryOutput<\n ExtensionDataRef extends UNewOutput\n ? NonNullable<T['output']>\n : UNewOutput,\n UFactoryOutput\n >;\n }): OverridableExtensionDefinition<{\n config: Expand<\n {\n [key in keyof TNewExtensionConfigSchema]: StandardSchemaV1.InferOutput<\n TNewExtensionConfigSchema[key]\n >;\n } & T['config']\n >;\n configInput: Expand<\n {\n [key in keyof TNewExtensionConfigSchema]?: StandardSchemaV1.InferInput<\n TNewExtensionConfigSchema[key]\n >;\n } & T['configInput']\n >;\n output: ExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput;\n inputs: Expand<T['inputs'] & TExtraInputs>;\n kind: T['kind'];\n name: string | undefined extends TName ? undefined : TName;\n params: T['params'];\n }>;\n}\n\nfunction unwrapParamsFactory<TParams extends object>(\n // Allow `Function` because `typeof <object> === 'function'` allows it, but in practice this should always be a param factory\n params: ParamsFactory<ExtensionBlueprintDefineParams> | Function,\n defineParams: ExtensionBlueprintDefineParams,\n kind: string,\n): TParams {\n const paramDefinition = (\n params as ParamsFactory<ExtensionBlueprintDefineParams>\n )(defineParams);\n try {\n return OpaqueBlueprintParams.toInternal(paramDefinition).params as TParams;\n } catch (e) {\n throw new TypeError(\n `Invalid invocation of blueprint with kind '${kind}', the parameter definition callback function did not return a valid parameter definition object; Caused by: ${e.message}`,\n );\n }\n}\n\nfunction unwrapParams<TParams extends object>(\n params: object | ParamsFactory<ExtensionBlueprintDefineParams> | string,\n ctx: { node: AppNode; [ctxParamsSymbol]?: any },\n defineParams: ExtensionBlueprintDefineParams | undefined,\n kind: string,\n): TParams {\n const overrideParams = ctx[ctxParamsSymbol] as\n | object\n | ParamsFactory<ExtensionBlueprintDefineParams>\n | undefined;\n\n if (defineParams) {\n if (overrideParams) {\n if (typeof overrideParams !== 'function') {\n throw new TypeError(\n `Invalid extension override of blueprint with kind '${kind}', the override params were passed as a plain object, but this blueprint requires them to be passed in callback form`,\n );\n }\n return unwrapParamsFactory(overrideParams, defineParams, kind);\n }\n\n if (typeof params !== 'function') {\n throw new TypeError(\n `Invalid invocation of blueprint with kind '${kind}', the parameters where passed as a plain object, but this blueprint requires them to be passed in callback form`,\n );\n }\n return unwrapParamsFactory(params, defineParams, kind);\n }\n\n const base =\n typeof params === 'function'\n ? unwrapParamsFactory<TParams>(\n params,\n createExtensionBlueprintParams,\n kind,\n )\n : (params as TParams);\n const overrides =\n typeof overrideParams === 'function'\n ? unwrapParamsFactory<TParams>(\n overrideParams,\n createExtensionBlueprintParams,\n kind,\n )\n : (overrideParams as Partial<TParams>);\n\n return {\n ...base,\n ...overrides,\n };\n}\n\n/**\n * Creates a new extension blueprint that encapsulates the creation of\n * extensions of particular kinds.\n *\n * @remarks\n *\n * For details on how blueprints work, see the\n * {@link https://backstage.io/docs/frontend-system/architecture/extension-blueprints | documentation for extension blueprints}\n * in the frontend system documentation.\n *\n * Extension blueprints make it much easier for users to create new extensions\n * for your plugin. Rather than letting them use `createExtension`\n * directly, you can define a set of parameters and default factory for your\n * blueprint, removing a lot of the boilerplate and complexity that is otherwise\n * needed to create an extension.\n *\n * Each blueprint has its own `kind` that helps identify and group the\n * extensions that have been created with it. For example the\n * {@link PageBlueprint} has the kind `'page'`, and extensions created with it\n * will be given the ID `'page:<plugin-id>[/<name>]'`. Blueprints should always\n * be exported as `<PascalCaseKind>Blueprint`.\n *\n * When creating a blueprint the type of the parameters are inferred from the\n * `factory` function that you provide. The exception to that is when you need\n * your blueprint to include inferred type parameters, in which case you need to\n * use the `defineParams` option. See the documentation for the `defineParams`\n * option for more details on how that works.\n *\n * @example\n * ```tsx\n * // In your plugin library\n * export const GreetingBlueprint = createExtensionBlueprint({\n * kind: 'greeting',\n * attachTo: { id: 'example', input: 'greetings' },\n * output: [coreExtensionData.reactElement],\n * factory(params: { greeting: string }) {\n * return [coreExtensionData.reactElement(<h1>{params.greeting}</h1>)];\n * },\n * });\n *\n * // Someone using your blueprint in their plugin\n * const exampleGreeting = GreetingBlueprint.make({\n * params: {\n * greeting: 'Hello, world!',\n * },\n * });\n * ```\n * @public\n */\nexport function createExtensionBlueprint<\n TParams extends object | ExtensionBlueprintDefineParams,\n UOutput extends ExtensionDataRef,\n TInputs extends { [inputName in string]: ExtensionInput },\n UFactoryOutput extends ExtensionDataValue<any, any>,\n TKind extends string,\n UParentInputs extends ExtensionDataRef,\n TDataRefs extends { [name in string]: ExtensionDataRef } = never,\n TNewConfigSchema extends { [key in string]: StandardSchemaV1 } = {},\n>(\n options: {\n kind: TKind;\n attachTo: ExtensionDefinitionAttachTo<UParentInputs> &\n VerifyExtensionAttachTo<UOutput, UParentInputs>;\n disabled?: boolean;\n if?: FilterPredicate;\n inputs?: TInputs;\n output: Array<UOutput>;\n configSchema?: TNewConfigSchema;\n defineParams?: TParams extends ExtensionBlueprintDefineParams\n ? TParams\n : 'The defineParams option must be a function if provided, see the docs for details';\n factory(\n params: TParams extends ExtensionBlueprintDefineParams\n ? ReturnType<TParams>['T']\n : TParams,\n context: {\n node: AppNode;\n apis: ApiHolder;\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n inputs: Expand<ResolvedExtensionInputs<TInputs>>;\n },\n ): Iterable<UFactoryOutput>;\n dataRefs?: TDataRefs;\n } & VerifyExtensionFactoryOutput<UOutput, UFactoryOutput>,\n): ExtensionBlueprint<{\n kind: TKind;\n params: TParams;\n output: UOutput extends ExtensionDataRef<\n infer IData,\n infer IId,\n infer IConfig\n >\n ? ExtensionDataRef<IData, IId, IConfig>\n : never;\n inputs: string extends keyof TInputs ? {} : TInputs;\n config: {\n [key in keyof TNewConfigSchema]: StandardSchemaV1.InferOutput<\n TNewConfigSchema[key]\n >;\n };\n configInput: {\n [key in keyof TNewConfigSchema]?: StandardSchemaV1.InferInput<\n TNewConfigSchema[key]\n >;\n };\n dataRefs: TDataRefs;\n}>;\n\n/** @internal */\nexport function createExtensionBlueprint(options: any): any {\n assertNoLegacyConfigSchema(options);\n\n const defineParams = options.defineParams as\n | ExtensionBlueprintDefineParams\n | undefined;\n\n return {\n dataRefs: options.dataRefs,\n make(args) {\n return createExtension({\n kind: options.kind,\n name: args.name,\n attachTo: (args.attachTo ??\n options.attachTo) as ExtensionDefinitionAttachTo,\n disabled: args.disabled ?? options.disabled,\n if: args.if ?? options.if,\n inputs: options.inputs,\n output: options.output as ExtensionDataRef[],\n configSchema: options.configSchema as any,\n factory: ctx =>\n options.factory(\n unwrapParams(args.params, ctx, defineParams, options.kind),\n ctx as any,\n ) as Iterable<ExtensionDataValue<any, any>>,\n }) as OverridableExtensionDefinition;\n },\n makeWithOverrides(args: any) {\n assertNoLegacyConfigSchema(args);\n\n return createExtension({\n kind: options.kind,\n name: args.name,\n attachTo: (args.attachTo ??\n options.attachTo) as ExtensionDefinitionAttachTo,\n disabled: args.disabled ?? options.disabled,\n if: args.if ?? options.if,\n inputs: { ...args.inputs, ...options.inputs },\n output: (args.output ?? options.output) as ExtensionDataRef[],\n configSchema:\n options.configSchema || args.configSchema\n ? {\n ...options.configSchema,\n ...args.configSchema,\n }\n : (undefined as any),\n factory: ctx => {\n const { node, config, inputs, apis } = ctx;\n return args.factory(\n (innerParams: any, innerContext: any) => {\n return createExtensionDataContainer<any>(\n options.factory(\n unwrapParams(innerParams, ctx, defineParams, options.kind),\n {\n apis,\n node,\n config: (innerContext?.config ?? config) as any,\n inputs: resolveInputOverrides(\n options.inputs,\n inputs,\n innerContext?.inputs,\n ) as any,\n },\n ) as Iterable<any>,\n 'original blueprint factory',\n options.output,\n );\n },\n {\n apis,\n node,\n config: config as any,\n inputs: inputs as any,\n },\n ) as Iterable<ExtensionDataValue<any, any>>;\n },\n }) as OverridableExtensionDefinition;\n },\n } as ExtensionBlueprint<any>;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createExtensionDataRef.esm.js","sources":["../../src/wiring/createExtensionDataRef.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\n/** @public */\nexport type ExtensionDataValue<TData, TId extends string> = {\n readonly $$type: '@backstage/ExtensionDataValue';\n readonly id: TId;\n readonly value: TData;\n};\n\n/** @public */\nexport type ExtensionDataRef<\n TData = unknown,\n TId extends string = string,\n TConfig extends { optional?: true } = { optional?: true },\n> = {\n readonly $$type: '@backstage/ExtensionDataRef';\n readonly id: TId;\n readonly T: TData;\n readonly config: TConfig;\n};\n\n/** @ignore */\nexport type ExtensionDataRefToValue<TDataRef extends ExtensionDataRef> =\n TDataRef extends ExtensionDataRef<infer IData, infer IId, any>\n ? ExtensionDataValue<IData, IId>\n : never;\n\n/** @public */\nexport interface ConfigurableExtensionDataRef<\n TData,\n TId extends string,\n TConfig extends { optional?: true } = {},\n> extends ExtensionDataRef<TData, TId, TConfig> {\n optional(): ConfigurableExtensionDataRef<\n TData,\n TId,\n TConfig & { optional: true }\n >;\n (t: TData): ExtensionDataValue<TData, TId>;\n}\n\n/** @public */\nexport function createExtensionDataRef<TData>(): {\n with<TId extends string>(options: {\n id: TId;\n }): ConfigurableExtensionDataRef<TData, TId>;\n} {\n const createRef = <TId extends string>(refId: TId) =>\n Object.assign(\n (value: TData): ExtensionDataValue<TData, TId> => ({\n $$type: '@backstage/ExtensionDataValue',\n id: refId,\n value,\n }),\n {\n id: refId,\n $$type: '@backstage/ExtensionDataRef',\n config: {},\n optional() {\n return {\n ...this,\n config: { ...this.config, optional: true },\n };\n },\n toString() {\n const optional = Boolean(this.config.optional);\n return `ExtensionDataRef{id=${refId},optional=${optional}}`;\n },\n } as ConfigurableExtensionDataRef<TData, TId, { optional?: true }>,\n );\n return {\n with<TId extends string>(options: { id: TId }) {\n return createRef(options.id);\n },\n };\n}\n"],"names":[],"mappings":"AAwDO,SAAS,sBAAA,GAId;AACA,EAAA,MAAM,SAAA,GAAY,CAAqB,KAAA,KACrC,MAAA,CAAO,MAAA;AAAA,IACL,CAAC,KAAA,MAAkD;AAAA,MACjD,MAAA,EAAQ,+BAAA;AAAA,MACR,EAAA,EAAI,KAAA;AAAA,MACJ;AAAA,KACF,CAAA;AAAA,IACA;AAAA,MACE,EAAA,EAAI,KAAA;AAAA,MACJ,MAAA,EAAQ,6BAAA;AAAA,MACR,QAAQ,EAAC;AAAA,MACT,QAAA,GAAW;AACT,QAAA,OAAO;AAAA,UACL,GAAG,IAAA;AAAA,UACH,QAAQ,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,UAAU,IAAA;AAAK,SAC3C;AAAA,MACF,CAAA;AAAA,MACA,QAAA,GAAW;AACT,QAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA;AAC7C,QAAA,OAAO,CAAA,oBAAA,EAAuB,KAAK,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAA,CAAA;AAAA,MAC1D;AAAA;AACF,GACF;AACF,EAAA,OAAO;AAAA,IACL,KAAyB,OAAA,EAAsB;AAC7C,MAAA,OAAO,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA,IAC7B;AAAA,GACF;AACF
|
|
1
|
+
{"version":3,"file":"createExtensionDataRef.esm.js","sources":["../../src/wiring/createExtensionDataRef.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\n/** @public */\nexport type ExtensionDataValue<TData, TId extends string> = {\n readonly $$type: '@backstage/ExtensionDataValue';\n readonly id: TId;\n readonly value: TData;\n};\n\n/** @public */\nexport type ExtensionDataRef<\n TData = unknown,\n TId extends string = string,\n TConfig extends { optional?: true } = { optional?: true },\n> = {\n readonly $$type: '@backstage/ExtensionDataRef';\n readonly id: TId;\n readonly T: TData;\n readonly config: TConfig;\n};\n\n/** @ignore */\nexport type ExtensionDataRefToValue<TDataRef extends ExtensionDataRef> =\n TDataRef extends ExtensionDataRef<infer IData, infer IId, any>\n ? ExtensionDataValue<IData, IId>\n : never;\n\n/** @public */\nexport interface ConfigurableExtensionDataRef<\n TData,\n TId extends string,\n TConfig extends { optional?: true } = {},\n> extends ExtensionDataRef<TData, TId, TConfig> {\n optional(): ConfigurableExtensionDataRef<\n TData,\n TId,\n TConfig & { optional: true }\n >;\n (t: TData): ExtensionDataValue<TData, TId>;\n}\n\n/** @public */\nexport function createExtensionDataRef<TData>(): {\n with<TId extends string>(options: {\n id: TId;\n }): ConfigurableExtensionDataRef<TData, TId>;\n} {\n const createRef = <TId extends string>(refId: TId) =>\n Object.assign(\n (value: TData): ExtensionDataValue<TData, TId> => ({\n $$type: '@backstage/ExtensionDataValue',\n id: refId,\n value,\n }),\n {\n id: refId,\n $$type: '@backstage/ExtensionDataRef',\n config: {},\n optional() {\n return {\n ...this,\n config: { ...this.config, optional: true },\n };\n },\n toString() {\n const optional = Boolean(this.config.optional);\n return `ExtensionDataRef{id=${refId},optional=${optional}}`;\n },\n } as ConfigurableExtensionDataRef<TData, TId, { optional?: true }>,\n );\n return {\n with<TId extends string>(options: { id: TId }) {\n return createRef(options.id);\n },\n };\n}\n"],"names":[],"mappings":"AAwDO,SAAS,sBAAA,GAId;AACA,EAAA,MAAM,SAAA,GAAY,CAAqB,KAAA,KACrC,MAAA,CAAO,MAAA;AAAA,IACL,CAAC,KAAA,MAAkD;AAAA,MACjD,MAAA,EAAQ,+BAAA;AAAA,MACR,EAAA,EAAI,KAAA;AAAA,MACJ;AAAA,KACF,CAAA;AAAA,IACA;AAAA,MACE,EAAA,EAAI,KAAA;AAAA,MACJ,MAAA,EAAQ,6BAAA;AAAA,MACR,QAAQ,EAAC;AAAA,MACT,QAAA,GAAW;AACT,QAAA,OAAO;AAAA,UACL,GAAG,IAAA;AAAA,UACH,QAAQ,EAAE,GAAG,IAAA,CAAK,MAAA,EAAQ,UAAU,IAAA;AAAK,SAC3C;AAAA,MACF,CAAA;AAAA,MACA,QAAA,GAAW;AACT,QAAA,MAAM,QAAA,GAAW,OAAA,CAAQ,IAAA,CAAK,MAAA,CAAO,QAAQ,CAAA;AAC7C,QAAA,OAAO,CAAA,oBAAA,EAAuB,KAAK,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAA,CAAA;AAAA,MAC1D;AAAA;AACF,GACF;AACF,EAAA,OAAO;AAAA,IACL,KAAyB,OAAA,EAAsB;AAC7C,MAAA,OAAO,SAAA,CAAU,QAAQ,EAAE,CAAA;AAAA,IAC7B;AAAA,GACF;AACF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createExtensionInput.esm.js","sources":["../../src/wiring/createExtensionInput.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 ExtensionInputContext,\n OpaqueExtensionInput,\n} from '@internal/frontend';\nimport { ExtensionDataRef } from './createExtensionDataRef';\n\n/** @public */\nexport interface ExtensionInput<\n UExtensionData extends ExtensionDataRef<\n unknown,\n string,\n { optional?: true }\n > = ExtensionDataRef,\n TConfig extends {\n singleton: boolean;\n optional: boolean;\n internal?: boolean;\n } = {\n singleton: boolean;\n optional: boolean;\n internal?: boolean;\n },\n> {\n readonly $$type: '@backstage/ExtensionInput';\n readonly extensionData: Array<UExtensionData>;\n readonly config: TConfig;\n readonly replaces?: Array<{ id: string; input: string }>;\n}\n\n/**\n * Creates a new extension input to be passed to the input map of an extension.\n *\n * @remarks\n *\n * Extension inputs created with this function can be passed to any `inputs` map\n * as part of creating or overriding an extension.\n *\n * The array of extension data references defines the data this input expects.\n * If the required data is not provided by the attached extension, the\n * attachment will fail.\n *\n * The `config` object can be used to restrict the behavior and shape of the\n * input. By default an input will accept zero or more extensions from any\n * plugin. The following options are available:\n *\n * - `singleton`: If set to `true`, only one extension can be attached to the\n * input at a time. Additional extensions will trigger an app error and be\n * ignored.\n * - `optional`: If set to `true`, the input is optional and can be omitted,\n * this only has an effect if the `singleton` is set to `true`.\n * - `internal`: If set to `true`, only extensions from the same plugin will be\n * allowed to attach to this input. Other extensions will trigger an app error\n * and be ignored.\n *\n * @param extensionData - The array of extension data references that this input\n * expects.\n * @param config - The configuration object for the input.\n * @returns An extension input declaration.\n * @example\n * ```ts\n * const extension = createExtension({\n * attachTo: { id: 'example-parent', input: 'example-input' },\n * inputs: {\n * content: createExtensionInput([coreExtensionData.reactElement], {\n * singleton: true,\n * }),\n * },\n * output: [coreExtensionData.reactElement],\n * *factory({ inputs }) {\n * const content = inputs.content?.get(coreExtensionData.reactElement);\n * yield coreExtensionData.reactElement(<ContentWrapper>{content}</ContentWrapper>);\n * },\n * });\n * ```\n * @public\n */\nexport function createExtensionInput<\n UExtensionData extends ExtensionDataRef<unknown, string, { optional?: true }>,\n TConfig extends {\n singleton?: boolean;\n optional?: boolean;\n internal?: boolean;\n },\n>(\n extensionData: Array<UExtensionData>,\n config?: TConfig & { replaces?: Array<{ id: string; input: string }> },\n): ExtensionInput<\n UExtensionData,\n {\n singleton: TConfig['singleton'] extends true ? true : false;\n optional: TConfig['optional'] extends true ? true : false;\n internal: TConfig['internal'] extends true ? true : false;\n }\n> {\n if (process.env.NODE_ENV !== 'production') {\n if (Array.isArray(extensionData)) {\n const seen = new Set();\n const duplicates = [];\n for (const dataRef of extensionData) {\n if (seen.has(dataRef.id)) {\n duplicates.push(dataRef.id);\n } else {\n seen.add(dataRef.id);\n }\n }\n if (duplicates.length > 0) {\n throw new Error(\n `ExtensionInput may not have duplicate data refs: '${duplicates.join(\n \"', '\",\n )}'`,\n );\n }\n }\n }\n const baseOptions = {\n extensionData,\n config: {\n singleton: Boolean(config?.singleton) as TConfig['singleton'] extends true\n ? true\n : false,\n optional: Boolean(config?.optional) as TConfig['optional'] extends true\n ? true\n : false,\n internal: Boolean(config?.internal) as TConfig['internal'] extends true\n ? true\n : false,\n },\n replaces: config?.replaces,\n };\n\n function createInstance(parent?: ExtensionInputContext): ExtensionInput<\n UExtensionData,\n {\n singleton: TConfig['singleton'] extends true ? true : false;\n optional: TConfig['optional'] extends true ? true : false;\n internal: TConfig['internal'] extends true ? true : false;\n }\n > {\n return OpaqueExtensionInput.createInstance(undefined, {\n ...baseOptions,\n context: parent,\n withContext: createInstance,\n });\n }\n\n return createInstance();\n}\n"],"names":[],"mappings":";;;;;AA4FO,SAAS,oBAAA,CAQd,eACA,MAAA,EAQA;AACA,EAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,YAAA,EAAc;AACzC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,aAAa,CAAA,EAAG;AAChC,MAAA,MAAM,IAAA,uBAAW,GAAA,EAAI;AACrB,MAAA,MAAM,aAAa,EAAC;AACpB,MAAA,KAAA,MAAW,WAAW,aAAA,EAAe;AACnC,QAAA,IAAI,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,EAAG;AACxB,UAAA,UAAA,CAAW,IAAA,CAAK,QAAQ,EAAE,CAAA;AAAA,QAC5B,CAAA,MAAO;AACL,UAAA,IAAA,CAAK,GAAA,CAAI,QAAQ,EAAE,CAAA;AAAA,QACrB;AAAA,MACF;AACA,MAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,qDAAqD,UAAA,CAAW,IAAA;AAAA,YAC9D;AAAA,WACD,CAAA,CAAA;AAAA,SACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,EAAA,MAAM,WAAA,GAAc;AAAA,IAClB,aAAA;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,SAAA,EAAW,OAAA,CAAQ,MAAA,EAAQ,SAAS,CAAA;AAAA,MAGpC,QAAA,EAAU,OAAA,CAAQ,MAAA,EAAQ,QAAQ,CAAA;AAAA,MAGlC,QAAA,EAAU,OAAA,CAAQ,MAAA,EAAQ,QAAQ;AAAA,KAGpC;AAAA,IACA,UAAU,MAAA,EAAQ;AAAA,GACpB;AAEA,EAAA,SAAS,eAAe,MAAA,EAOtB;AACA,IAAA,OAAO,oBAAA,CAAqB,eAAe,MAAA,EAAW;AAAA,MACpD,GAAG,WAAA;AAAA,MACH,OAAA,EAAS,MAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,cAAA,EAAe;AACxB
|
|
1
|
+
{"version":3,"file":"createExtensionInput.esm.js","sources":["../../src/wiring/createExtensionInput.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 ExtensionInputContext,\n OpaqueExtensionInput,\n} from '@internal/frontend';\nimport { ExtensionDataRef } from './createExtensionDataRef';\n\n/** @public */\nexport interface ExtensionInput<\n UExtensionData extends ExtensionDataRef<\n unknown,\n string,\n { optional?: true }\n > = ExtensionDataRef,\n TConfig extends {\n singleton: boolean;\n optional: boolean;\n internal?: boolean;\n } = {\n singleton: boolean;\n optional: boolean;\n internal?: boolean;\n },\n> {\n readonly $$type: '@backstage/ExtensionInput';\n readonly extensionData: Array<UExtensionData>;\n readonly config: TConfig;\n readonly replaces?: Array<{ id: string; input: string }>;\n}\n\n/**\n * Creates a new extension input to be passed to the input map of an extension.\n *\n * @remarks\n *\n * Extension inputs created with this function can be passed to any `inputs` map\n * as part of creating or overriding an extension.\n *\n * The array of extension data references defines the data this input expects.\n * If the required data is not provided by the attached extension, the\n * attachment will fail.\n *\n * The `config` object can be used to restrict the behavior and shape of the\n * input. By default an input will accept zero or more extensions from any\n * plugin. The following options are available:\n *\n * - `singleton`: If set to `true`, only one extension can be attached to the\n * input at a time. Additional extensions will trigger an app error and be\n * ignored.\n * - `optional`: If set to `true`, the input is optional and can be omitted,\n * this only has an effect if the `singleton` is set to `true`.\n * - `internal`: If set to `true`, only extensions from the same plugin will be\n * allowed to attach to this input. Other extensions will trigger an app error\n * and be ignored.\n *\n * @param extensionData - The array of extension data references that this input\n * expects.\n * @param config - The configuration object for the input.\n * @returns An extension input declaration.\n * @example\n * ```ts\n * const extension = createExtension({\n * attachTo: { id: 'example-parent', input: 'example-input' },\n * inputs: {\n * content: createExtensionInput([coreExtensionData.reactElement], {\n * singleton: true,\n * }),\n * },\n * output: [coreExtensionData.reactElement],\n * *factory({ inputs }) {\n * const content = inputs.content?.get(coreExtensionData.reactElement);\n * yield coreExtensionData.reactElement(<ContentWrapper>{content}</ContentWrapper>);\n * },\n * });\n * ```\n * @public\n */\nexport function createExtensionInput<\n UExtensionData extends ExtensionDataRef<unknown, string, { optional?: true }>,\n TConfig extends {\n singleton?: boolean;\n optional?: boolean;\n internal?: boolean;\n },\n>(\n extensionData: Array<UExtensionData>,\n config?: TConfig & { replaces?: Array<{ id: string; input: string }> },\n): ExtensionInput<\n UExtensionData,\n {\n singleton: TConfig['singleton'] extends true ? true : false;\n optional: TConfig['optional'] extends true ? true : false;\n internal: TConfig['internal'] extends true ? true : false;\n }\n> {\n if (process.env.NODE_ENV !== 'production') {\n if (Array.isArray(extensionData)) {\n const seen = new Set();\n const duplicates = [];\n for (const dataRef of extensionData) {\n if (seen.has(dataRef.id)) {\n duplicates.push(dataRef.id);\n } else {\n seen.add(dataRef.id);\n }\n }\n if (duplicates.length > 0) {\n throw new Error(\n `ExtensionInput may not have duplicate data refs: '${duplicates.join(\n \"', '\",\n )}'`,\n );\n }\n }\n }\n const baseOptions = {\n extensionData,\n config: {\n singleton: Boolean(config?.singleton) as TConfig['singleton'] extends true\n ? true\n : false,\n optional: Boolean(config?.optional) as TConfig['optional'] extends true\n ? true\n : false,\n internal: Boolean(config?.internal) as TConfig['internal'] extends true\n ? true\n : false,\n },\n replaces: config?.replaces,\n };\n\n function createInstance(parent?: ExtensionInputContext): ExtensionInput<\n UExtensionData,\n {\n singleton: TConfig['singleton'] extends true ? true : false;\n optional: TConfig['optional'] extends true ? true : false;\n internal: TConfig['internal'] extends true ? true : false;\n }\n > {\n return OpaqueExtensionInput.createInstance(undefined, {\n ...baseOptions,\n context: parent,\n withContext: createInstance,\n });\n }\n\n return createInstance();\n}\n"],"names":[],"mappings":";;;;;AA4FO,SAAS,oBAAA,CAQd,eACA,MAAA,EAQA;AACA,EAAA,IAAI,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,YAAA,EAAc;AACzC,IAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,aAAa,CAAA,EAAG;AAChC,MAAA,MAAM,IAAA,uBAAW,GAAA,EAAI;AACrB,MAAA,MAAM,aAAa,EAAC;AACpB,MAAA,KAAA,MAAW,WAAW,aAAA,EAAe;AACnC,QAAA,IAAI,IAAA,CAAK,GAAA,CAAI,OAAA,CAAQ,EAAE,CAAA,EAAG;AACxB,UAAA,UAAA,CAAW,IAAA,CAAK,QAAQ,EAAE,CAAA;AAAA,QAC5B,CAAA,MAAO;AACL,UAAA,IAAA,CAAK,GAAA,CAAI,QAAQ,EAAE,CAAA;AAAA,QACrB;AAAA,MACF;AACA,MAAA,IAAI,UAAA,CAAW,SAAS,CAAA,EAAG;AACzB,QAAA,MAAM,IAAI,KAAA;AAAA,UACR,qDAAqD,UAAA,CAAW,IAAA;AAAA,YAC9D;AAAA,WACD,CAAA,CAAA;AAAA,SACH;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACA,EAAA,MAAM,WAAA,GAAc;AAAA,IAClB,aAAA;AAAA,IACA,MAAA,EAAQ;AAAA,MACN,SAAA,EAAW,OAAA,CAAQ,MAAA,EAAQ,SAAS,CAAA;AAAA,MAGpC,QAAA,EAAU,OAAA,CAAQ,MAAA,EAAQ,QAAQ,CAAA;AAAA,MAGlC,QAAA,EAAU,OAAA,CAAQ,MAAA,EAAQ,QAAQ;AAAA,KAGpC;AAAA,IACA,UAAU,MAAA,EAAQ;AAAA,GACpB;AAEA,EAAA,SAAS,eAAe,MAAA,EAOtB;AACA,IAAA,OAAO,oBAAA,CAAqB,eAAe,MAAA,EAAW;AAAA,MACpD,GAAG,WAAA;AAAA,MACH,OAAA,EAAS,MAAA;AAAA,MACT,WAAA,EAAa;AAAA,KACd,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,cAAA,EAAe;AACxB;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFrontendFeatureLoader.esm.js","sources":["../../src/wiring/createFrontendFeatureLoader.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { ConfigApi } from '../apis/definitions';\nimport { describeParentCallSite } from '../routing/describeParentCallSite';\nimport { FrontendFeature } from './types';\n\n/** @public */\nexport interface CreateFrontendFeatureLoaderOptions {\n loader(deps: {\n config: ConfigApi;\n }):\n | Iterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | Promise<{ default: FrontendFeature | FrontendFeatureLoader }>\n >\n | Promise<\n Iterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | Promise<{ default: FrontendFeature | FrontendFeatureLoader }>\n >\n >\n | AsyncIterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | { default: FrontendFeature | FrontendFeatureLoader }\n >;\n}\n\n/** @public */\nexport interface FrontendFeatureLoader {\n readonly $$type: '@backstage/FrontendFeatureLoader';\n}\n\n/** @internal */\nexport interface InternalFrontendFeatureLoader extends FrontendFeatureLoader {\n readonly version: 'v1';\n readonly description: string;\n readonly loader: (deps: {\n config: ConfigApi;\n }) => Promise<(FrontendFeature | FrontendFeatureLoader)[]>;\n}\n\n/** @public */\nexport function createFrontendFeatureLoader(\n options: CreateFrontendFeatureLoaderOptions,\n): FrontendFeatureLoader {\n const description = `created at '${describeParentCallSite()}'`;\n return {\n $$type: '@backstage/FrontendFeatureLoader',\n version: 'v1',\n description,\n toString() {\n return `FeatureLoader{description=${description}}`;\n },\n async loader(deps: {\n config: ConfigApi;\n }): Promise<(FrontendFeature | FrontendFeatureLoader)[]> {\n const it = await options.loader(deps);\n const result = new Array<FrontendFeature | FrontendFeatureLoader>();\n for await (const item of it) {\n if (isFeatureOrLoader(item)) {\n result.push(item);\n } else if ('default' in item) {\n result.push(item.default);\n } else {\n throw new Error(`Invalid item \"${item}\"`);\n }\n }\n return result;\n },\n } as InternalFrontendFeatureLoader;\n}\n\n/** @internal */\nexport function isInternalFrontendFeatureLoader(opaque: {\n $$type: string;\n}): opaque is InternalFrontendFeatureLoader {\n if (opaque.$$type === '@backstage/FrontendFeatureLoader') {\n // Make sure we throw if invalid\n toInternalFrontendFeatureLoader(opaque as FrontendFeatureLoader);\n return true;\n }\n return false;\n}\n\n/** @internal */\nexport function toInternalFrontendFeatureLoader(\n plugin: FrontendFeatureLoader,\n): InternalFrontendFeatureLoader {\n const internal = plugin as InternalFrontendFeatureLoader;\n if (internal.$$type !== '@backstage/FrontendFeatureLoader') {\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\nfunction isFeatureOrLoader(\n obj: unknown,\n): obj is FrontendFeature | FrontendFeatureLoader {\n if (obj !== null && typeof obj === 'object' && '$$type' in obj) {\n return (\n obj.$$type === '@backstage/FrontendPlugin' ||\n obj.$$type === '@backstage/FrontendModule' ||\n obj.$$type === '@backstage/FrontendFeatureLoader'\n );\n }\n return false;\n}\n"],"names":[],"mappings":";;AA2DO,SAAS,4BACd,OAAA,EACuB;AACvB,EAAA,MAAM,WAAA,GAAc,CAAA,YAAA,EAAe,sBAAA,EAAwB,CAAA,CAAA,CAAA;AAC3D,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,kCAAA;AAAA,IACR,OAAA,EAAS,IAAA;AAAA,IACT,WAAA;AAAA,IACA,QAAA,GAAW;AACT,MAAA,OAAO,6BAA6B,WAAW,CAAA,CAAA,CAAA;AAAA,IACjD,CAAA;AAAA,IACA,MAAM,OAAO,IAAA,EAE4C;AACvD,MAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA;AACpC,MAAA,MAAM,MAAA,GAAS,IAAI,KAAA,EAA+C;AAClE,MAAA,WAAA,MAAiB,QAAQ,EAAA,EAAI;AAC3B,QAAA,IAAI,iBAAA,CAAkB,IAAI,CAAA,EAAG;AAC3B,UAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,QAClB,CAAA,MAAA,IAAW,aAAa,IAAA,EAAM;AAC5B,UAAA,MAAA,CAAO,IAAA,CAAK,KAAK,OAAO,CAAA;AAAA,QAC1B,CAAA,MAAO;AACL,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,QAC1C;AAAA,MACF;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,GACF;AACF;AA8BA,SAAS,kBACP,GAAA,EACgD;AAChD,EAAA,IAAI,QAAQ,IAAA,IAAQ,OAAO,GAAA,KAAQ,QAAA,IAAY,YAAY,GAAA,EAAK;AAC9D,IAAA,OACE,IAAI,MAAA,KAAW,2BAAA,IACf,IAAI,MAAA,KAAW,2BAAA,IACf,IAAI,MAAA,KAAW,kCAAA;AAAA,EAEnB;AACA,EAAA,OAAO,KAAA;AACT
|
|
1
|
+
{"version":3,"file":"createFrontendFeatureLoader.esm.js","sources":["../../src/wiring/createFrontendFeatureLoader.ts"],"sourcesContent":["/*\n * Copyright 2025 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 { ConfigApi } from '../apis/definitions';\nimport { describeParentCallSite } from '../routing/describeParentCallSite';\nimport { FrontendFeature } from './types';\n\n/** @public */\nexport interface CreateFrontendFeatureLoaderOptions {\n loader(deps: {\n config: ConfigApi;\n }):\n | Iterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | Promise<{ default: FrontendFeature | FrontendFeatureLoader }>\n >\n | Promise<\n Iterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | Promise<{ default: FrontendFeature | FrontendFeatureLoader }>\n >\n >\n | AsyncIterable<\n | FrontendFeature\n | FrontendFeatureLoader\n | { default: FrontendFeature | FrontendFeatureLoader }\n >;\n}\n\n/** @public */\nexport interface FrontendFeatureLoader {\n readonly $$type: '@backstage/FrontendFeatureLoader';\n}\n\n/** @internal */\nexport interface InternalFrontendFeatureLoader extends FrontendFeatureLoader {\n readonly version: 'v1';\n readonly description: string;\n readonly loader: (deps: {\n config: ConfigApi;\n }) => Promise<(FrontendFeature | FrontendFeatureLoader)[]>;\n}\n\n/** @public */\nexport function createFrontendFeatureLoader(\n options: CreateFrontendFeatureLoaderOptions,\n): FrontendFeatureLoader {\n const description = `created at '${describeParentCallSite()}'`;\n return {\n $$type: '@backstage/FrontendFeatureLoader',\n version: 'v1',\n description,\n toString() {\n return `FeatureLoader{description=${description}}`;\n },\n async loader(deps: {\n config: ConfigApi;\n }): Promise<(FrontendFeature | FrontendFeatureLoader)[]> {\n const it = await options.loader(deps);\n const result = new Array<FrontendFeature | FrontendFeatureLoader>();\n for await (const item of it) {\n if (isFeatureOrLoader(item)) {\n result.push(item);\n } else if ('default' in item) {\n result.push(item.default);\n } else {\n throw new Error(`Invalid item \"${item}\"`);\n }\n }\n return result;\n },\n } as InternalFrontendFeatureLoader;\n}\n\n/** @internal */\nexport function isInternalFrontendFeatureLoader(opaque: {\n $$type: string;\n}): opaque is InternalFrontendFeatureLoader {\n if (opaque.$$type === '@backstage/FrontendFeatureLoader') {\n // Make sure we throw if invalid\n toInternalFrontendFeatureLoader(opaque as FrontendFeatureLoader);\n return true;\n }\n return false;\n}\n\n/** @internal */\nexport function toInternalFrontendFeatureLoader(\n plugin: FrontendFeatureLoader,\n): InternalFrontendFeatureLoader {\n const internal = plugin as InternalFrontendFeatureLoader;\n if (internal.$$type !== '@backstage/FrontendFeatureLoader') {\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\nfunction isFeatureOrLoader(\n obj: unknown,\n): obj is FrontendFeature | FrontendFeatureLoader {\n if (obj !== null && typeof obj === 'object' && '$$type' in obj) {\n return (\n obj.$$type === '@backstage/FrontendPlugin' ||\n obj.$$type === '@backstage/FrontendModule' ||\n obj.$$type === '@backstage/FrontendFeatureLoader'\n );\n }\n return false;\n}\n"],"names":[],"mappings":";;AA2DO,SAAS,4BACd,OAAA,EACuB;AACvB,EAAA,MAAM,WAAA,GAAc,CAAA,YAAA,EAAe,sBAAA,EAAwB,CAAA,CAAA,CAAA;AAC3D,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,kCAAA;AAAA,IACR,OAAA,EAAS,IAAA;AAAA,IACT,WAAA;AAAA,IACA,QAAA,GAAW;AACT,MAAA,OAAO,6BAA6B,WAAW,CAAA,CAAA,CAAA;AAAA,IACjD,CAAA;AAAA,IACA,MAAM,OAAO,IAAA,EAE4C;AACvD,MAAA,MAAM,EAAA,GAAK,MAAM,OAAA,CAAQ,MAAA,CAAO,IAAI,CAAA;AACpC,MAAA,MAAM,MAAA,GAAS,IAAI,KAAA,EAA+C;AAClE,MAAA,WAAA,MAAiB,QAAQ,EAAA,EAAI;AAC3B,QAAA,IAAI,iBAAA,CAAkB,IAAI,CAAA,EAAG;AAC3B,UAAA,MAAA,CAAO,KAAK,IAAI,CAAA;AAAA,QAClB,CAAA,MAAA,IAAW,aAAa,IAAA,EAAM;AAC5B,UAAA,MAAA,CAAO,IAAA,CAAK,KAAK,OAAO,CAAA;AAAA,QAC1B,CAAA,MAAO;AACL,UAAA,MAAM,IAAI,KAAA,CAAM,CAAA,cAAA,EAAiB,IAAI,CAAA,CAAA,CAAG,CAAA;AAAA,QAC1C;AAAA,MACF;AACA,MAAA,OAAO,MAAA;AAAA,IACT;AAAA,GACF;AACF;AA8BA,SAAS,kBACP,GAAA,EACgD;AAChD,EAAA,IAAI,QAAQ,IAAA,IAAQ,OAAO,GAAA,KAAQ,QAAA,IAAY,YAAY,GAAA,EAAK;AAC9D,IAAA,OACE,IAAI,MAAA,KAAW,2BAAA,IACf,IAAI,MAAA,KAAW,2BAAA,IACf,IAAI,MAAA,KAAW,kCAAA;AAAA,EAEnB;AACA,EAAA,OAAO,KAAA;AACT;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFrontendModule.esm.js","sources":["../../src/wiring/createFrontendModule.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 resolveExtensionDefinitions,\n} from './resolveExtensionDefinition';\nimport { FeatureFlagConfig } from './types';\nimport { FilterPredicate } from '@backstage/filter-predicates';\n\n/** @public */\nexport interface CreateFrontendModuleOptions<\n TPluginId extends string,\n TExtensions extends readonly ExtensionDefinition[],\n> {\n pluginId: TPluginId;\n extensions?: TExtensions;\n featureFlags?: FeatureFlagConfig[];\n if?: FilterPredicate;\n}\n\n/** @public */\nexport interface FrontendModule {\n readonly $$type: '@backstage/FrontendModule';\n readonly pluginId: string;\n}\n\n/** @internal */\nexport interface InternalFrontendModule extends FrontendModule {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n readonly if?: FilterPredicate;\n}\n\n/**\n * Creates a new module that can be installed in a Backstage app.\n *\n * @remarks\n *\n * Modules are used to add or override extensions for an existing plugin. If a\n * module provides an extension with the same ID as one provided by the plugin,\n * the extension provided by the module will always take precedence.\n *\n * Every module is created for a specific plugin by providing the\n * unique ID of the plugin that the module should be installed for. If that\n * plugin is not present in the app, the module will be ignored and have no\n * effect.\n *\n * For more information on how modules work, see the\n * {@link https://backstage.io/docs/frontend-system/architecture/extension-overrides#creating-a-frontend-module | documentation for modules}\n * in the frontend system documentation.\n *\n * It is recommended to name the module variable of the form `<pluginId>Module<ModuleName>`.\n *\n * @example\n *\n * ```tsx\n * import { createFrontendModule } from '@backstage/frontend-plugin-api';\n *\n * export const exampleModuleCustomPage = createFrontendModule({\n * pluginId: 'example',\n * extensions: [\n * // Overrides the default page for the 'example' plugin\n * PageBlueprint.make({\n * path: '/example',\n * loader: () => import('./CustomPage').then(m => <m.CustomPage />),\n * }),\n * ],\n * });\n * ```\n *\n * @public\n */\nexport function createFrontendModule<\n TId extends string,\n TExtensions extends readonly ExtensionDefinition[],\n>(options: CreateFrontendModuleOptions<TId, TExtensions>): FrontendModule {\n const { pluginId } = options;\n\n const { extensions } = resolveExtensionDefinitions(options.extensions ?? [], {\n namespace: pluginId,\n featureType: 'Module',\n });\n\n return {\n $$type: '@backstage/FrontendModule',\n version: 'v1',\n pluginId,\n featureFlags: options.featureFlags ?? [],\n if: options.if,\n extensions,\n toString() {\n return `Module{pluginId=${pluginId}}`;\n },\n } as InternalFrontendModule;\n}\n\n/** @internal */\nexport function isInternalFrontendModule(opaque: {\n $$type: string;\n}): opaque is InternalFrontendModule {\n if (opaque.$$type === '@backstage/FrontendModule') {\n // Make sure we throw if invalid\n toInternalFrontendModule(opaque as FrontendModule);\n return true;\n }\n return false;\n}\n\n/** @internal */\nexport function toInternalFrontendModule(\n plugin: FrontendModule,\n): InternalFrontendModule {\n const internal = plugin as InternalFrontendModule;\n if (internal.$$type !== '@backstage/FrontendModule') {\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":";;AAwFO,SAAS,qBAGd,OAAA,EAAwE;AACxE,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AAErB,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,4BAA4B,OAAA,CAAQ,UAAA,IAAc,EAAC,EAAG;AAAA,IAC3E,SAAA,EAAW,QAAA;AAAA,IACX,WAAA,EAAa;AAAA,GACd,CAAA;AAED,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,2BAAA;AAAA,IACR,OAAA,EAAS,IAAA;AAAA,IACT,QAAA;AAAA,IACA,YAAA,EAAc,OAAA,CAAQ,YAAA,IAAgB,EAAC;AAAA,IACvC,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,UAAA;AAAA,IACA,QAAA,GAAW;AACT,MAAA,OAAO,mBAAmB,QAAQ,CAAA,CAAA,CAAA;AAAA,IACpC;AAAA,GACF;AACF
|
|
1
|
+
{"version":3,"file":"createFrontendModule.esm.js","sources":["../../src/wiring/createFrontendModule.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 resolveExtensionDefinitions,\n} from './resolveExtensionDefinition';\nimport { FeatureFlagConfig } from './types';\nimport { FilterPredicate } from '@backstage/filter-predicates';\n\n/** @public */\nexport interface CreateFrontendModuleOptions<\n TPluginId extends string,\n TExtensions extends readonly ExtensionDefinition[],\n> {\n pluginId: TPluginId;\n extensions?: TExtensions;\n featureFlags?: FeatureFlagConfig[];\n if?: FilterPredicate;\n}\n\n/** @public */\nexport interface FrontendModule {\n readonly $$type: '@backstage/FrontendModule';\n readonly pluginId: string;\n}\n\n/** @internal */\nexport interface InternalFrontendModule extends FrontendModule {\n readonly version: 'v1';\n readonly extensions: Extension<unknown>[];\n readonly featureFlags: FeatureFlagConfig[];\n readonly if?: FilterPredicate;\n}\n\n/**\n * Creates a new module that can be installed in a Backstage app.\n *\n * @remarks\n *\n * Modules are used to add or override extensions for an existing plugin. If a\n * module provides an extension with the same ID as one provided by the plugin,\n * the extension provided by the module will always take precedence.\n *\n * Every module is created for a specific plugin by providing the\n * unique ID of the plugin that the module should be installed for. If that\n * plugin is not present in the app, the module will be ignored and have no\n * effect.\n *\n * For more information on how modules work, see the\n * {@link https://backstage.io/docs/frontend-system/architecture/extension-overrides#creating-a-frontend-module | documentation for modules}\n * in the frontend system documentation.\n *\n * It is recommended to name the module variable of the form `<pluginId>Module<ModuleName>`.\n *\n * @example\n *\n * ```tsx\n * import { createFrontendModule } from '@backstage/frontend-plugin-api';\n *\n * export const exampleModuleCustomPage = createFrontendModule({\n * pluginId: 'example',\n * extensions: [\n * // Overrides the default page for the 'example' plugin\n * PageBlueprint.make({\n * path: '/example',\n * loader: () => import('./CustomPage').then(m => <m.CustomPage />),\n * }),\n * ],\n * });\n * ```\n *\n * @public\n */\nexport function createFrontendModule<\n TId extends string,\n TExtensions extends readonly ExtensionDefinition[],\n>(options: CreateFrontendModuleOptions<TId, TExtensions>): FrontendModule {\n const { pluginId } = options;\n\n const { extensions } = resolveExtensionDefinitions(options.extensions ?? [], {\n namespace: pluginId,\n featureType: 'Module',\n });\n\n return {\n $$type: '@backstage/FrontendModule',\n version: 'v1',\n pluginId,\n featureFlags: options.featureFlags ?? [],\n if: options.if,\n extensions,\n toString() {\n return `Module{pluginId=${pluginId}}`;\n },\n } as InternalFrontendModule;\n}\n\n/** @internal */\nexport function isInternalFrontendModule(opaque: {\n $$type: string;\n}): opaque is InternalFrontendModule {\n if (opaque.$$type === '@backstage/FrontendModule') {\n // Make sure we throw if invalid\n toInternalFrontendModule(opaque as FrontendModule);\n return true;\n }\n return false;\n}\n\n/** @internal */\nexport function toInternalFrontendModule(\n plugin: FrontendModule,\n): InternalFrontendModule {\n const internal = plugin as InternalFrontendModule;\n if (internal.$$type !== '@backstage/FrontendModule') {\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":";;AAwFO,SAAS,qBAGd,OAAA,EAAwE;AACxE,EAAA,MAAM,EAAE,UAAS,GAAI,OAAA;AAErB,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,4BAA4B,OAAA,CAAQ,UAAA,IAAc,EAAC,EAAG;AAAA,IAC3E,SAAA,EAAW,QAAA;AAAA,IACX,WAAA,EAAa;AAAA,GACd,CAAA;AAED,EAAA,OAAO;AAAA,IACL,MAAA,EAAQ,2BAAA;AAAA,IACR,OAAA,EAAS,IAAA;AAAA,IACT,QAAA;AAAA,IACA,YAAA,EAAc,OAAA,CAAQ,YAAA,IAAgB,EAAC;AAAA,IACvC,IAAI,OAAA,CAAQ,EAAA;AAAA,IACZ,UAAA;AAAA,IACA,QAAA,GAAW;AACT,MAAA,OAAO,mBAAmB,QAAQ,CAAA,CAAA,CAAA;AAAA,IACpC;AAAA,GACF;AACF;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createFrontendPlugin.esm.js","sources":["../../src/wiring/createFrontendPlugin.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 { OpaqueFrontendPlugin } from '@internal/frontend';\nimport {\n ExtensionDefinition,\n OverridableExtensionDefinition,\n} from './createExtension';\nimport {\n resolveExtensionDefinition,\n resolveExtensionDefinitions,\n throwOnDuplicateExtensionIds,\n} from './resolveExtensionDefinition';\nimport { FeatureFlagConfig } from './types';\nimport { MakeSortedExtensionsMap } from './MakeSortedExtensionsMap';\nimport { JsonObject } from '@backstage/types';\nimport { IconElement } from '../icons/types';\nimport { RouteRef, SubRouteRef, ExternalRouteRef } from '../routing';\nimport { ID_PATTERN } from './constants';\nimport { FilterPredicate } from '@backstage/filter-predicates';\n\n/**\n * Information about the plugin.\n *\n * @public\n * @remarks\n *\n * This interface is intended to be extended via [module\n * augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)\n * in order to add fields that are specific to each project.\n *\n * For example, one might add a `slackChannel` field that is read from the\n * opaque manifest file.\n *\n * See the options for `createApp` for more information about how to\n * customize the parsing of manifest files.\n */\nexport interface FrontendPluginInfo {\n /**\n * The name of the package that implements the plugin.\n */\n packageName?: string;\n\n /**\n * The version of the plugin, typically the version of the package.json file.\n */\n version?: string;\n\n /**\n * As short description of the plugin, typically the description field in\n * package.json.\n */\n description?: string;\n\n /**\n * The owner entity references of the plugin.\n */\n ownerEntityRefs?: string[];\n\n /**\n * Links related to the plugin.\n */\n links?: Array<{ title: string; url: string }>;\n}\n\n/**\n * Options for providing information for a plugin.\n *\n * @public\n */\nexport type FrontendPluginInfoOptions = {\n /**\n * A loader function for the package.json file for the plugin.\n */\n packageJson?: () => Promise<{ name: string } & JsonObject>;\n /**\n * A loader function for an opaque manifest file for the plugin.\n */\n manifest?: () => Promise<JsonObject>;\n};\n\n/**\n * A variant of the {@link FrontendPlugin} interface that can also be used to install overrides for the plugin.\n *\n * @public\n */\nexport interface OverridableFrontendPlugin<\n TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {\n [name in string]: RouteRef | SubRouteRef;\n },\n TExternalRoutes extends { [name in string]: ExternalRouteRef } = {\n [name in string]: ExternalRouteRef;\n },\n TExtensionMap extends { [id in string]: ExtensionDefinition } = {\n [id in string]: ExtensionDefinition;\n },\n> extends FrontendPlugin<TRoutes, TExternalRoutes> {\n getExtension<TId extends keyof TExtensionMap>(\n id: TId,\n ): OverridableExtensionDefinition<TExtensionMap[TId]['T']>;\n withOverrides(options: {\n /**\n * Extensions to add to the plugin. An extension that overrides an existing\n * extension replaces it at its original position in the plugin's list of\n * extensions, while other extensions are appended at the end.\n */\n extensions?: Array<ExtensionDefinition>;\n\n /**\n * Overrides the shared condition that applies to all extensions in the plugin.\n */\n if?: FilterPredicate;\n\n /**\n * Overrides the display title of the plugin.\n */\n title?: string;\n\n /**\n * Overrides the display icon of the plugin.\n */\n icon?: IconElement;\n\n /**\n * Overrides the original info loaders of the plugin one by one.\n */\n info?: FrontendPluginInfoOptions;\n }): OverridableFrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;\n}\n\n/** @public */\nexport interface FrontendPlugin<\n TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {\n [name in string]: RouteRef | SubRouteRef;\n },\n TExternalRoutes extends { [name in string]: ExternalRouteRef } = {\n [name in string]: ExternalRouteRef;\n },\n> {\n readonly $$type: '@backstage/FrontendPlugin';\n /**\n * The plugin ID.\n */\n readonly pluginId: string;\n /**\n * Deprecated alias for `pluginId`.\n *\n * @deprecated Use `pluginId` instead.\n */\n readonly id: string;\n /**\n * The display title of the plugin, used in page headers and navigation.\n * Falls back to the plugin ID if not provided.\n */\n readonly title?: string;\n /**\n * The display icon of the plugin, used in page headers and navigation.\n */\n readonly icon?: IconElement;\n readonly routes: TRoutes;\n readonly externalRoutes: TExternalRoutes;\n\n /**\n * Loads the plugin info.\n */\n info(): Promise<FrontendPluginInfo>;\n}\n\n/**\n * Options for {@link createFrontendPlugin}.\n *\n * @public\n */\nexport interface CreateFrontendPluginOptions<\n TId extends string,\n TRoutes extends { [name in string]: RouteRef | SubRouteRef },\n TExternalRoutes extends { [name in string]: ExternalRouteRef },\n TExtensions extends readonly ExtensionDefinition[],\n> {\n pluginId: TId;\n /**\n * The display title of the plugin, used in page headers and navigation.\n * Falls back to the plugin ID if not provided.\n */\n title?: string;\n /**\n * The display icon of the plugin, used in page headers and navigation.\n */\n icon?: IconElement;\n routes?: TRoutes;\n externalRoutes?: TExternalRoutes;\n extensions?: TExtensions;\n featureFlags?: FeatureFlagConfig[];\n if?: FilterPredicate;\n info?: FrontendPluginInfoOptions;\n}\n\n/**\n * @deprecated Use {@link CreateFrontendPluginOptions} instead.\n * @public\n */\nexport type PluginOptions<\n TId extends string,\n TRoutes extends { [name in string]: RouteRef | SubRouteRef },\n TExternalRoutes extends { [name in string]: ExternalRouteRef },\n TExtensions extends readonly ExtensionDefinition[],\n> = CreateFrontendPluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>;\n\n/**\n * Creates a new plugin that can be installed in a Backstage app.\n *\n * @remarks\n *\n * Every plugin is created with a unique ID and a set of extensions\n * that are installed as part of the plugin.\n *\n * For more information on how plugins work, see the\n * {@link https://backstage.io/docs/frontend-system/building-plugins/index | documentation for plugins}\n * in the frontend system documentation.\n *\n * @example\n *\n * ```tsx\n * import { createFrontendPlugin } from '@backstage/frontend-plugin-api';\n *\n * export const examplePlugin = createFrontendPlugin({\n * pluginId: 'example',\n * extensions: [\n * PageBlueprint.make({\n * path: '/example',\n * loader: () => import('./ExamplePage').then(m => <m.ExamplePage />),\n * }),\n * ],\n * });\n * ```\n *\n * @public\n */\nexport function createFrontendPlugin<\n TId extends string,\n TExtensions extends readonly ExtensionDefinition[],\n TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {},\n TExternalRoutes extends { [name in string]: ExternalRouteRef } = {},\n>(\n options: CreateFrontendPluginOptions<\n TId,\n TRoutes,\n TExternalRoutes,\n TExtensions\n >,\n): OverridableFrontendPlugin<\n TRoutes,\n TExternalRoutes,\n MakeSortedExtensionsMap<TExtensions[number], TId>\n> {\n const pluginId = options.pluginId;\n\n if (!ID_PATTERN.test(pluginId)) {\n // eslint-disable-next-line no-console\n console.warn(\n `WARNING: The pluginId '${pluginId}' will be invalid soon, please change it to match the pattern ${ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`,\n );\n }\n\n const { extensions, extensionDefinitionsById } = resolveExtensionDefinitions(\n options.extensions ?? [],\n {\n namespace: pluginId,\n featureType: 'Plugin',\n },\n );\n\n return OpaqueFrontendPlugin.createInstance('v1', {\n pluginId,\n id: pluginId,\n title: options.title,\n icon: options.icon,\n routes: options.routes ?? ({} as TRoutes),\n externalRoutes: options.externalRoutes ?? ({} as TExternalRoutes),\n featureFlags: options.featureFlags ?? [],\n if: options.if,\n extensions: extensions,\n infoOptions: options.info,\n\n // This method is overridden when the plugin instance is installed in an app\n async info() {\n throw new Error(\n `Attempted to load plugin info for plugin '${pluginId}', but the plugin instance is not installed in an app`,\n );\n },\n getExtension(id) {\n const ext = extensionDefinitionsById.get(id);\n if (!ext) {\n throw new Error(\n `Attempted to get non-existent extension '${id}' from plugin '${pluginId}'`,\n );\n }\n return ext;\n },\n toString() {\n return `Plugin{id=${pluginId}}`;\n },\n withOverrides(overrides) {\n let ifPredicate = options.if;\n if ('if' in overrides) {\n ifPredicate = overrides.if;\n }\n const overrideExtensions = overrides.extensions ?? [];\n const overrideExtensionEntries = overrideExtensions.map(\n extension =>\n [\n resolveExtensionDefinition(extension, { namespace: pluginId }).id,\n extension,\n ] as const,\n );\n throwOnDuplicateExtensionIds(\n overrideExtensionEntries.map(([id]) => id),\n { namespace: pluginId, featureType: 'Plugin' },\n );\n const overrideExtensionsById = new Map(overrideExtensionEntries);\n // Extensions that override an existing one replace it in place, keeping\n // the original registration order, since the order affects the order of\n // attachments in the app. Remaining extensions are appended at the end.\n const replacedExtensionIds = new Set<string>();\n const mergedExtensions = (options.extensions ?? []).map(extension => {\n const id = resolveExtensionDefinition(extension, {\n namespace: pluginId,\n }).id;\n const overrideExtension = overrideExtensionsById.get(id);\n if (overrideExtension) {\n replacedExtensionIds.add(id);\n return overrideExtension;\n }\n return extension;\n });\n const appendedExtensions = overrideExtensionEntries\n .filter(([id]) => !replacedExtensionIds.has(id))\n .map(([, extension]) => extension);\n return createFrontendPlugin({\n ...options,\n pluginId,\n if: ifPredicate,\n title: overrides.title ?? options.title,\n icon: overrides.icon ?? options.icon,\n extensions: [...mergedExtensions, ...appendedExtensions],\n info: {\n ...options.info,\n ...overrides.info,\n },\n });\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createFrontendPlugin.esm.js","sources":["../../src/wiring/createFrontendPlugin.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 { OpaqueFrontendPlugin } from '@internal/frontend';\nimport {\n ExtensionDefinition,\n OverridableExtensionDefinition,\n} from './createExtension';\nimport {\n resolveExtensionDefinition,\n resolveExtensionDefinitions,\n throwOnDuplicateExtensionIds,\n} from './resolveExtensionDefinition';\nimport { FeatureFlagConfig } from './types';\nimport { MakeSortedExtensionsMap } from './MakeSortedExtensionsMap';\nimport { JsonObject } from '@backstage/types';\nimport { IconElement } from '../icons/types';\nimport { RouteRef, SubRouteRef, ExternalRouteRef } from '../routing';\nimport { ID_PATTERN } from './constants';\nimport { FilterPredicate } from '@backstage/filter-predicates';\n\n/**\n * Information about the plugin.\n *\n * @public\n * @remarks\n *\n * This interface is intended to be extended via [module\n * augmentation](https://www.typescriptlang.org/docs/handbook/declaration-merging.html#module-augmentation)\n * in order to add fields that are specific to each project.\n *\n * For example, one might add a `slackChannel` field that is read from the\n * opaque manifest file.\n *\n * See the options for `createApp` for more information about how to\n * customize the parsing of manifest files.\n */\nexport interface FrontendPluginInfo {\n /**\n * The name of the package that implements the plugin.\n */\n packageName?: string;\n\n /**\n * The version of the plugin, typically the version of the package.json file.\n */\n version?: string;\n\n /**\n * As short description of the plugin, typically the description field in\n * package.json.\n */\n description?: string;\n\n /**\n * The owner entity references of the plugin.\n */\n ownerEntityRefs?: string[];\n\n /**\n * Links related to the plugin.\n */\n links?: Array<{ title: string; url: string }>;\n}\n\n/**\n * Options for providing information for a plugin.\n *\n * @public\n */\nexport type FrontendPluginInfoOptions = {\n /**\n * A loader function for the package.json file for the plugin.\n */\n packageJson?: () => Promise<{ name: string } & JsonObject>;\n /**\n * A loader function for an opaque manifest file for the plugin.\n */\n manifest?: () => Promise<JsonObject>;\n};\n\n/**\n * A variant of the {@link FrontendPlugin} interface that can also be used to install overrides for the plugin.\n *\n * @public\n */\nexport interface OverridableFrontendPlugin<\n TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {\n [name in string]: RouteRef | SubRouteRef;\n },\n TExternalRoutes extends { [name in string]: ExternalRouteRef } = {\n [name in string]: ExternalRouteRef;\n },\n TExtensionMap extends { [id in string]: ExtensionDefinition } = {\n [id in string]: ExtensionDefinition;\n },\n> extends FrontendPlugin<TRoutes, TExternalRoutes> {\n getExtension<TId extends keyof TExtensionMap>(\n id: TId,\n ): OverridableExtensionDefinition<TExtensionMap[TId]['T']>;\n withOverrides(options: {\n /**\n * Extensions to add to the plugin. An extension that overrides an existing\n * extension replaces it at its original position in the plugin's list of\n * extensions, while other extensions are appended at the end.\n */\n extensions?: Array<ExtensionDefinition>;\n\n /**\n * Overrides the shared condition that applies to all extensions in the plugin.\n */\n if?: FilterPredicate;\n\n /**\n * Overrides the display title of the plugin.\n */\n title?: string;\n\n /**\n * Overrides the display icon of the plugin.\n */\n icon?: IconElement;\n\n /**\n * Overrides the original info loaders of the plugin one by one.\n */\n info?: FrontendPluginInfoOptions;\n }): OverridableFrontendPlugin<TRoutes, TExternalRoutes, TExtensionMap>;\n}\n\n/** @public */\nexport interface FrontendPlugin<\n TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {\n [name in string]: RouteRef | SubRouteRef;\n },\n TExternalRoutes extends { [name in string]: ExternalRouteRef } = {\n [name in string]: ExternalRouteRef;\n },\n> {\n readonly $$type: '@backstage/FrontendPlugin';\n /**\n * The plugin ID.\n */\n readonly pluginId: string;\n /**\n * Deprecated alias for `pluginId`.\n *\n * @deprecated Use `pluginId` instead.\n */\n readonly id: string;\n /**\n * The display title of the plugin, used in page headers and navigation.\n * Falls back to the plugin ID if not provided.\n */\n readonly title?: string;\n /**\n * The display icon of the plugin, used in page headers and navigation.\n */\n readonly icon?: IconElement;\n readonly routes: TRoutes;\n readonly externalRoutes: TExternalRoutes;\n\n /**\n * Loads the plugin info.\n */\n info(): Promise<FrontendPluginInfo>;\n}\n\n/**\n * Options for {@link createFrontendPlugin}.\n *\n * @public\n */\nexport interface CreateFrontendPluginOptions<\n TId extends string,\n TRoutes extends { [name in string]: RouteRef | SubRouteRef },\n TExternalRoutes extends { [name in string]: ExternalRouteRef },\n TExtensions extends readonly ExtensionDefinition[],\n> {\n pluginId: TId;\n /**\n * The display title of the plugin, used in page headers and navigation.\n * Falls back to the plugin ID if not provided.\n */\n title?: string;\n /**\n * The display icon of the plugin, used in page headers and navigation.\n */\n icon?: IconElement;\n routes?: TRoutes;\n externalRoutes?: TExternalRoutes;\n extensions?: TExtensions;\n featureFlags?: FeatureFlagConfig[];\n if?: FilterPredicate;\n info?: FrontendPluginInfoOptions;\n}\n\n/**\n * @deprecated Use {@link CreateFrontendPluginOptions} instead.\n * @public\n */\nexport type PluginOptions<\n TId extends string,\n TRoutes extends { [name in string]: RouteRef | SubRouteRef },\n TExternalRoutes extends { [name in string]: ExternalRouteRef },\n TExtensions extends readonly ExtensionDefinition[],\n> = CreateFrontendPluginOptions<TId, TRoutes, TExternalRoutes, TExtensions>;\n\n/**\n * Creates a new plugin that can be installed in a Backstage app.\n *\n * @remarks\n *\n * Every plugin is created with a unique ID and a set of extensions\n * that are installed as part of the plugin.\n *\n * For more information on how plugins work, see the\n * {@link https://backstage.io/docs/frontend-system/building-plugins/index | documentation for plugins}\n * in the frontend system documentation.\n *\n * @example\n *\n * ```tsx\n * import { createFrontendPlugin } from '@backstage/frontend-plugin-api';\n *\n * export const examplePlugin = createFrontendPlugin({\n * pluginId: 'example',\n * extensions: [\n * PageBlueprint.make({\n * path: '/example',\n * loader: () => import('./ExamplePage').then(m => <m.ExamplePage />),\n * }),\n * ],\n * });\n * ```\n *\n * @public\n */\nexport function createFrontendPlugin<\n TId extends string,\n TExtensions extends readonly ExtensionDefinition[],\n TRoutes extends { [name in string]: RouteRef | SubRouteRef } = {},\n TExternalRoutes extends { [name in string]: ExternalRouteRef } = {},\n>(\n options: CreateFrontendPluginOptions<\n TId,\n TRoutes,\n TExternalRoutes,\n TExtensions\n >,\n): OverridableFrontendPlugin<\n TRoutes,\n TExternalRoutes,\n MakeSortedExtensionsMap<TExtensions[number], TId>\n> {\n const pluginId = options.pluginId;\n\n if (!ID_PATTERN.test(pluginId)) {\n // eslint-disable-next-line no-console\n console.warn(\n `WARNING: The pluginId '${pluginId}' will be invalid soon, please change it to match the pattern ${ID_PATTERN} (letters, digits, and dashes only, starting with a letter)`,\n );\n }\n\n const { extensions, extensionDefinitionsById } = resolveExtensionDefinitions(\n options.extensions ?? [],\n {\n namespace: pluginId,\n featureType: 'Plugin',\n },\n );\n\n return OpaqueFrontendPlugin.createInstance('v1', {\n pluginId,\n id: pluginId,\n title: options.title,\n icon: options.icon,\n routes: options.routes ?? ({} as TRoutes),\n externalRoutes: options.externalRoutes ?? ({} as TExternalRoutes),\n featureFlags: options.featureFlags ?? [],\n if: options.if,\n extensions: extensions,\n infoOptions: options.info,\n\n // This method is overridden when the plugin instance is installed in an app\n async info() {\n throw new Error(\n `Attempted to load plugin info for plugin '${pluginId}', but the plugin instance is not installed in an app`,\n );\n },\n getExtension(id) {\n const ext = extensionDefinitionsById.get(id);\n if (!ext) {\n throw new Error(\n `Attempted to get non-existent extension '${id}' from plugin '${pluginId}'`,\n );\n }\n return ext;\n },\n toString() {\n return `Plugin{id=${pluginId}}`;\n },\n withOverrides(overrides) {\n let ifPredicate = options.if;\n if ('if' in overrides) {\n ifPredicate = overrides.if;\n }\n const overrideExtensions = overrides.extensions ?? [];\n const overrideExtensionEntries = overrideExtensions.map(\n extension =>\n [\n resolveExtensionDefinition(extension, { namespace: pluginId }).id,\n extension,\n ] as const,\n );\n throwOnDuplicateExtensionIds(\n overrideExtensionEntries.map(([id]) => id),\n { namespace: pluginId, featureType: 'Plugin' },\n );\n const overrideExtensionsById = new Map(overrideExtensionEntries);\n // Extensions that override an existing one replace it in place, keeping\n // the original registration order, since the order affects the order of\n // attachments in the app. Remaining extensions are appended at the end.\n const replacedExtensionIds = new Set<string>();\n const mergedExtensions = (options.extensions ?? []).map(extension => {\n const id = resolveExtensionDefinition(extension, {\n namespace: pluginId,\n }).id;\n const overrideExtension = overrideExtensionsById.get(id);\n if (overrideExtension) {\n replacedExtensionIds.add(id);\n return overrideExtension;\n }\n return extension;\n });\n const appendedExtensions = overrideExtensionEntries\n .filter(([id]) => !replacedExtensionIds.has(id))\n .map(([, extension]) => extension);\n return createFrontendPlugin({\n ...options,\n pluginId,\n if: ifPredicate,\n title: overrides.title ?? options.title,\n icon: overrides.icon ?? options.icon,\n extensions: [...mergedExtensions, ...appendedExtensions],\n info: {\n ...options.info,\n ...overrides.info,\n },\n });\n },\n });\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveExtensionDefinition.esm.js","sources":["../../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 { ApiHolder, AppNode } from '../apis';\nimport {\n ExtensionDefinitionAttachTo,\n ExtensionDefinition,\n ExtensionDefinitionParameters,\n ResolvedExtensionInputs,\n} from './createExtension';\nimport { PortableSchema } from '../schema';\nimport { ExtensionInput } from './createExtensionInput';\nimport { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef';\nimport {\n OpaqueExtensionDefinition,\n OpaqueExtensionInput,\n} from '@internal/frontend';\nimport { FilterPredicate } from '@backstage/filter-predicates';\n\n/** @public */\nexport type ExtensionAttachTo = { id: string; input: string };\n\n/** @public */\nexport interface Extension<TConfig, TConfigInput = TConfig> {\n $$type: '@backstage/Extension';\n readonly id: string;\n readonly attachTo: ExtensionAttachTo;\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: {\n [inputName in string]: {\n $$type: '@backstage/ExtensionInput';\n extensionData: {\n [name in string]: ExtensionDataRef;\n };\n config: { optional: boolean; singleton: boolean };\n };\n };\n readonly output: {\n [name in string]: ExtensionDataRef;\n };\n factory(context: {\n apis: ApiHolder;\n node: AppNode;\n config: TConfig;\n inputs: {\n [inputName in string]: unknown;\n };\n }): {\n [inputName in string]: unknown;\n };\n }\n | {\n readonly version: 'v2';\n readonly if?: FilterPredicate;\n readonly inputs: { [inputName in string]: ExtensionInput };\n readonly output: Array<ExtensionDataRef>;\n factory(options: {\n apis: ApiHolder;\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput;\n }>;\n }): Iterable<ExtensionDataValue<any, any>>;\n }\n );\n\n/** @internal */\nexport function toInternalExtension<TConfig, TConfigInput>(\n overrides: Extension<TConfig, TConfigInput>,\n): InternalExtension<TConfig, TConfigInput> {\n const internal = overrides as InternalExtension<TConfig, TConfigInput>;\n if (internal.$$type !== '@backstage/Extension') {\n throw new Error(\n `Invalid extension instance, bad type '${internal.$$type}'`,\n );\n }\n const version = internal.version;\n if (version !== 'v1' && version !== 'v2') {\n throw new Error(`Invalid extension instance, bad version '${version}'`);\n }\n return internal;\n}\n\n/** @ignore */\nexport type ResolveExtensionId<\n TExtension extends ExtensionDefinition,\n TNamespace extends string,\n> = TExtension extends ExtensionDefinition<{\n kind: infer IKind extends string | undefined;\n name: infer IName extends string | undefined;\n params: any;\n}>\n ? [string] extends [IKind | IName]\n ? never\n : (\n undefined extends IName ? TNamespace : `${TNamespace}/${IName}`\n ) extends infer INamePart extends string\n ? IKind extends string\n ? `${IKind}:${INamePart}`\n : INamePart\n : never\n : never;\n\nfunction resolveExtensionId(\n kind?: string,\n namespace?: string,\n name?: string,\n): string {\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 return kind ? `${kind}:${namePart}` : namePart;\n}\n\nfunction resolveAttachTo(\n attachTo: ExtensionDefinitionAttachTo | ExtensionDefinitionAttachTo[],\n namespace?: string,\n): ExtensionAttachTo | ExtensionAttachTo[] {\n const resolveSpec = (\n spec: ExtensionDefinitionAttachTo,\n ): { id: string; input: string } => {\n if (OpaqueExtensionInput.isType(spec)) {\n const { context } = OpaqueExtensionInput.toInternal(spec);\n if (!context) {\n throw new Error(\n 'Invalid input object without a parent extension used as attachment point',\n );\n }\n return {\n id: resolveExtensionId(context.kind, namespace, context.name),\n input: context.input,\n };\n }\n if ('relative' in spec && spec.relative) {\n return {\n id: resolveExtensionId(\n spec.relative.kind,\n namespace,\n spec.relative.name,\n ),\n input: spec.input,\n };\n }\n if ('id' in spec) {\n return { id: spec.id, input: spec.input };\n }\n throw new Error('Invalid attachment point specification');\n };\n\n if (Array.isArray(attachTo)) {\n return attachTo.map(resolveSpec);\n }\n\n return resolveSpec(attachTo);\n}\n\n/**\n * Resolves a list of extension definitions into extensions, returning both the\n * resolved extensions and a map of extension definitions keyed by resolved ID.\n * Throws if any two definitions resolve to the same ID.\n *\n * @internal\n */\nexport function resolveExtensionDefinitions(\n definitions: Iterable<ExtensionDefinition>,\n context: { namespace: string; featureType: string },\n): {\n extensions: Extension<any>[];\n extensionDefinitionsById: Map<\n string,\n typeof OpaqueExtensionDefinition.TInternal\n >;\n} {\n const extensions = new Array<Extension<any>>();\n const extensionDefinitionsById = new Map<\n string,\n typeof OpaqueExtensionDefinition.TInternal\n >();\n\n for (const def of definitions) {\n const internal = OpaqueExtensionDefinition.toInternal(def);\n const ext = resolveExtensionDefinition(def, {\n namespace: context.namespace,\n });\n extensions.push(ext);\n extensionDefinitionsById.set(ext.id, {\n ...internal,\n namespace: context.namespace,\n });\n }\n\n throwOnDuplicateExtensionIds(\n extensions.map(e => e.id),\n context,\n );\n\n return { extensions, extensionDefinitionsById };\n}\n\n/**\n * Throws if the provided list of resolved extension IDs contains duplicates.\n *\n * @internal\n */\nexport function throwOnDuplicateExtensionIds(\n extensionIds: string[],\n context: { namespace: string; featureType: string },\n): void {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const id of extensionIds) {\n if (seen.has(id)) {\n duplicates.add(id);\n } else {\n seen.add(id);\n }\n }\n if (duplicates.size > 0) {\n throw new Error(\n `${context.featureType} '${\n context.namespace\n }' provided duplicate extensions: ${Array.from(duplicates).join(', ')}`,\n );\n }\n}\n\n/** @internal */\nexport function resolveExtensionDefinition<\n T extends ExtensionDefinitionParameters,\n>(\n definition: ExtensionDefinition<T>,\n context?: { namespace?: string },\n): Extension<T['config'], T['configInput']> {\n const internalDefinition = OpaqueExtensionDefinition.toInternal(definition);\n\n const {\n name,\n kind,\n namespace: internalNamespace,\n override: _skip2,\n attachTo,\n ...rest\n } = internalDefinition;\n\n const namespace = internalNamespace ?? context?.namespace;\n const id = resolveExtensionId(kind, namespace, name);\n\n return {\n ...rest,\n attachTo: resolveAttachTo(attachTo, namespace) as ExtensionAttachTo,\n $$type: '@backstage/Extension',\n version: internalDefinition.version,\n id,\n toString() {\n return `Extension{id=${id}}`;\n },\n } as InternalExtension<T['config'], T['configInput']> & Object;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"resolveExtensionDefinition.esm.js","sources":["../../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 { ApiHolder, AppNode } from '../apis';\nimport {\n ExtensionDefinitionAttachTo,\n ExtensionDefinition,\n ExtensionDefinitionParameters,\n ResolvedExtensionInputs,\n} from './createExtension';\nimport { PortableSchema } from '../schema';\nimport { ExtensionInput } from './createExtensionInput';\nimport { ExtensionDataRef, ExtensionDataValue } from './createExtensionDataRef';\nimport {\n OpaqueExtensionDefinition,\n OpaqueExtensionInput,\n} from '@internal/frontend';\nimport { FilterPredicate } from '@backstage/filter-predicates';\n\n/** @public */\nexport type ExtensionAttachTo = { id: string; input: string };\n\n/** @public */\nexport interface Extension<TConfig, TConfigInput = TConfig> {\n $$type: '@backstage/Extension';\n readonly id: string;\n readonly attachTo: ExtensionAttachTo;\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: {\n [inputName in string]: {\n $$type: '@backstage/ExtensionInput';\n extensionData: {\n [name in string]: ExtensionDataRef;\n };\n config: { optional: boolean; singleton: boolean };\n };\n };\n readonly output: {\n [name in string]: ExtensionDataRef;\n };\n factory(context: {\n apis: ApiHolder;\n node: AppNode;\n config: TConfig;\n inputs: {\n [inputName in string]: unknown;\n };\n }): {\n [inputName in string]: unknown;\n };\n }\n | {\n readonly version: 'v2';\n readonly if?: FilterPredicate;\n readonly inputs: { [inputName in string]: ExtensionInput };\n readonly output: Array<ExtensionDataRef>;\n factory(options: {\n apis: ApiHolder;\n node: AppNode;\n config: TConfig;\n inputs: ResolvedExtensionInputs<{\n [inputName in string]: ExtensionInput;\n }>;\n }): Iterable<ExtensionDataValue<any, any>>;\n }\n );\n\n/** @internal */\nexport function toInternalExtension<TConfig, TConfigInput>(\n overrides: Extension<TConfig, TConfigInput>,\n): InternalExtension<TConfig, TConfigInput> {\n const internal = overrides as InternalExtension<TConfig, TConfigInput>;\n if (internal.$$type !== '@backstage/Extension') {\n throw new Error(\n `Invalid extension instance, bad type '${internal.$$type}'`,\n );\n }\n const version = internal.version;\n if (version !== 'v1' && version !== 'v2') {\n throw new Error(`Invalid extension instance, bad version '${version}'`);\n }\n return internal;\n}\n\n/** @ignore */\nexport type ResolveExtensionId<\n TExtension extends ExtensionDefinition,\n TNamespace extends string,\n> = TExtension extends ExtensionDefinition<{\n kind: infer IKind extends string | undefined;\n name: infer IName extends string | undefined;\n params: any;\n}>\n ? [string] extends [IKind | IName]\n ? never\n : (\n undefined extends IName ? TNamespace : `${TNamespace}/${IName}`\n ) extends infer INamePart extends string\n ? IKind extends string\n ? `${IKind}:${INamePart}`\n : INamePart\n : never\n : never;\n\nfunction resolveExtensionId(\n kind?: string,\n namespace?: string,\n name?: string,\n): string {\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 return kind ? `${kind}:${namePart}` : namePart;\n}\n\nfunction resolveAttachTo(\n attachTo: ExtensionDefinitionAttachTo | ExtensionDefinitionAttachTo[],\n namespace?: string,\n): ExtensionAttachTo | ExtensionAttachTo[] {\n const resolveSpec = (\n spec: ExtensionDefinitionAttachTo,\n ): { id: string; input: string } => {\n if (OpaqueExtensionInput.isType(spec)) {\n const { context } = OpaqueExtensionInput.toInternal(spec);\n if (!context) {\n throw new Error(\n 'Invalid input object without a parent extension used as attachment point',\n );\n }\n return {\n id: resolveExtensionId(context.kind, namespace, context.name),\n input: context.input,\n };\n }\n if ('relative' in spec && spec.relative) {\n return {\n id: resolveExtensionId(\n spec.relative.kind,\n namespace,\n spec.relative.name,\n ),\n input: spec.input,\n };\n }\n if ('id' in spec) {\n return { id: spec.id, input: spec.input };\n }\n throw new Error('Invalid attachment point specification');\n };\n\n if (Array.isArray(attachTo)) {\n return attachTo.map(resolveSpec);\n }\n\n return resolveSpec(attachTo);\n}\n\n/**\n * Resolves a list of extension definitions into extensions, returning both the\n * resolved extensions and a map of extension definitions keyed by resolved ID.\n * Throws if any two definitions resolve to the same ID.\n *\n * @internal\n */\nexport function resolveExtensionDefinitions(\n definitions: Iterable<ExtensionDefinition>,\n context: { namespace: string; featureType: string },\n): {\n extensions: Extension<any>[];\n extensionDefinitionsById: Map<\n string,\n typeof OpaqueExtensionDefinition.TInternal\n >;\n} {\n const extensions = new Array<Extension<any>>();\n const extensionDefinitionsById = new Map<\n string,\n typeof OpaqueExtensionDefinition.TInternal\n >();\n\n for (const def of definitions) {\n const internal = OpaqueExtensionDefinition.toInternal(def);\n const ext = resolveExtensionDefinition(def, {\n namespace: context.namespace,\n });\n extensions.push(ext);\n extensionDefinitionsById.set(ext.id, {\n ...internal,\n namespace: context.namespace,\n });\n }\n\n throwOnDuplicateExtensionIds(\n extensions.map(e => e.id),\n context,\n );\n\n return { extensions, extensionDefinitionsById };\n}\n\n/**\n * Throws if the provided list of resolved extension IDs contains duplicates.\n *\n * @internal\n */\nexport function throwOnDuplicateExtensionIds(\n extensionIds: string[],\n context: { namespace: string; featureType: string },\n): void {\n const seen = new Set<string>();\n const duplicates = new Set<string>();\n for (const id of extensionIds) {\n if (seen.has(id)) {\n duplicates.add(id);\n } else {\n seen.add(id);\n }\n }\n if (duplicates.size > 0) {\n throw new Error(\n `${context.featureType} '${\n context.namespace\n }' provided duplicate extensions: ${Array.from(duplicates).join(', ')}`,\n );\n }\n}\n\n/** @internal */\nexport function resolveExtensionDefinition<\n T extends ExtensionDefinitionParameters,\n>(\n definition: ExtensionDefinition<T>,\n context?: { namespace?: string },\n): Extension<T['config'], T['configInput']> {\n const internalDefinition = OpaqueExtensionDefinition.toInternal(definition);\n\n const {\n name,\n kind,\n namespace: internalNamespace,\n override: _skip2,\n attachTo,\n ...rest\n } = internalDefinition;\n\n const namespace = internalNamespace ?? context?.namespace;\n const id = resolveExtensionId(kind, namespace, name);\n\n return {\n ...rest,\n attachTo: resolveAttachTo(attachTo, namespace) as ExtensionAttachTo,\n $$type: '@backstage/Extension',\n version: internalDefinition.version,\n id,\n toString() {\n return `Extension{id=${id}}`;\n },\n } as InternalExtension<T['config'], T['configInput']> & Object;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveInputOverrides.esm.js","sources":["../../src/wiring/resolveInputOverrides.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { Expand } from '@backstage/types';\nimport { createExtensionDataContainer } from '@internal/frontend';\nimport {\n ExtensionDataRefToValue,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\nimport { ExtensionDataContainer } from './types';\n\n/** @ignore */\nexport type ResolvedInputValueOverrides<\n TInputs extends { [inputName in string]: ExtensionInput } = {\n [inputName in string]: ExtensionInput;\n },\n> = Expand<\n {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n internal?: boolean;\n }\n >\n ? IOptional extends true\n ? never\n : KName\n : never]: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n {\n optional: boolean;\n singleton: infer ISingleton extends boolean;\n internal?: boolean;\n }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n } & {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n internal?: boolean;\n }\n >\n ? IOptional extends true\n ? KName\n : never\n : never]?: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n {\n optional: boolean;\n singleton: infer ISingleton extends boolean;\n internal?: boolean;\n }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n }\n>;\n\nfunction expectArray<T>(value: T | T[]): T[] {\n return value as T[];\n}\nfunction expectItem<T>(value: T | T[]): T {\n return value as T;\n}\n\n/** @internal */\nexport function resolveInputOverrides(\n declaredInputs?: { [inputName in string]: ExtensionInput },\n inputs?: {\n [KName in string]?:\n | ({ node: AppNode } & ExtensionDataContainer<any>)\n | Array<{ node: AppNode } & ExtensionDataContainer<any>>;\n },\n inputOverrides?: ResolvedInputValueOverrides,\n) {\n if (!declaredInputs || !inputs || !inputOverrides) {\n return inputs;\n }\n\n const newInputs: typeof inputs = {};\n for (const name in declaredInputs) {\n if (!Object.hasOwn(declaredInputs, name)) {\n continue;\n }\n const declaredInput = declaredInputs[name];\n const providedData = inputOverrides[name];\n if (declaredInput.config.singleton) {\n const originalInput = expectItem(inputs[name]);\n if (providedData) {\n const providedContainer = createExtensionDataContainer(\n providedData as Iterable<ExtensionDataValue<any, any>>,\n 'extension input override',\n declaredInput.extensionData,\n );\n if (!originalInput) {\n throw new Error(\n `attempted to override data of input '${name}' but it is not present in the original inputs`,\n );\n }\n newInputs[name] = Object.assign(providedContainer, {\n node: (originalInput as { node: AppNode }).node,\n }) as any;\n }\n } else {\n const originalInput = expectArray(inputs[name]);\n if (!Array.isArray(providedData)) {\n throw new Error(\n `override data provided for input '${name}' must be an array`,\n );\n }\n\n // Regular inputs can be overridden in two different ways:\n // 1) Forward a subset of the original inputs in a new order\n // 2) Provide new data for each original input\n\n // First check if all inputs are being removed\n if (providedData.length === 0) {\n newInputs[name] = [];\n } else {\n // Check how many of the provided data items have a node property, i.e. is a forwarded input\n const withNodesCount = providedData.filter(d => 'node' in d).length;\n if (withNodesCount === 0) {\n if (originalInput.length !== providedData.length) {\n throw new Error(\n `override data provided for input '${name}' must match the length of the original inputs`,\n );\n }\n newInputs[name] = providedData.map((data, i) => {\n const providedContainer = createExtensionDataContainer(\n data as Iterable<ExtensionDataValue<any, any>>,\n 'extension input override',\n declaredInput.extensionData,\n );\n return Object.assign(providedContainer, {\n node: (originalInput[i] as { node: AppNode }).node,\n }) as any;\n });\n } else if (withNodesCount === providedData.length) {\n newInputs[name] = providedData as any;\n } else {\n throw new Error(\n `override data for input '${name}' may not mix forwarded inputs with data overrides`,\n );\n }\n }\n }\n }\n return newInputs;\n}\n"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"resolveInputOverrides.esm.js","sources":["../../src/wiring/resolveInputOverrides.ts"],"sourcesContent":["/*\n * Copyright 2024 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 { Expand } from '@backstage/types';\nimport { createExtensionDataContainer } from '@internal/frontend';\nimport {\n ExtensionDataRefToValue,\n ExtensionDataValue,\n} from './createExtensionDataRef';\nimport { ExtensionInput } from './createExtensionInput';\nimport { ExtensionDataContainer } from './types';\n\n/** @ignore */\nexport type ResolvedInputValueOverrides<\n TInputs extends { [inputName in string]: ExtensionInput } = {\n [inputName in string]: ExtensionInput;\n },\n> = Expand<\n {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n internal?: boolean;\n }\n >\n ? IOptional extends true\n ? never\n : KName\n : never]: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n {\n optional: boolean;\n singleton: infer ISingleton extends boolean;\n internal?: boolean;\n }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n } & {\n [KName in keyof TInputs as TInputs[KName] extends ExtensionInput<\n any,\n {\n optional: infer IOptional extends boolean;\n singleton: boolean;\n internal?: boolean;\n }\n >\n ? IOptional extends true\n ? KName\n : never\n : never]?: TInputs[KName] extends ExtensionInput<\n infer IDataRefs,\n {\n optional: boolean;\n singleton: infer ISingleton extends boolean;\n internal?: boolean;\n }\n >\n ? ISingleton extends true\n ? Iterable<ExtensionDataRefToValue<IDataRefs>>\n : Array<Iterable<ExtensionDataRefToValue<IDataRefs>>>\n : never;\n }\n>;\n\nfunction expectArray<T>(value: T | T[]): T[] {\n return value as T[];\n}\nfunction expectItem<T>(value: T | T[]): T {\n return value as T;\n}\n\n/** @internal */\nexport function resolveInputOverrides(\n declaredInputs?: { [inputName in string]: ExtensionInput },\n inputs?: {\n [KName in string]?:\n | ({ node: AppNode } & ExtensionDataContainer<any>)\n | Array<{ node: AppNode } & ExtensionDataContainer<any>>;\n },\n inputOverrides?: ResolvedInputValueOverrides,\n) {\n if (!declaredInputs || !inputs || !inputOverrides) {\n return inputs;\n }\n\n const newInputs: typeof inputs = {};\n for (const name in declaredInputs) {\n if (!Object.hasOwn(declaredInputs, name)) {\n continue;\n }\n const declaredInput = declaredInputs[name];\n const providedData = inputOverrides[name];\n if (declaredInput.config.singleton) {\n const originalInput = expectItem(inputs[name]);\n if (providedData) {\n const providedContainer = createExtensionDataContainer(\n providedData as Iterable<ExtensionDataValue<any, any>>,\n 'extension input override',\n declaredInput.extensionData,\n );\n if (!originalInput) {\n throw new Error(\n `attempted to override data of input '${name}' but it is not present in the original inputs`,\n );\n }\n newInputs[name] = Object.assign(providedContainer, {\n node: (originalInput as { node: AppNode }).node,\n }) as any;\n }\n } else {\n const originalInput = expectArray(inputs[name]);\n if (!Array.isArray(providedData)) {\n throw new Error(\n `override data provided for input '${name}' must be an array`,\n );\n }\n\n // Regular inputs can be overridden in two different ways:\n // 1) Forward a subset of the original inputs in a new order\n // 2) Provide new data for each original input\n\n // First check if all inputs are being removed\n if (providedData.length === 0) {\n newInputs[name] = [];\n } else {\n // Check how many of the provided data items have a node property, i.e. is a forwarded input\n const withNodesCount = providedData.filter(d => 'node' in d).length;\n if (withNodesCount === 0) {\n if (originalInput.length !== providedData.length) {\n throw new Error(\n `override data provided for input '${name}' must match the length of the original inputs`,\n );\n }\n newInputs[name] = providedData.map((data, i) => {\n const providedContainer = createExtensionDataContainer(\n data as Iterable<ExtensionDataValue<any, any>>,\n 'extension input override',\n declaredInput.extensionData,\n );\n return Object.assign(providedContainer, {\n node: (originalInput[i] as { node: AppNode }).node,\n }) as any;\n });\n } else if (withNodesCount === providedData.length) {\n newInputs[name] = providedData as any;\n } else {\n throw new Error(\n `override data for input '${name}' may not mix forwarded inputs with data overrides`,\n );\n }\n }\n }\n }\n return newInputs;\n}\n"],"names":[],"mappings":"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"}
|