From b99b158dfc148ec54422ff625ebcbbd442c295a9 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Aug 2024 08:39:47 +0200 Subject: [PATCH 1/8] chore: deprecate the `namespace` option in blueprints and extensions Signed-off-by: blam --- .../frontend-plugin-api/src/blueprints/IconBundleBlueprint.ts | 1 - .../frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts | 2 +- packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.ts | 1 - packages/frontend-plugin-api/src/wiring/createExtension.ts | 1 + .../frontend-plugin-api/src/wiring/createExtensionBlueprint.ts | 3 +++ plugins/app/src/extensions/App.tsx | 1 - plugins/app/src/extensions/AppLayout.tsx | 1 - plugins/app/src/extensions/AppNav.tsx | 1 - plugins/app/src/extensions/AppRoot.tsx | 1 - plugins/app/src/extensions/AppRoutes.tsx | 1 - plugins/app/src/extensions/elements.tsx | 2 -- 11 files changed, 5 insertions(+), 10 deletions(-) diff --git a/packages/frontend-plugin-api/src/blueprints/IconBundleBlueprint.ts b/packages/frontend-plugin-api/src/blueprints/IconBundleBlueprint.ts index 369ac052f5..51b3b6d633 100644 --- a/packages/frontend-plugin-api/src/blueprints/IconBundleBlueprint.ts +++ b/packages/frontend-plugin-api/src/blueprints/IconBundleBlueprint.ts @@ -24,7 +24,6 @@ const iconsDataRef = createExtensionDataRef<{ /** @public */ export const IconBundleBlueprint = createExtensionBlueprint({ kind: 'icon-bundle', - namespace: 'app', attachTo: { id: 'api:app/icons', input: 'icons' }, output: [iconsDataRef], config: { diff --git a/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts b/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts index 6d3f6280a3..89c2229fab 100644 --- a/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts +++ b/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.test.ts @@ -42,7 +42,7 @@ describe('ThemeBlueprint', () => { "inputs": {}, "kind": "theme", "name": "light", - "namespace": "app", + "namespace": undefined, "output": [ [Function], ], diff --git a/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.ts b/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.ts index ca33970125..323078bc4e 100644 --- a/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.ts +++ b/packages/frontend-plugin-api/src/blueprints/ThemeBlueprint.ts @@ -28,7 +28,6 @@ const themeDataRef = createExtensionDataRef().with({ */ export const ThemeBlueprint = createExtensionBlueprint({ kind: 'theme', - namespace: 'app', attachTo: { id: 'api:app/app-theme', input: 'themes' }, output: [themeDataRef], dataRefs: { diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index 445bbd8a68..ab999a2d0c 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -122,6 +122,7 @@ export type CreateExtensionOptions< UFactoryOutput extends ExtensionDataValue, > = { kind?: TKind; + /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ namespace?: TNamespace; name?: TName; attachTo: { id: string; input: string }; diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index 77d078f257..de788473b5 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -57,6 +57,7 @@ export type CreateExtensionBlueprintOptions< TDataRefs extends { [name in string]: AnyExtensionDataRef }, > = { kind: TKind; + /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ namespace?: TNamespace; attachTo: { id: string; input: string }; disabled?: boolean; @@ -111,6 +112,7 @@ export interface ExtensionBlueprint< TNewNamespace extends string | undefined, TNewName extends string | undefined, >(args: { + /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ namespace?: TNewNamespace; name?: TNewName; attachTo?: { id: string; input: string }; @@ -149,6 +151,7 @@ export interface ExtensionBlueprint< >; }, >(args: { + /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ namespace?: TNewNamespace; name?: TNewName; attachTo?: { id: string; input: string }; diff --git a/plugins/app/src/extensions/App.tsx b/plugins/app/src/extensions/App.tsx index 5c6d95bfbc..7f4b3d5ee1 100644 --- a/plugins/app/src/extensions/App.tsx +++ b/plugins/app/src/extensions/App.tsx @@ -27,7 +27,6 @@ import { ApiProvider } from '../../../../packages/core-app-api/src'; import { AppThemeProvider } from '../../../../packages/core-app-api/src/app/AppThemeProvider'; export const App = createExtension({ - namespace: 'app', attachTo: { id: 'root', input: 'app' }, inputs: { root: createExtensionInput([coreExtensionData.reactElement], { diff --git a/plugins/app/src/extensions/AppLayout.tsx b/plugins/app/src/extensions/AppLayout.tsx index 9fadba8a93..3a0560a807 100644 --- a/plugins/app/src/extensions/AppLayout.tsx +++ b/plugins/app/src/extensions/AppLayout.tsx @@ -23,7 +23,6 @@ import { import { SidebarPage } from '@backstage/core-components'; export const AppLayout = createExtension({ - namespace: 'app', name: 'layout', attachTo: { id: 'app/root', input: 'children' }, inputs: { diff --git a/plugins/app/src/extensions/AppNav.tsx b/plugins/app/src/extensions/AppNav.tsx index 3659f474b2..3e4fcebf8c 100644 --- a/plugins/app/src/extensions/AppNav.tsx +++ b/plugins/app/src/extensions/AppNav.tsx @@ -82,7 +82,6 @@ const SidebarNavItem = ( }; export const AppNav = createExtension({ - namespace: 'app', name: 'nav', attachTo: { id: 'app/layout', input: 'nav' }, inputs: { diff --git a/plugins/app/src/extensions/AppRoot.tsx b/plugins/app/src/extensions/AppRoot.tsx index bd786765f9..014f9a1354 100644 --- a/plugins/app/src/extensions/AppRoot.tsx +++ b/plugins/app/src/extensions/AppRoot.tsx @@ -53,7 +53,6 @@ import { RouteTracker } from '../../../../packages/frontend-app-api/src/routing/ import { getBasePath } from '../../../../packages/frontend-app-api/src/routing/getBasePath'; export const AppRoot = createExtension({ - namespace: 'app', name: 'root', attachTo: { id: 'app', input: 'root' }, inputs: { diff --git a/plugins/app/src/extensions/AppRoutes.tsx b/plugins/app/src/extensions/AppRoutes.tsx index 6ef7e2a271..5880d6182e 100644 --- a/plugins/app/src/extensions/AppRoutes.tsx +++ b/plugins/app/src/extensions/AppRoutes.tsx @@ -25,7 +25,6 @@ import { import { useRoutes } from 'react-router-dom'; export const AppRoutes = createExtension({ - namespace: 'app', name: 'routes', attachTo: { id: 'app/layout', input: 'content' }, inputs: { diff --git a/plugins/app/src/extensions/elements.tsx b/plugins/app/src/extensions/elements.tsx index 1ab7f97ba2..bbb6374ebe 100644 --- a/plugins/app/src/extensions/elements.tsx +++ b/plugins/app/src/extensions/elements.tsx @@ -19,7 +19,6 @@ import { AppRootElementBlueprint } from '@backstage/frontend-plugin-api'; import React from 'react'; export const oauthRequestDialogAppRootElement = AppRootElementBlueprint.make({ - namespace: 'app', name: 'oauth-request-dialog', params: { element: , @@ -28,7 +27,6 @@ export const oauthRequestDialogAppRootElement = AppRootElementBlueprint.make({ export const alertDisplayAppRootElement = AppRootElementBlueprint.makeWithOverrides({ - namespace: 'app', name: 'alert-display', config: { schema: { From 6860490a88e3f2f6173a9b05238922b0570ff8b9 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Aug 2024 09:25:16 +0200 Subject: [PATCH 2/8] chore: api-reports Signed-off-by: blam --- packages/frontend-plugin-api/api-report.md | 4 ++-- plugins/app/api-report.md | 18 +++++++++--------- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index b42efddffa..9419efc05e 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -1289,7 +1289,7 @@ export { googleAuthApiRef }; // @public (undocumented) export const IconBundleBlueprint: ExtensionBlueprint<{ kind: 'icon-bundle'; - namespace: 'app'; + namespace: undefined; name: undefined; params: { icons: { @@ -1701,7 +1701,7 @@ export interface SubRouteRef< // @public export const ThemeBlueprint: ExtensionBlueprint<{ kind: 'theme'; - namespace: 'app'; + namespace: undefined; name: undefined; params: { theme: AppTheme; diff --git a/plugins/app/api-report.md b/plugins/app/api-report.md index ca76ecb91b..fbf77debb4 100644 --- a/plugins/app/api-report.md +++ b/plugins/app/api-report.md @@ -71,7 +71,7 @@ const appPlugin: FrontendPlugin< >; }; kind: undefined; - namespace: 'app'; + namespace: undefined; name: undefined; }>; 'api:app/app-language': ExtensionDefinition<{ @@ -112,7 +112,7 @@ const appPlugin: FrontendPlugin< >; }; kind: undefined; - namespace: 'app'; + namespace: undefined; name: 'layout'; }>; 'app/nav': ExtensionDefinition<{ @@ -155,7 +155,7 @@ const appPlugin: FrontendPlugin< >; }; kind: undefined; - namespace: 'app'; + namespace: undefined; name: 'nav'; }>; 'app/root': ExtensionDefinition<{ @@ -220,7 +220,7 @@ const appPlugin: FrontendPlugin< >; }; kind: undefined; - namespace: 'app'; + namespace: undefined; name: 'root'; }>; 'app/routes': ExtensionDefinition<{ @@ -249,7 +249,7 @@ const appPlugin: FrontendPlugin< >; }; kind: undefined; - namespace: 'app'; + namespace: undefined; name: 'routes'; }>; 'api:app/app-theme': ExtensionDefinition<{ @@ -275,7 +275,7 @@ const appPlugin: FrontendPlugin< }>; 'theme:app/light': ExtensionDefinition<{ kind: 'theme'; - namespace: 'app'; + namespace: undefined; name: 'light'; config: {}; configInput: {}; @@ -284,7 +284,7 @@ const appPlugin: FrontendPlugin< }>; 'theme:app/dark': ExtensionDefinition<{ kind: 'theme'; - namespace: 'app'; + namespace: undefined; name: 'dark'; config: {}; configInput: {}; @@ -393,7 +393,7 @@ const appPlugin: FrontendPlugin< }>; 'app-root-element:app/oauth-request-dialog': ExtensionDefinition<{ kind: 'app-root-element'; - namespace: 'app'; + namespace: undefined; name: 'oauth-request-dialog'; config: {}; configInput: {}; @@ -436,7 +436,7 @@ const appPlugin: FrontendPlugin< >; }; kind: 'app-root-element'; - namespace: 'app'; + namespace: undefined; name: 'alert-display'; }>; 'api:app/discovery': ExtensionDefinition<{ From 52f9c5a0124b832458728d9464e335fa9990f486 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Aug 2024 09:26:15 +0200 Subject: [PATCH 3/8] chore: changeset Signed-off-by: blam --- .changeset/fuzzy-feet-exist.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/fuzzy-feet-exist.md diff --git a/.changeset/fuzzy-feet-exist.md b/.changeset/fuzzy-feet-exist.md new file mode 100644 index 0000000000..2197da2f1f --- /dev/null +++ b/.changeset/fuzzy-feet-exist.md @@ -0,0 +1,6 @@ +--- +'@backstage/frontend-plugin-api': patch +'@backstage/plugin-app': patch +--- + +Deprecated the `namespace` option for `createExtensionBlueprint` and `createExtension`, these are no longer required and will default to the `pluginId` instead From 86ec8e170b595d2c756e206873e74af67bf10b2d Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Aug 2024 13:11:43 +0200 Subject: [PATCH 4/8] chore: added a console warning for deprecation as it's a little tricky to do in typescript Signed-off-by: blam --- .../src/wiring/resolveExtensionDefinition.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts index 870fb258f5..a6be1ded97 100644 --- a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts +++ b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts @@ -149,6 +149,7 @@ export function resolveExtensionDefinition< override: _skip2, ...rest } = internalDefinition; + const namespace = internalDefinition.namespace ?? context?.namespace; const namePart = @@ -161,6 +162,13 @@ export function resolveExtensionDefinition< const id = kind ? `${kind}:${namePart}` : namePart; + if (internalDefinition.namespace) { + // eslint-disable-next-line no-console + console.warn( + `Extension ${id} has a deprecated namespace set, this option is no longer required, and should be removed from createExtensionBlueprint or createExtension. It will be automatically set from the pluginId when installing extensions using createFrontendModule and createFrontendPlugin`, + ); + } + return { ...rest, $$type: '@backstage/Extension', From a3b48cc65ac0a147350d3f42836235ff1aaa9dc1 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Aug 2024 15:12:50 +0200 Subject: [PATCH 5/8] chore: rework how we do the deprecations Signed-off-by: blam --- packages/frontend-plugin-api/api-report.md | 166 +++++++++++++++++- .../src/wiring/createExtension.ts | 89 +++++++++- .../src/wiring/createExtensionBlueprint.ts | 155 +++++++++++++++- .../src/wiring/resolveExtensionDefinition.ts | 7 - 4 files changed, 401 insertions(+), 16 deletions(-) diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 9419efc05e..fbcd3a9caa 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -477,6 +477,55 @@ export function createComponentRef(options: { }): ComponentRef; // @public (undocumented) +export function createExtension< + UOutput extends AnyExtensionDataRef, + TInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { + optional: boolean; + singleton: boolean; + } + >; + }, + TConfigSchema extends { + [key: string]: (zImpl: typeof z) => z.ZodType; + }, + UFactoryOutput extends ExtensionDataValue, + const TKind extends string | undefined = undefined, + const TNamespace extends string | undefined = undefined, + const TName extends string | undefined = undefined, +>( + options: CreateExtensionOptions< + TKind, + undefined, + TName, + UOutput, + TInputs, + TConfigSchema, + UFactoryOutput + >, +): ExtensionDefinition<{ + config: string extends keyof TConfigSchema + ? {} + : { + [key in keyof TConfigSchema]: z.infer>; + }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + output: UOutput; + inputs: TInputs; + kind: string | undefined extends TKind ? undefined : TKind; + namespace: string | undefined extends TNamespace ? undefined : TNamespace; + name: string | undefined extends TName ? undefined : TName; +}>; + +// @public @deprecated (undocumented) export function createExtension< UOutput extends AnyExtensionDataRef, TInputs extends { @@ -543,7 +592,7 @@ export function createExtensionBlueprint< }, UFactoryOutput extends ExtensionDataValue, TKind extends string, - TNamespace extends string | undefined = undefined, + TNamespace extends undefined = undefined, TName extends string | undefined = undefined, TDataRefs extends { [name in string]: AnyExtensionDataRef; @@ -551,7 +600,7 @@ export function createExtensionBlueprint< >( options: CreateExtensionBlueprintOptions< TKind, - TNamespace, + undefined, TName, TParams, UOutput, @@ -562,7 +611,7 @@ export function createExtensionBlueprint< >, ): ExtensionBlueprint<{ kind: TKind; - namespace: TNamespace; + namespace: undefined; name: TName; params: TParams; output: UOutput; @@ -857,6 +906,28 @@ export interface ExtensionBlueprint< // (undocumented) dataRefs: T['dataRefs']; // (undocumented) + make< + TNewNamespace extends string | undefined, + TNewName extends string | undefined, + >(args: { + namespace?: undefined; + name?: TNewName; + attachTo?: { + id: string; + input: string; + }; + disabled?: boolean; + params: T['params']; + }): ExtensionDefinition<{ + kind: T['kind']; + namespace: undefined; + name: string | undefined extends TNewName ? T['name'] : TNewName; + config: T['config']; + configInput: T['configInput']; + output: T['output']; + inputs: T['inputs']; + }>; + // @deprecated (undocumented) make< TNewNamespace extends string | undefined, TNewName extends string | undefined, @@ -898,7 +969,94 @@ export interface ExtensionBlueprint< >; }, >(args: { - namespace?: TNewNamespace; + namespace?: undefined; + name?: TNewName; + attachTo?: { + id: string; + input: string; + }; + disabled?: boolean; + inputs?: TExtraInputs & { + [KName in keyof T['inputs']]?: `Error: Input '${KName & + string}' is already defined in parent definition`; + }; + output?: Array; + config?: { + schema: TExtensionConfigSchema & { + [KName in keyof T['config']]?: `Error: Config key '${KName & + string}' is already defined in parent schema`; + }; + }; + factory( + originalFactory: ( + params: T['params'], + context?: { + config?: T['config']; + inputs?: ResolveInputValueOverrides>; + }, + ) => ExtensionDataContainer>, + context: { + node: AppNode; + apis: ApiHolder; + config: T['config'] & { + [key in keyof TExtensionConfigSchema]: z.infer< + ReturnType + >; + }; + inputs: Expand>; + }, + ): Iterable & + VerifyExtensionFactoryOutput< + AnyExtensionDataRef extends UNewOutput + ? NonNullable + : UNewOutput, + UFactoryOutput + >; + }): ExtensionDefinition<{ + config: (string extends keyof TExtensionConfigSchema + ? {} + : { + [key in keyof TExtensionConfigSchema]: z.infer< + ReturnType + >; + }) & + T['config']; + configInput: (string extends keyof TExtensionConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TExtensionConfigSchema]: ReturnType< + TExtensionConfigSchema[key] + >; + }> + >) & + T['configInput']; + output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput; + inputs: T['inputs'] & TExtraInputs; + kind: T['kind']; + namespace: undefined; + name: string | undefined extends TNewName ? T['name'] : TNewName; + }>; + // @deprecated (undocumented) + makeWithOverrides< + TNewNamespace extends string | undefined, + TNewName extends string | undefined, + TExtensionConfigSchema extends { + [key in string]: (zImpl: typeof z) => z.ZodType; + }, + UFactoryOutput extends ExtensionDataValue, + UNewOutput extends AnyExtensionDataRef, + TExtraInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { + optional: boolean; + singleton: boolean; + } + >; + }, + >(args: { + namespace: TNewNamespace; name?: TNewName; attachTo?: { id: string; diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index ab999a2d0c..8c79758395 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -122,7 +122,6 @@ export type CreateExtensionOptions< UFactoryOutput extends ExtensionDataValue, > = { kind?: TKind; - /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ namespace?: TNamespace; name?: TName; attachTo: { id: string; input: string }; @@ -315,6 +314,94 @@ export function toInternalExtensionDefinition< } /** @public */ +export function createExtension< + UOutput extends AnyExtensionDataRef, + TInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { optional: boolean; singleton: boolean } + >; + }, + TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType }, + UFactoryOutput extends ExtensionDataValue, + const TKind extends string | undefined = undefined, + const TNamespace extends string | undefined = undefined, + const TName extends string | undefined = undefined, +>( + options: CreateExtensionOptions< + TKind, + undefined, + TName, + UOutput, + TInputs, + TConfigSchema, + UFactoryOutput + >, +): ExtensionDefinition<{ + config: string extends keyof TConfigSchema + ? {} + : { + [key in keyof TConfigSchema]: z.infer>; + }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + output: UOutput; + inputs: TInputs; + kind: string | undefined extends TKind ? undefined : TKind; + namespace: string | undefined extends TNamespace ? undefined : TNamespace; + name: string | undefined extends TName ? undefined : TName; +}>; +/** + * @public + * @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. + */ +export function createExtension< + UOutput extends AnyExtensionDataRef, + TInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { optional: boolean; singleton: boolean } + >; + }, + TConfigSchema extends { [key: string]: (zImpl: typeof z) => z.ZodType }, + UFactoryOutput extends ExtensionDataValue, + const TKind extends string | undefined = undefined, + const TNamespace extends string | undefined = undefined, + const TName extends string | undefined = undefined, +>( + options: CreateExtensionOptions< + TKind, + TNamespace, + TName, + UOutput, + TInputs, + TConfigSchema, + UFactoryOutput + >, +): ExtensionDefinition<{ + config: string extends keyof TConfigSchema + ? {} + : { + [key in keyof TConfigSchema]: z.infer>; + }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + output: UOutput; + inputs: TInputs; + kind: string | undefined extends TKind ? undefined : TKind; + namespace: string | undefined extends TNamespace ? undefined : TNamespace; + name: string | undefined extends TName ? undefined : TName; +}>; export function createExtension< UOutput extends AnyExtensionDataRef, TInputs extends { diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index de788473b5..f67b30c8df 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -57,7 +57,6 @@ export type CreateExtensionBlueprintOptions< TDataRefs extends { [name in string]: AnyExtensionDataRef }, > = { kind: TKind; - /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ namespace?: TNamespace; attachTo: { id: string; input: string }; disabled?: boolean; @@ -112,7 +111,25 @@ export interface ExtensionBlueprint< TNewNamespace extends string | undefined, TNewName extends string | undefined, >(args: { - /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ + namespace?: undefined; + name?: TNewName; + attachTo?: { id: string; input: string }; + disabled?: boolean; + params: T['params']; + }): ExtensionDefinition<{ + kind: T['kind']; + namespace: undefined; + name: string | undefined extends TNewName ? T['name'] : TNewName; + config: T['config']; + configInput: T['configInput']; + output: T['output']; + inputs: T['inputs']; + }>; + /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ + make< + TNewNamespace extends string | undefined, + TNewName extends string | undefined, + >(args: { namespace?: TNewNamespace; name?: TNewName; attachTo?: { id: string; input: string }; @@ -151,8 +168,88 @@ export interface ExtensionBlueprint< >; }, >(args: { - /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ - namespace?: TNewNamespace; + namespace?: undefined; + name?: TNewName; + attachTo?: { id: string; input: string }; + disabled?: boolean; + inputs?: TExtraInputs & { + [KName in keyof T['inputs']]?: `Error: Input '${KName & + string}' is already defined in parent definition`; + }; + output?: Array; + config?: { + schema: TExtensionConfigSchema & { + [KName in keyof T['config']]?: `Error: Config key '${KName & + string}' is already defined in parent schema`; + }; + }; + factory( + originalFactory: ( + params: T['params'], + context?: { + config?: T['config']; + inputs?: ResolveInputValueOverrides>; + }, + ) => ExtensionDataContainer>, + context: { + node: AppNode; + apis: ApiHolder; + config: T['config'] & { + [key in keyof TExtensionConfigSchema]: z.infer< + ReturnType + >; + }; + inputs: Expand>; + }, + ): Iterable & + VerifyExtensionFactoryOutput< + AnyExtensionDataRef extends UNewOutput + ? NonNullable + : UNewOutput, + UFactoryOutput + >; + }): ExtensionDefinition<{ + config: (string extends keyof TExtensionConfigSchema + ? {} + : { + [key in keyof TExtensionConfigSchema]: z.infer< + ReturnType + >; + }) & + T['config']; + configInput: (string extends keyof TExtensionConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TExtensionConfigSchema]: ReturnType< + TExtensionConfigSchema[key] + >; + }> + >) & + T['configInput']; + output: AnyExtensionDataRef extends UNewOutput ? T['output'] : UNewOutput; + inputs: T['inputs'] & TExtraInputs; + kind: T['kind']; + namespace: undefined; + name: string | undefined extends TNewName ? T['name'] : TNewName; + }>; + /** @deprecated namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ + makeWithOverrides< + TNewNamespace extends string | undefined, + TNewName extends string | undefined, + TExtensionConfigSchema extends { + [key in string]: (zImpl: typeof z) => z.ZodType; + }, + UFactoryOutput extends ExtensionDataValue, + UNewOutput extends AnyExtensionDataRef, + TExtraInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { optional: boolean; singleton: boolean } + >; + }, + >(args: { + namespace: TNewNamespace; name?: TNewName; attachTo?: { id: string; input: string }; disabled?: boolean; @@ -227,6 +324,56 @@ export interface ExtensionBlueprint< * * @public */ +export function createExtensionBlueprint< + TParams extends object, + UOutput extends AnyExtensionDataRef, + TInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { optional: boolean; singleton: boolean } + >; + }, + TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }, + UFactoryOutput extends ExtensionDataValue, + TKind extends string, + TNamespace extends undefined = undefined, + TName extends string | undefined = undefined, + TDataRefs extends { [name in string]: AnyExtensionDataRef } = never, +>( + options: CreateExtensionBlueprintOptions< + TKind, + undefined, + TName, + TParams, + UOutput, + TInputs, + TConfigSchema, + UFactoryOutput, + TDataRefs + >, +): ExtensionBlueprint<{ + kind: TKind; + namespace: undefined; + name: TName; + params: TParams; + output: UOutput; + inputs: string extends keyof TInputs ? {} : TInputs; + config: string extends keyof TConfigSchema + ? {} + : { [key in keyof TConfigSchema]: z.infer> }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + dataRefs: TDataRefs; +}>; +/** + * @public + * @deprcated the namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. + */ export function createExtensionBlueprint< TParams extends object, UOutput extends AnyExtensionDataRef, diff --git a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts index a6be1ded97..5a631819d7 100644 --- a/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts +++ b/packages/frontend-plugin-api/src/wiring/resolveExtensionDefinition.ts @@ -162,13 +162,6 @@ export function resolveExtensionDefinition< const id = kind ? `${kind}:${namePart}` : namePart; - if (internalDefinition.namespace) { - // eslint-disable-next-line no-console - console.warn( - `Extension ${id} has a deprecated namespace set, this option is no longer required, and should be removed from createExtensionBlueprint or createExtension. It will be automatically set from the pluginId when installing extensions using createFrontendModule and createFrontendPlugin`, - ); - } - return { ...rest, $$type: '@backstage/Extension', From 8c27b82078f4738d2d76231108c1066e69bf8e93 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Aug 2024 17:22:00 +0200 Subject: [PATCH 6/8] chore: need a separate type for the overload and for the implementation Signed-off-by: blam --- .../src/wiring/createExtensionBlueprint.ts | 48 ++++++++++++++++++- 1 file changed, 47 insertions(+), 1 deletion(-) diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index f67b30c8df..40d1284b15 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -372,8 +372,54 @@ export function createExtensionBlueprint< }>; /** * @public - * @deprcated the namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. + * @deprecated the namespace is no longer required, you can safely remove this option and it will default to the `pluginId`. It will be removed in a future release. */ +export function createExtensionBlueprint< + TParams extends object, + UOutput extends AnyExtensionDataRef, + TInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { optional: boolean; singleton: boolean } + >; + }, + TConfigSchema extends { [key in string]: (zImpl: typeof z) => z.ZodType }, + UFactoryOutput extends ExtensionDataValue, + TKind extends string, + TNamespace extends string | undefined = undefined, + TName extends string | undefined = undefined, + TDataRefs extends { [name in string]: AnyExtensionDataRef } = never, +>( + options: CreateExtensionBlueprintOptions< + TKind, + TNamespace, + TName, + TParams, + UOutput, + TInputs, + TConfigSchema, + UFactoryOutput, + TDataRefs + >, +): ExtensionBlueprint<{ + kind: TKind; + namespace: TNamespace; + name: TName; + params: TParams; + output: UOutput; + inputs: string extends keyof TInputs ? {} : TInputs; + config: string extends keyof TConfigSchema + ? {} + : { [key in keyof TConfigSchema]: z.infer> }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + dataRefs: TDataRefs; +}>; export function createExtensionBlueprint< TParams extends object, UOutput extends AnyExtensionDataRef, From 79310e935c54628073b03b037b2ed1e6e4299f33 Mon Sep 17 00:00:00 2001 From: blam Date: Fri, 30 Aug 2024 17:26:51 +0200 Subject: [PATCH 7/8] chore: derprecation Signed-off-by: blam --- packages/frontend-plugin-api/api-report.md | 57 ++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index fbcd3a9caa..276ca190a6 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -631,6 +631,63 @@ export function createExtensionBlueprint< dataRefs: TDataRefs; }>; +// @public @deprecated (undocumented) +export function createExtensionBlueprint< + TParams extends object, + UOutput extends AnyExtensionDataRef, + TInputs extends { + [inputName in string]: ExtensionInput< + AnyExtensionDataRef, + { + optional: boolean; + singleton: boolean; + } + >; + }, + TConfigSchema extends { + [key in string]: (zImpl: typeof z) => z.ZodType; + }, + UFactoryOutput extends ExtensionDataValue, + TKind extends string, + TNamespace extends string | undefined = undefined, + TName extends string | undefined = undefined, + TDataRefs extends { + [name in string]: AnyExtensionDataRef; + } = never, +>( + options: CreateExtensionBlueprintOptions< + TKind, + TNamespace, + TName, + TParams, + UOutput, + TInputs, + TConfigSchema, + UFactoryOutput, + TDataRefs + >, +): ExtensionBlueprint<{ + kind: TKind; + namespace: TNamespace; + name: TName; + params: TParams; + output: UOutput; + inputs: string extends keyof TInputs ? {} : TInputs; + config: string extends keyof TConfigSchema + ? {} + : { + [key in keyof TConfigSchema]: z.infer>; + }; + configInput: string extends keyof TConfigSchema + ? {} + : z.input< + z.ZodObject<{ + [key in keyof TConfigSchema]: ReturnType; + }> + >; + dataRefs: TDataRefs; +}>; + // @public (undocumented) export type CreateExtensionBlueprintOptions< TKind extends string, From aeea1adaa5eaf01dfd9cc25636f2090c92f56b6f Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 2 Sep 2024 15:35:36 +0200 Subject: [PATCH 8/8] chore: added some more info in changeset Signed-off-by: blam --- .changeset/fuzzy-feet-exist.md | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/.changeset/fuzzy-feet-exist.md b/.changeset/fuzzy-feet-exist.md index 2197da2f1f..35ef1e58fd 100644 --- a/.changeset/fuzzy-feet-exist.md +++ b/.changeset/fuzzy-feet-exist.md @@ -3,4 +3,32 @@ '@backstage/plugin-app': patch --- -Deprecated the `namespace` option for `createExtensionBlueprint` and `createExtension`, these are no longer required and will default to the `pluginId` instead +Deprecated the `namespace` option for `createExtensionBlueprint` and `createExtension`, these are no longer required and will default to the `pluginId` instead. + +You can migrate some of your extensions that use `createExtensionOverrides` to using `createFrontendModule` instead and providing a `pluginId` there. + +```ts +// Before +createExtensionOverrides({ + extensions: [ + createExtension({ + name: 'my-extension', + namespace: 'my-namespace', + kind: 'test', + ... + }) + ], +}); + +// After +createFrontendModule({ + pluginId: 'my-namespace', + extensions: [ + createExtension({ + name: 'my-extension', + kind: 'test', + ... + }) + ], +}); +```