diff --git a/.changeset/chilly-days-peel.md b/.changeset/chilly-days-peel.md new file mode 100644 index 0000000000..d82344d364 --- /dev/null +++ b/.changeset/chilly-days-peel.md @@ -0,0 +1,5 @@ +--- +'@backstage/frontend-plugin-api': patch +--- + +Added support for using the `params` in other properties of the `createExtensionBlueprint` options by providing a callback. diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index d37f0a3a56..8d8dd05bf2 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -662,7 +662,7 @@ export type CreateExtensionBlueprintOptions< }, > = { kind: string; - namespace?: string; + namespace?: string | ((params: TParams) => string); attachTo: { id: string; input: string; @@ -670,8 +670,9 @@ export type CreateExtensionBlueprintOptions< disabled?: boolean; inputs?: TInputs; output: Array; + name?: string | ((params: TParams) => string); config?: { - schema: TConfigSchema; + schema: TConfigSchema | ((params: TParams) => TConfigSchema); }; factory( params: TParams, diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx index 6cf10d7f08..dfdbfface6 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx @@ -326,4 +326,62 @@ describe('createExtensionBlueprint', () => { expect(true).toBe(true); }); + + it('should allow providing callback for properties to set with params', () => { + type TestParams = { test: string }; + + const Blueprint = createExtensionBlueprint({ + kind: 'test-extension', + attachTo: { id: 'test', input: 'default' }, + name: (params: TestParams) => `${params.test}-name`, + output: [coreExtensionData.reactElement], + namespace: (props: TestParams) => props.test, + config: { + schema: (props: TestParams) => ({ + test: z => z.string().default(props.test), + }), + }, + factory(params: TestParams) { + return [coreExtensionData.reactElement(
{params.test}
)]; + }, + }); + + expect(Blueprint.make({ params: { test: 'hello' } })) + .toMatchInlineSnapshot(` + { + "$$type": "@backstage/ExtensionDefinition", + "attachTo": { + "id": "test", + "input": "default", + }, + "configSchema": { + "parse": [Function], + "schema": { + "$schema": "http://json-schema.org/draft-07/schema#", + "additionalProperties": false, + "properties": { + "test": { + "default": "hello", + "type": "string", + }, + }, + "type": "object", + }, + }, + "disabled": false, + "factory": [Function], + "inputs": {}, + "kind": "test-extension", + "name": "hello-name", + "namespace": "hello", + "output": [ + [Function], + ], + "toString": [Function], + "version": "v2", + } + `); + + expect(true).toBe(true); + }); }); diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index b579cc207a..46db278bf8 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -48,13 +48,14 @@ export type CreateExtensionBlueprintOptions< TDataRefs extends { [name in string]: AnyExtensionDataRef }, > = { kind: string; - namespace?: string; + namespace?: string | ((params: TParams) => string); attachTo: { id: string; input: string }; disabled?: boolean; inputs?: TInputs; output: Array; + name?: string | ((params: TParams) => string); config?: { - schema: TConfigSchema; + schema: TConfigSchema | ((params: TParams) => TConfigSchema); }; factory( params: TParams, @@ -250,14 +251,30 @@ class ExtensionBlueprintImpl< > > > { + const optionsSchema = + typeof this.options.config?.schema === 'function' + ? this.options.config?.schema(args.params!) + : this.options.config?.schema; + const schema = { - ...this.options.config?.schema, + ...optionsSchema, ...args.config?.schema, } as TConfigSchema & TExtensionConfigSchema; + + const namespace = + typeof this.options.namespace === 'function' + ? this.options.namespace(args.params!) + : this.options.namespace; + + const name = + typeof this.options.name === 'function' + ? this.options.name(args.params!) + : this.options.name; + return createExtension({ kind: this.options.kind, - namespace: args.namespace ?? this.options.namespace, - name: args.name, + namespace: args.namespace ?? namespace, + name: args.name ?? name, attachTo: args.attachTo ?? this.options.attachTo, disabled: args.disabled ?? this.options.disabled, inputs: args.inputs ?? this.options.inputs,