From 5f388ca50154c43d1270dcc7d4ed4648fb37a0bc Mon Sep 17 00:00:00 2001 From: Patrik Oldsberg Date: Fri, 2 Sep 2022 15:39:36 +0200 Subject: [PATCH] backend-plugin-api: built-in options in service factories MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Fredrik Adelöw Signed-off-by: Patrik Oldsberg --- .../src/services/system/types.test.ts | 89 +++++++++++++++++++ .../src/services/system/types.ts | 18 +++- 2 files changed, 104 insertions(+), 3 deletions(-) create mode 100644 packages/backend-plugin-api/src/services/system/types.test.ts diff --git a/packages/backend-plugin-api/src/services/system/types.test.ts b/packages/backend-plugin-api/src/services/system/types.test.ts new file mode 100644 index 0000000000..29512d3a58 --- /dev/null +++ b/packages/backend-plugin-api/src/services/system/types.test.ts @@ -0,0 +1,89 @@ +/* + * Copyright 2022 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 { createServiceFactory, createServiceRef } from './types'; + +describe('createServiceFactory', () => { + it('should create a meta factory with no options', () => { + const ref = createServiceRef({ id: 'x' }); + const metaFactory = createServiceFactory({ + service: ref, + deps: {}, + async factory(_deps) { + return async () => 'x'; + }, + }); + expect(metaFactory).toEqual(expect.any(Function)); + expect(metaFactory().service).toBe(ref); + + // @ts-expect-error + metaFactory('string'); + // @ts-expect-error + metaFactory({}); + // @ts-expect-error + metaFactory({ x: 1 }); + // @ts-expect-error + metaFactory(null); + metaFactory(undefined); + metaFactory(); + }); + + it('should create a meta factory with optional options', () => { + const ref = createServiceRef({ id: 'x' }); + const metaFactory = createServiceFactory({ + service: ref, + deps: {}, + async factory(_deps, _opts?: { x: number }) { + return async () => 'x'; + }, + }); + expect(metaFactory).toEqual(expect.any(Function)); + + // @ts-expect-error + metaFactory('string'); + // @ts-expect-error + metaFactory({}); + metaFactory({ x: 1 }); + // @ts-expect-error + metaFactory(null); + metaFactory(undefined); + metaFactory(); + }); + + it('should create a meta factory with required options', () => { + const ref = createServiceRef({ id: 'x' }); + const metaFactory = createServiceFactory({ + service: ref, + deps: {}, + async factory(_deps, _opts: { x: number }) { + return async () => 'x'; + }, + }); + expect(metaFactory).toEqual(expect.any(Function)); + + // @ts-expect-error + metaFactory('string'); + // @ts-expect-error + metaFactory({}); + metaFactory({ x: 1 }); + // @ts-expect-error + metaFactory(null); + // @ts-expect-error + metaFactory(undefined); + // @ts-expect-error + metaFactory(); + }); +}); diff --git a/packages/backend-plugin-api/src/services/system/types.ts b/packages/backend-plugin-api/src/services/system/types.ts index d622b3917f..4737c6a0e8 100644 --- a/packages/backend-plugin-api/src/services/system/types.ts +++ b/packages/backend-plugin-api/src/services/system/types.ts @@ -90,10 +90,22 @@ export function createServiceFactory< TService, TImpl extends TService, TDeps extends { [name in string]: unknown }, + TOpts extends { [name in string]: unknown } | undefined = undefined, >(factory: { service: ServiceRef; deps: TypesToServiceRef; - factory(deps: DepsToDepFactories): Promise>; -}): ServiceFactory { - return factory as ServiceFactory; + factory( + deps: DepsToDepFactories, + options: TOpts, + ): Promise>; +}): undefined extends TOpts + ? (options?: TOpts) => ServiceFactory + : (options: TOpts) => ServiceFactory { + return (options?: TOpts) => ({ + service: factory.service, + deps: factory.deps, + factory(deps: DepsToDepFactories) { + return factory.factory(deps, options!); + }, + }); }