From 765d91aa0b75cbf8fac5c4b4331de2af4cda5b04 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 5 Aug 2024 09:20:02 +0200 Subject: [PATCH 1/4] chore: added failing test for callback form Signed-off-by: blam --- .../wiring/createExtensionBlueprint.test.tsx | 56 +++++++++++++++++++ .../src/wiring/createExtensionBlueprint.ts | 7 ++- 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx index 6cf10d7f08..38e92fc26a 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx @@ -326,4 +326,60 @@ describe('createExtensionBlueprint', () => { expect(true).toBe(true); }); + + it('should allow providing callback for properties to set with params', () => { + const Blueprint = createExtensionBlueprint({ + kind: 'test-extension', + attachTo: { id: 'test', input: 'default' }, + output: [coreExtensionData.reactElement], + namespace: props => props.test, + name: props => `${props.test}-name`, + config: { + schema: props => ({ + test: z => z.string().default(props.test), + }), + }, + factory(params: { test: string }) { + 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": "test", + "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..4a8f4a7c46 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -47,14 +47,14 @@ export type CreateExtensionBlueprintOptions< UFactoryOutput extends ExtensionDataValue, TDataRefs extends { [name in string]: AnyExtensionDataRef }, > = { - kind: string; - namespace?: string; + kind: string | ((params: TParams) => string); + namespace?: string | ((params: TParams) => string); attachTo: { id: string; input: string }; disabled?: boolean; inputs?: TInputs; output: Array; config?: { - schema: TConfigSchema; + schema: TConfigSchema | ((params: TParams) => TConfigSchema); }; factory( params: TParams, @@ -254,6 +254,7 @@ class ExtensionBlueprintImpl< ...this.options.config?.schema, ...args.config?.schema, } as TConfigSchema & TExtensionConfigSchema; + return createExtension({ kind: this.options.kind, namespace: args.namespace ?? this.options.namespace, From 6ec1f48baf47f3a529c92698224d4864fd2bb9c6 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 5 Aug 2024 16:15:07 +0200 Subject: [PATCH 2/4] chore: supporting overriding using a function Signed-off-by: blam --- .../wiring/createExtensionBlueprint.test.tsx | 12 ++++++---- .../src/wiring/createExtensionBlueprint.ts | 24 +++++++++++++++---- 2 files changed, 27 insertions(+), 9 deletions(-) diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx index 38e92fc26a..dfdbfface6 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx @@ -328,18 +328,20 @@ describe('createExtensionBlueprint', () => { }); 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 => props.test, - name: props => `${props.test}-name`, + namespace: (props: TestParams) => props.test, config: { - schema: props => ({ + schema: (props: TestParams) => ({ test: z => z.string().default(props.test), }), }, - factory(params: { test: string }) { + factory(params: TestParams) { return [coreExtensionData.reactElement(
{params.test}
)]; }, }); @@ -359,7 +361,7 @@ describe('createExtensionBlueprint', () => { "additionalProperties": false, "properties": { "test": { - "default": "test", + "default": "hello", "type": "string", }, }, diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index 4a8f4a7c46..46db278bf8 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -47,12 +47,13 @@ export type CreateExtensionBlueprintOptions< UFactoryOutput extends ExtensionDataValue, TDataRefs extends { [name in string]: AnyExtensionDataRef }, > = { - kind: string | ((params: TParams) => string); + kind: 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 | ((params: TParams) => TConfigSchema); }; @@ -250,15 +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, From 210d066af41579732ee9b2862f47bf1b6f36e217 Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 5 Aug 2024 16:16:51 +0200 Subject: [PATCH 3/4] chore: added changeset Signed-off-by: blam --- .changeset/chilly-days-peel.md | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .changeset/chilly-days-peel.md 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. From cfbffadf638a5758599223afb08fc4ad483ea82e Mon Sep 17 00:00:00 2001 From: blam Date: Mon, 5 Aug 2024 16:33:57 +0200 Subject: [PATCH 4/4] chore: api-reports Signed-off-by: blam --- packages/frontend-plugin-api/api-report.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) 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,