diff --git a/packages/frontend-plugin-api/src/extensions/ApiBlueprint.test.ts b/packages/frontend-plugin-api/src/extensions/ApiBlueprint.test.ts new file mode 100644 index 0000000000..99369c6acd --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/ApiBlueprint.test.ts @@ -0,0 +1,66 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createExtensionInput } from '../wiring'; +import { ApiBlueprint } from './ApiBlueprint'; +import { createApiFactory, createApiRef } from '@backstage/core-plugin-api'; + +describe('ApiBlueprint', () => { + it('should create an extension with sensible defaults', () => { + const api = createApiRef<{ foo: string }>({ id: 'test' }); + const factory = createApiFactory({ + api, + deps: {}, + factory: () => ({ foo: 'bar' }), + }); + + const extension = ApiBlueprint.make({ + params: { + factory, + }, + }); + + expect(extension).toMatchInlineSnapshot(); + }); + + it('should create an extension with custom factory', () => { + const api = createApiRef<{ foo: string }>({ id: 'test' }); + const factory = jest.fn(() => ({ foo: 'bar' })); + + const extension = ApiBlueprint.make({ + config: { + schema: { + test: z => z.string().default('test'), + }, + }, + inputs: { + test: createExtensionInput([ApiBlueprint.dataRefs.factory]), + }, + factory(originalFactory, { config: _config, inputs: _inputs }) { + return originalFactory({ + api, + factory: () => + createApiFactory({ + api, + deps: {}, + factory, + }), + }); + }, + }); + + expect(extension).toMatchInlineSnapshot(); + }); +}); diff --git a/packages/frontend-plugin-api/src/extensions/ApiBlueprint.ts b/packages/frontend-plugin-api/src/extensions/ApiBlueprint.ts new file mode 100644 index 0000000000..dd2130f2cb --- /dev/null +++ b/packages/frontend-plugin-api/src/extensions/ApiBlueprint.ts @@ -0,0 +1,50 @@ +/* + * Copyright 2024 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +import { createExtensionBlueprint } from '../wiring'; +import { createApiExtension } from './createApiExtension'; +import { AnyApiFactory, AnyApiRef } from '@backstage/core-plugin-api'; + +export const ApiBlueprint = createExtensionBlueprint({ + kind: 'api', + attachTo: { id: 'app', input: 'apis' }, + output: [createApiExtension.factoryDataRef], + dataRefs: { + factory: createApiExtension.factoryDataRef, + }, + *factory( + params: // remove this form. + | { + api: AnyApiRef; + factory: (params: unknown) => AnyApiFactory; + } + | { + factory: AnyApiFactory; + }, + { config, inputs }, + ) { + yield createApiExtension.factoryDataRef( + typeof params.factory === 'function' + ? params.factory({ config, inputs }) + : params.factory, + ); + }, + namespace: params => { + const apiRef = + 'api' in params ? params.api : (params.factory as { api: AnyApiRef }).api; + + return apiRef.id; + }, +}); diff --git a/packages/frontend-plugin-api/src/extensions/PageBlueprint.tsx b/packages/frontend-plugin-api/src/extensions/PageBlueprint.tsx index 4ee26321b7..506301ffdf 100644 --- a/packages/frontend-plugin-api/src/extensions/PageBlueprint.tsx +++ b/packages/frontend-plugin-api/src/extensions/PageBlueprint.tsx @@ -38,16 +38,13 @@ export const PageBlueprint = createExtensionBlueprint({ routeRef, }: { defaultPath?: string; - loader: (opts: { - config: typeof config; - inputs: typeof inputs; - }) => Promise; + loader: () => Promise; routeRef?: RouteRef; }, - { config, inputs, node }, + { config, node }, ) { const ExtensionComponent = lazy(() => - loader({ config, inputs }).then(element => ({ default: () => element })), + loader().then(element => ({ default: () => element })), ); yield coreExtensionData.routePath(config.path ?? defaultPath!);