From 966cca176bc0506034499ce2cb622ebdffe2ca1b Mon Sep 17 00:00:00 2001 From: blam Date: Wed, 26 Jun 2024 16:31:25 +0200 Subject: [PATCH] chore: tidying up Signed-off-by: blam Signed-off-by: blam --- .../core-compat-api/src/convertLegacyApp.ts | 72 +---- packages/frontend-plugin-api/api-report.md | 214 ++++++++++----- .../src/wiring/createExtension.test.ts | 33 --- .../src/wiring/createExtension.ts | 125 +++------ .../src/wiring/createExtensionKind.test.tsx | 164 ++++++++++++ .../src/wiring/createExtensionKind.ts | 245 ++++++++++++++---- .../frontend-plugin-api/src/wiring/index.ts | 4 +- 7 files changed, 550 insertions(+), 307 deletions(-) diff --git a/packages/core-compat-api/src/convertLegacyApp.ts b/packages/core-compat-api/src/convertLegacyApp.ts index 567e5efcad..72ce4b5e61 100644 --- a/packages/core-compat-api/src/convertLegacyApp.ts +++ b/packages/core-compat-api/src/convertLegacyApp.ts @@ -26,7 +26,6 @@ import { coreExtensionData, createExtension, createExtensionInput, - createExtensionKind, createExtensionOverrides, } from '@backstage/frontend-plugin-api'; import { getComponentData } from '@backstage/core-plugin-api'; @@ -129,80 +128,21 @@ export function convertLegacyApp( }; }, }); - - const CoreNavOverride = CurrentCoreNav.override({ - // namespace: 'app', - // name: 'nav', - // attachTo: { id: 'app/layout', input: 'nav' }, - // output: {}, + const CoreNavOverride = createExtension({ + namespace: 'app', + name: 'nav', + attachTo: { id: 'app/layout', input: 'nav' }, + output: {}, factory: () => ({}), disabled: true, }); - createExtensionOverride({ - extension: CurrentCoreNav, - factory: () => null, - }); - const collectedRoutes = collectLegacyRoutes(routesEl); return [ ...collectedRoutes, createExtensionOverrides({ - extensions: [CoreNavOverride, CoreNavOverride], + extensions: [CoreLayoutOverride, CoreNavOverride], }), ]; } - -const EntityCardExtension = createExtensionKind({ - kind: 'entity-card', - attachTo: { id: 'entity-card', input: 'default' }, - inputs: { - loader: createExtensionInput({ - element: coreExtensionData.reactElement, - }), - }, - output: { - element: coreExtensionData.reactElement, - }, - factory({ inputs }, props: { title: string }) { - console.log(inputs.loader); - return { - element: React.createElement('h1'), - }; - }, -}); - -const GithubCard = EntityCardExtension.new({ - props: { - title: 'GitHub Card', - }, - factory({ inputs: { loader } }) { - console.log(loader); - return { - element: React.createElement('h2'), - }; - }, -}); - -GithubCard.override({ - attachTo: { id: 'entity-card', input: 'github' }, - inputs: { - loader: createExtensionInput( - { - element: coreExtensionData.reactElement, - }, - { singleton: false }, - ), - loader2: createExtensionInput({ - element: coreExtensionData.reactElement, - }), - }, - factory({ originalFactory, inputs }) { - inputs.loader2; - inputs.loader; - return originalFactory({ - inputsOverride: inputs, - }); - }, -}); diff --git a/packages/frontend-plugin-api/api-report.md b/packages/frontend-plugin-api/api-report.md index 48718f5375..6a04d04cd6 100644 --- a/packages/frontend-plugin-api/api-report.md +++ b/packages/frontend-plugin-api/api-report.md @@ -529,9 +529,91 @@ export function createExtensionKind< TOutput extends AnyExtensionDataMap, TConfig, >( - options: ExtensionKindOptions, + options: CreateExtensionKindOptions, ): ExtensionKind; +// @public (undocumented) +export interface CreateExtensionKindInstanceOptions< + TOptions, + TInputs extends AnyExtensionInputMap, + TOutput extends AnyExtensionDataMap, + TConfig, +> { + // (undocumented) + attachTo?: { + id: string; + input: string; + }; + // (undocumented) + configSchema?: PortableSchema; + // (undocumented) + disabled?: boolean; + // (undocumented) + factory?( + context: { + node: AppNode; + config: TConfig; + inputs: Expand>; + originalFactory( + context?: { + node?: AppNode; + config?: TConfig; + inputs?: Expand>; + }, + options?: TOptions, + ): Expand>; + }, + options: TOptions, + ): Expand>; + // (undocumented) + inputs?: TInputs; + // (undocumented) + name?: string; + // (undocumented) + namespace?: string; + // (undocumented) + options: TOptions; + // (undocumented) + output?: TOutput; +} + +// @public (undocumented) +export interface CreateExtensionKindOptions< + TOptions, + TInputs extends AnyExtensionInputMap, + TOutput extends AnyExtensionDataMap, + TConfig, +> { + // (undocumented) + attachTo: { + id: string; + input: string; + }; + // (undocumented) + configSchema?: PortableSchema; + // (undocumented) + disabled?: boolean; + // (undocumented) + factory( + context: { + node: AppNode; + config: TConfig; + inputs: Expand>; + }, + options: TOptions, + ): Expand>; + // (undocumented) + inputs?: TInputs; + // (undocumented) + kind: string; + // (undocumented) + name?: string; + // (undocumented) + namespace?: string; + // (undocumented) + output: TOutput; +} + // @public (undocumented) export interface CreateExtensionOptions< TOutput extends AnyExtensionDataMap, @@ -548,7 +630,7 @@ export interface CreateExtensionOptions< // (undocumented) disabled?: boolean; // (undocumented) - factory(context: { + factory(options: { node: AppNode; config: TConfig; inputs: Expand>; @@ -565,6 +647,51 @@ export interface CreateExtensionOptions< output: TOutput; } +// @public (undocumented) +export interface CreateExtensionOverrideKindInstanceOptions< + TOptions, + TInputs extends AnyExtensionInputMap, + TOutput extends AnyExtensionDataMap, + TConfig, +> { + // (undocumented) + attachTo?: { + id: string; + input: string; + }; + // (undocumented) + configSchema?: PortableSchema; + // (undocumented) + disabled?: boolean; + // (undocumented) + factory?( + context: { + node: AppNode; + config: TConfig; + inputs: Expand>; + originalFactory( + context?: { + node?: AppNode; + config?: TConfig; + inputs?: Expand>; + }, + options?: TOptions, + ): Expand>; + }, + options: TOptions, + ): Expand>; + // (undocumented) + inputs?: TInputs; + // (undocumented) + name?: string; + // (undocumented) + namespace?: string; + // (undocumented) + options?: TOptions; + // (undocumented) + output?: TOutput; +} + // @public (undocumented) export function createExtensionOverrides( options: ExtensionOverridesOptions, @@ -937,75 +1064,26 @@ export class ExtensionKind< TOutput extends AnyExtensionDataMap, TConfig, >( - options: ExtensionKindOptions, + options: CreateExtensionKindOptions, ): ExtensionKind; // (undocumented) - new(args: { - namespace?: string; - name?: string; - attachTo?: { - id: string; - input: string; - }; - disabled?: boolean; - inputs?: TInputs; - output?: TOutput; - configSchema?: PortableSchema; - options: TOptions; - factory?( - context: { - node: AppNode; - config: TConfig; - inputs: Expand>; - orignalFactory( - context?: { - node?: AppNode; - config?: TConfig; - inputs?: Expand>; - }, - options?: TOptions, - ): Expand>; - }, - options: TOptions, - ): Expand>; - }): ExtensionDefinition; -} - -// @public (undocumented) -export interface ExtensionKindOptions< - TOptions, - TInputs extends AnyExtensionInputMap, - TOutput extends AnyExtensionDataMap, - TConfig, -> { - // (undocumented) - attachTo: { - id: string; - input: string; + new( + instanceProperties: CreateExtensionKindInstanceOptions< + TOptions, + TInputs, + TOutput, + TConfig + >, + ): ExtensionDefinition & { + override: ( + overrides: CreateExtensionOverrideKindInstanceOptions< + TOptions, + TInputs, + TOutput, + TConfig + >, + ) => ExtensionDefinition; }; - // (undocumented) - configSchema?: PortableSchema; - // (undocumented) - disabled?: boolean; - // (undocumented) - factory( - context: { - node: AppNode; - config: TConfig; - inputs: Expand>; - }, - options: TOptions, - ): Expand>; - // (undocumented) - inputs?: TInputs; - // (undocumented) - kind: string; - // (undocumented) - name?: string; - // (undocumented) - namespace?: string; - // (undocumented) - output: TOutput; } // @public (undocumented) diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts index cfef69b0fe..42ab21db80 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.test.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.test.ts @@ -291,37 +291,4 @@ describe('createExtension', () => { 'ExtensionDefinition{namespace=test,attachTo=root@default}', ); }); - - describe('override', () => { - it('should create an extension override', () => { - const extension = createExtension({ - namespace: 'test', - attachTo: { id: 'root', input: 'default' }, - output: { - foo: stringData, - }, - factory() { - return { - foo: 'bar', - }; - }, - }); - - const override = extension.override({ - attachTo: { - id: 'root', - input: 'default2', - }, - factory() { - return { - foo: 'baz', - }; - }, - }); - - expect(String(override)).toBe( - 'ExtensionDefinition{namespace=test,attachTo=root@default2}', - ); - }); - }); }); diff --git a/packages/frontend-plugin-api/src/wiring/createExtension.ts b/packages/frontend-plugin-api/src/wiring/createExtension.ts index b56cc39fc9..be76fbc069 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtension.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtension.ts @@ -91,7 +91,7 @@ export interface CreateExtensionOptions< inputs?: TInputs; output: TOutput; configSchema?: PortableSchema; - factory(context: { + factory(options: { node: AppNode; config: TConfig; inputs: Expand>; @@ -99,33 +99,7 @@ export interface CreateExtensionOptions< } /** @public */ -export interface ExtensionDefinitionOverrides< - TOriginalConfig, - TOriginalInputs extends AnyExtensionInputMap, - TOverrideInputs extends AnyExtensionInputMap, -> { - readonly disabled?: boolean; - readonly attachTo?: { id: string; input: string }; - // TODO: inputs (only adding to the list? or redefine arity and superset of old type on existing input?) - // TODO: config (any merging needed on there?) - inputs?: TOverrideInputs; - factory?(options: { - node: AppNode; - config: TOriginalConfig; - inputs: Expand>; - originalFactory: (originalFactoryOptions?: { - inputsOverride?: ResolvedExtensionInputs< - TOriginalInputs & TOverrideInputs - >; - }) => ExtensionDataValues; - }): ExtensionDataValues; -} - -/** @public */ -export interface ExtensionDefinition< - TConfig, - TInputs extends AnyExtensionInputMap, -> { +export interface ExtensionDefinition { $$type: '@backstage/ExtensionDefinition'; readonly kind?: string; readonly namespace?: string; @@ -133,20 +107,15 @@ export interface ExtensionDefinition< readonly attachTo: { id: string; input: string }; readonly disabled: boolean; readonly configSchema?: PortableSchema; - override( - overrides: ExtensionDefinitionOverrides, - ): ExtensionDefinition; } /** @internal */ -export interface InternalExtensionDefinition< - TConfig, - TInputs extends AnyExtensionInputMap, -> extends ExtensionDefinition { +export interface InternalExtensionDefinition + extends ExtensionDefinition { readonly version: 'v1'; - readonly inputs: TInputs; + readonly inputs: AnyExtensionInputMap; readonly output: AnyExtensionDataMap; - factory(context: { + factory(options: { node: AppNode; config: TConfig; inputs: ResolvedExtensionInputs; @@ -154,13 +123,10 @@ export interface InternalExtensionDefinition< } /** @internal */ -export function toInternalExtensionDefinition< - TConfig, - TInputs extends AnyExtensionInputMap, ->( - overrides: ExtensionDefinition, -): InternalExtensionDefinition { - const internal = overrides as InternalExtensionDefinition; +export function toInternalExtensionDefinition( + overrides: ExtensionDefinition, +): InternalExtensionDefinition { + const internal = overrides as InternalExtensionDefinition; if (internal.$$type !== '@backstage/ExtensionDefinition') { throw new Error( `Invalid extension definition instance, bad type '${internal.$$type}'`, @@ -181,69 +147,38 @@ export function createExtension< TConfig = never, >( options: CreateExtensionOptions, -): ExtensionDefinition { - const { - kind, - namespace, - name, - attachTo, - disabled = false, - inputs = {} as TInputs, - output, - configSchema, - factory, - } = options; - +): ExtensionDefinition { return { $$type: '@backstage/ExtensionDefinition', version: 'v1', - kind, - namespace, - name, - attachTo, - disabled, - inputs, - output, - configSchema, - factory({ inputs: factoryInputs, ...rest }) { + kind: options.kind, + namespace: options.namespace, + name: options.name, + attachTo: options.attachTo, + disabled: options.disabled ?? false, + inputs: options.inputs ?? {}, + output: options.output, + configSchema: options.configSchema, + factory({ inputs, ...rest }) { // TODO: Simplify this, but TS wouldn't infer the input type for some reason - return factory({ - inputs: factoryInputs as Expand>, + return options.factory({ + inputs: inputs as Expand>, ...rest, }); }, toString() { const parts: string[] = []; - if (kind) { - parts.push(`kind=${kind}`); + if (options.kind) { + parts.push(`kind=${options.kind}`); } - if (namespace) { - parts.push(`namespace=${namespace}`); + if (options.namespace) { + parts.push(`namespace=${options.namespace}`); } - if (name) { - parts.push(`name=${name}`); + if (options.name) { + parts.push(`name=${options.name}`); } - parts.push(`attachTo=${attachTo.id}@${attachTo.input}`); + parts.push(`attachTo=${options.attachTo.id}@${options.attachTo.input}`); return `ExtensionDefinition{${parts.join(',')}}`; }, - override( - overrides: ExtensionDefinitionOverrides< - TConfig, - TInputs, - TOverrideInputs - >, - ): ExtensionDefinition { - return createExtension({ - kind, - namespace, - name, - attachTo: overrides.attachTo ?? attachTo, - disabled: overrides.disabled ?? disabled, - inputs: { ...inputs, ...overrides.inputs }, - output, - configSchema, - factory, - }); - }, - } as InternalExtensionDefinition; + } as InternalExtensionDefinition; } diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionKind.test.tsx b/packages/frontend-plugin-api/src/wiring/createExtensionKind.test.tsx index 3bdcd3a7cc..30c3e6ca44 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionKind.test.tsx +++ b/packages/frontend-plugin-api/src/wiring/createExtensionKind.test.tsx @@ -64,6 +64,7 @@ describe('createExtensionKind', () => { }, factory: expect.any(Function), toString: expect.any(Function), + override: expect.any(Function), version: 'v1', }); @@ -102,4 +103,167 @@ describe('createExtensionKind', () => { const { container } = createExtensionTester(extension).render(); expect(container.querySelector('h2')).toHaveTextContent('Hello, world!'); }); + + it('should allow calling of the default value from override', () => { + const TestExtension = createExtensionKind({ + kind: 'test-extension', + attachTo: { id: 'test', input: 'default' }, + output: { + element: coreExtensionData.reactElement, + }, + factory(_, options: { text: string }) { + return { + element:

{options.text}

, + }; + }, + }); + + const extension = TestExtension.new({ + name: 'my-extension', + options: { + text: 'Hello, world!', + }, + factory({ originalFactory }, options: { text: string }) { + const { element } = originalFactory(); + return { + element: ( +

+ {options.text} + {element} +

+ ), + }; + }, + }); + + expect(extension).toBeDefined(); + + const { container } = createExtensionTester(extension).render(); + + expect(container.querySelector('h2 h1')).toHaveTextContent('Hello, world!'); + }); + + it('should allow overriding options of the default value from override', () => { + const TestExtension = createExtensionKind({ + kind: 'test-extension', + attachTo: { id: 'test', input: 'default' }, + output: { + element: coreExtensionData.reactElement, + }, + factory(_, options: { text: string }) { + return { + element:

{options.text}

, + }; + }, + }); + + const extension = TestExtension.new({ + name: 'my-extension', + options: { + text: 'Hello, world!', + }, + factory({ originalFactory }, options: { text: string }) { + const { element } = originalFactory(undefined, { text: 'nothing!' }); + return { + element: ( +

+ {options.text} + {element} +

+ ), + }; + }, + }); + + expect(extension).toBeDefined(); + + const { container } = createExtensionTester(extension).render(); + + expect(container.querySelector('h2 h1')).toHaveTextContent('nothing!'); + }); + + describe('override', () => { + it('should allow overriding of the default factory', () => { + const TestExtension = createExtensionKind({ + kind: 'test-extension', + attachTo: { id: 'test', input: 'default' }, + output: { + element: coreExtensionData.reactElement, + }, + factory(_, options: { text: string }) { + return { + element:

{options.text}

, + }; + }, + }); + + const extension = TestExtension.new({ + name: 'my-extension', + options: { + text: 'Hello, world!', + }, + factory(_, options: { text: string }) { + return { + element:

{options.text}

, + }; + }, + }); + + const overridden = extension.override({ + factory({ originalFactory }, { text }) { + return { + element: ( +
+ {originalFactory().element} +

{text}

+
+ ), + }; + }, + }); + + const { container } = createExtensionTester(overridden).render(); + expect(container.querySelector('h2')).toHaveTextContent('Hello, world!'); + expect(container.querySelector('h3')).toHaveTextContent('Hello, world!'); + }); + }); + + it('should allow calling the kind factory if another factory is not defined in the instance', () => { + const TestExtension = createExtensionKind({ + kind: 'test-extension', + attachTo: { id: 'test', input: 'default' }, + output: { + element: coreExtensionData.reactElement, + }, + factory(_, options: { text: string }) { + return { + element:

{options.text}

, + }; + }, + }); + + const extension = TestExtension.new({ + name: 'my-extension', + options: { + text: 'Hello, world!', + }, + }); + + const overridden = extension.override({ + factory({ originalFactory }, { text }) { + return { + element: ( +
+ {originalFactory().element} +

{text}

+
+ ), + }; + }, + }); + + const { container } = createExtensionTester(overridden).render(); + expect(container.querySelector('h1')).toHaveTextContent('Hello, world!'); + expect(container.querySelector('h3')).toHaveTextContent('Hello, world!'); + }); }); diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionKind.ts b/packages/frontend-plugin-api/src/wiring/createExtensionKind.ts index 353fb8ab70..9813c9e50c 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionKind.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionKind.ts @@ -13,6 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + import { AppNode } from '../apis'; import { PortableSchema } from '../schema'; import { Expand } from '../types'; @@ -52,6 +53,76 @@ export interface CreateExtensionKindOptions< ): Expand>; } +/** + * @public + */ +export interface CreateExtensionKindInstanceOptions< + TOptions, + TInputs extends AnyExtensionInputMap, + TOutput extends AnyExtensionDataMap, + TConfig, +> { + namespace?: string; + name?: string; + attachTo?: { id: string; input: string }; + disabled?: boolean; + inputs?: TInputs; + output?: TOutput; + configSchema?: PortableSchema; + options: TOptions; + factory?( + context: { + node: AppNode; + config: TConfig; + inputs: Expand>; + originalFactory( + context?: { + node?: AppNode; + config?: TConfig; + inputs?: Expand>; + }, + options?: TOptions, + ): Expand>; + }, + options: TOptions, + ): Expand>; +} + +/** + * @public + */ +export interface CreateExtensionOverrideKindInstanceOptions< + TOptions, + TInputs extends AnyExtensionInputMap, + TOutput extends AnyExtensionDataMap, + TConfig, +> { + namespace?: string; + name?: string; + attachTo?: { id: string; input: string }; + disabled?: boolean; + inputs?: TInputs; + output?: TOutput; + configSchema?: PortableSchema; + options?: TOptions; + factory?( + context: { + node: AppNode; + config: TConfig; + inputs: Expand>; + originalFactory( + context?: { + node?: AppNode; + config?: TConfig; + inputs?: Expand>; + }, + options?: TOptions, + ): Expand>; + }, + options: TOptions, + ): Expand>; +} + /** * TODO: should we export an interface instead of a concrete class? * @public @@ -74,7 +145,7 @@ export class ExtensionKind< } private constructor( - private readonly options: CreateExtensionKindOptions< + private readonly kindProperties: CreateExtensionKindOptions< TOptions, TInputs, TOutput, @@ -82,49 +153,41 @@ export class ExtensionKind< >, ) {} - public new(args: { - namespace?: string; - name?: string; - attachTo?: { id: string; input: string }; - disabled?: boolean; - inputs?: TInputs; - output?: TOutput; - configSchema?: PortableSchema; - options: TOptions; - factory?( - context: { - node: AppNode; - config: TConfig; - inputs: Expand>; - orignalFactory( - context?: { - node?: AppNode; - config?: TConfig; - inputs?: Expand>; - }, - options?: TOptions, - ): Expand>; - }, - options: TOptions, - ): Expand>; - }): ExtensionDefinition { - return createExtension({ - kind: this.options.kind, - namespace: args.namespace ?? this.options.namespace, - name: args.name ?? this.options.name, - attachTo: args.attachTo ?? this.options.attachTo, - disabled: args.disabled ?? this.options.disabled, - inputs: args.inputs ?? this.options.inputs, - output: args.output ?? this.options.output, - configSchema: args.configSchema ?? this.options.configSchema, // TODO: some config merging or smth + public new( + instanceProperties: CreateExtensionKindInstanceOptions< + TOptions, + TInputs, + TOutput, + TConfig + >, + ): ExtensionDefinition & { + override: ( + overrides: CreateExtensionOverrideKindInstanceOptions< + TOptions, + TInputs, + TOutput, + TConfig + >, + ) => ExtensionDefinition; + } { + const extension = createExtension({ + kind: this.kindProperties.kind, + namespace: instanceProperties.namespace ?? this.kindProperties.namespace, + name: instanceProperties.name ?? this.kindProperties.name, + attachTo: instanceProperties.attachTo ?? this.kindProperties.attachTo, + disabled: instanceProperties.disabled ?? this.kindProperties.disabled, + inputs: instanceProperties.inputs ?? this.kindProperties.inputs, + output: instanceProperties.output ?? this.kindProperties.output, + configSchema: + instanceProperties.configSchema ?? this.kindProperties.configSchema, // TODO: some config merging or smth factory: ({ node, config, inputs }) => { - if (args.factory) { - return args.factory( + if (instanceProperties.factory) { + return instanceProperties.factory( { node, config, inputs, - orignalFactory: ( + originalFactory: ( innerContext?: { node?: AppNode; config?: TConfig; @@ -132,29 +195,123 @@ export class ExtensionKind< }, innerOptions?: TOptions, ) => - this.options.factory( + this.kindProperties.factory( { node: innerContext?.node ?? node, config: innerContext?.config ?? config, inputs: innerContext?.inputs ?? inputs, }, - innerOptions ?? args.options, + innerOptions ?? instanceProperties.options, ), }, - args.options, + instanceProperties.options, ); } - return this.options.factory( + return this.kindProperties.factory( { node, config, inputs, }, - args.options, + instanceProperties.options, ); }, }); + + return { + ...extension, + override: overrides => { + return createExtension({ + kind: this.kindProperties.kind, + namespace: + overrides.namespace ?? + instanceProperties.namespace ?? + this.kindProperties.namespace, + name: + overrides.name ?? + instanceProperties.name ?? + this.kindProperties.name, + attachTo: + overrides.attachTo ?? + instanceProperties.attachTo ?? + this.kindProperties.attachTo, + disabled: + overrides.disabled ?? + instanceProperties.disabled ?? + this.kindProperties.disabled, + inputs: + overrides.inputs ?? + instanceProperties.inputs ?? + this.kindProperties.inputs, + output: + overrides.output ?? + instanceProperties.output ?? + this.kindProperties.output, + configSchema: + overrides.configSchema ?? + instanceProperties.configSchema ?? + this.kindProperties.configSchema, // TODO: some config merging or smth + factory: ({ node, config, inputs }) => { + if (overrides.factory) { + return overrides.factory( + { + node, + config, + inputs, + originalFactory: ( + innerContext?: { + node?: AppNode; + config?: TConfig; + inputs?: Expand>; + }, + innerOptions?: TOptions, + ) => + instanceProperties.factory?.( + { + node: innerContext?.node ?? node, + config: innerContext?.config ?? config, + inputs: innerContext?.inputs ?? inputs, + originalFactory: this.kindProperties.factory, + }, + innerOptions ?? instanceProperties.options, + ) ?? + this.kindProperties.factory( + { + node, + config, + inputs, + }, + innerOptions ?? instanceProperties.options, + ), + }, + instanceProperties.options, + ); + } + + return ( + instanceProperties.factory?.( + { + node, + config, + inputs, + originalFactory: this.kindProperties.factory, + }, + instanceProperties.options, + ) ?? + this.kindProperties.factory( + { + node, + config, + inputs, + }, + instanceProperties.options, + ) + ); + }, + }); + }, + }; } } diff --git a/packages/frontend-plugin-api/src/wiring/index.ts b/packages/frontend-plugin-api/src/wiring/index.ts index 8fe9dc3a54..a312c0f06f 100644 --- a/packages/frontend-plugin-api/src/wiring/index.ts +++ b/packages/frontend-plugin-api/src/wiring/index.ts @@ -49,7 +49,9 @@ export { type FrontendFeature, } from './types'; export { - type CreateExtensionKindOptions as ExtensionKindOptions, + type CreateExtensionKindOptions, + type CreateExtensionKindInstanceOptions, + type CreateExtensionOverrideKindInstanceOptions, ExtensionKind, createExtensionKind, } from './createExtensionKind';