backend-plugin-api: make factory funcs use params and switch service factories to new pattern
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -16,9 +16,12 @@
|
||||
|
||||
import { createServiceFactory, createServiceRef } from './types';
|
||||
|
||||
const ref = createServiceRef<string>({ id: 'x' });
|
||||
const rootDep = createServiceRef<number>({ id: 'y', scope: 'root' });
|
||||
const pluginDep = createServiceRef<boolean>({ id: 'z' });
|
||||
|
||||
describe('createServiceFactory', () => {
|
||||
it('should create a meta factory with no options', () => {
|
||||
const ref = createServiceRef<string>({ id: 'x' });
|
||||
const metaFactory = createServiceFactory({
|
||||
service: ref,
|
||||
deps: {},
|
||||
@@ -37,12 +40,12 @@ describe('createServiceFactory', () => {
|
||||
metaFactory({ x: 1 });
|
||||
// @ts-expect-error
|
||||
metaFactory(null);
|
||||
// @ts-expect-error
|
||||
metaFactory(undefined);
|
||||
metaFactory();
|
||||
});
|
||||
|
||||
it('should create a meta factory with optional options', () => {
|
||||
const ref = createServiceRef<string>({ id: 'x' });
|
||||
const metaFactory = createServiceFactory((_opts?: { x: number }) => ({
|
||||
service: ref,
|
||||
deps: {},
|
||||
@@ -66,7 +69,6 @@ describe('createServiceFactory', () => {
|
||||
});
|
||||
|
||||
it('should create a meta factory with required options', () => {
|
||||
const ref = createServiceRef<string>({ id: 'x' });
|
||||
const metaFactory = createServiceFactory((_opts: { x: number }) => ({
|
||||
service: ref,
|
||||
deps: {},
|
||||
@@ -95,7 +97,6 @@ describe('createServiceFactory', () => {
|
||||
interface TestOptions {
|
||||
x: number;
|
||||
}
|
||||
const ref = createServiceRef<string>({ id: 'x' });
|
||||
const metaFactory = createServiceFactory((_opts?: TestOptions) => ({
|
||||
service: ref,
|
||||
deps: {},
|
||||
@@ -122,7 +123,6 @@ describe('createServiceFactory', () => {
|
||||
interface TestOptions {
|
||||
x: number;
|
||||
}
|
||||
const ref = createServiceRef<string>({ id: 'x' });
|
||||
const metaFactory = createServiceFactory((_opts: TestOptions) => ({
|
||||
service: ref,
|
||||
deps: {},
|
||||
@@ -147,8 +147,91 @@ describe('createServiceFactory', () => {
|
||||
metaFactory();
|
||||
});
|
||||
|
||||
it('should create factory with required options and dependencies', () => {
|
||||
interface TestOptions {
|
||||
x: number;
|
||||
}
|
||||
|
||||
function unused(..._any: any[]) {}
|
||||
|
||||
const metaFactory = createServiceFactory((_opts: TestOptions) => ({
|
||||
service: ref,
|
||||
deps: {
|
||||
root: rootDep,
|
||||
plugin: pluginDep,
|
||||
},
|
||||
async factory({ root }) {
|
||||
const root1: number = root;
|
||||
// @ts-expect-error
|
||||
const root2: string = root;
|
||||
return async ({ plugin }) => {
|
||||
const plugin3: boolean = plugin;
|
||||
// @ts-expect-error
|
||||
const plugin4: number = plugin;
|
||||
unused(root1, root2, plugin3, plugin4);
|
||||
return 'x';
|
||||
};
|
||||
},
|
||||
}));
|
||||
expect(metaFactory).toEqual(expect.any(Function));
|
||||
|
||||
// @ts-expect-error
|
||||
metaFactory('string');
|
||||
// @ts-expect-error
|
||||
metaFactory({});
|
||||
metaFactory({ x: 1 });
|
||||
// @ts-expect-error
|
||||
metaFactory({ x: 1, y: 2 });
|
||||
// @ts-expect-error
|
||||
metaFactory(null);
|
||||
// @ts-expect-error
|
||||
metaFactory(undefined);
|
||||
// @ts-expect-error
|
||||
metaFactory();
|
||||
});
|
||||
|
||||
it('should create factory with optional options and dependencies', () => {
|
||||
interface TestOptions {
|
||||
x: number;
|
||||
}
|
||||
|
||||
function unused(..._any: any[]) {}
|
||||
|
||||
const metaFactory = createServiceFactory((_opts?: TestOptions) => ({
|
||||
service: ref,
|
||||
deps: {
|
||||
root: rootDep,
|
||||
plugin: pluginDep,
|
||||
},
|
||||
async factory({ root }) {
|
||||
const root1: number = root;
|
||||
// @ts-expect-error
|
||||
const root2: string = root;
|
||||
return async ({ plugin }) => {
|
||||
const plugin3: boolean = plugin;
|
||||
// @ts-expect-error
|
||||
const plugin4: number = plugin;
|
||||
unused(root1, root2, plugin3, plugin4);
|
||||
return 'x';
|
||||
};
|
||||
},
|
||||
}));
|
||||
expect(metaFactory).toEqual(expect.any(Function));
|
||||
|
||||
// @ts-expect-error
|
||||
metaFactory('string');
|
||||
// @ts-expect-error
|
||||
metaFactory({});
|
||||
metaFactory({ x: 1 });
|
||||
// @ts-expect-error
|
||||
metaFactory({ x: 1, y: 2 });
|
||||
// @ts-expect-error
|
||||
metaFactory(null);
|
||||
metaFactory(undefined);
|
||||
metaFactory();
|
||||
});
|
||||
|
||||
it('should only allow objects as options', () => {
|
||||
const ref = createServiceRef<string>({ id: 'x' });
|
||||
// @ts-expect-error
|
||||
const metaFactory = createServiceFactory((_opts: string) => ({
|
||||
service: ref,
|
||||
|
||||
@@ -14,11 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
FactoryFunctionConfig,
|
||||
FactoryFunctionWithOptions,
|
||||
MaybeOptions,
|
||||
} from '../../types';
|
||||
import { FactoryFunctionConfig, FactoryFunction } from '../../types';
|
||||
|
||||
/**
|
||||
* TODO
|
||||
@@ -137,9 +133,7 @@ type ServiceRefsToInstances<
|
||||
T extends { [key in string]: ServiceRef<unknown> },
|
||||
TScope extends 'root' | 'plugin' = 'root' | 'plugin',
|
||||
> = {
|
||||
[name in {
|
||||
[key in keyof T]: T[key] extends ServiceRef<unknown, TScope> ? key : never;
|
||||
}[keyof T]]: T[name] extends ServiceRef<infer TImpl> ? TImpl : never;
|
||||
[key in keyof T as T[key]['scope'] extends TScope ? key : never]: T[key]['T'];
|
||||
};
|
||||
|
||||
/** @public */
|
||||
@@ -166,16 +160,16 @@ export function createServiceFactory<
|
||||
TScope extends 'root' | 'plugin',
|
||||
TImpl extends TService,
|
||||
TDeps extends { [name in string]: ServiceRef<unknown> },
|
||||
TOpts extends MaybeOptions = undefined,
|
||||
TOpts extends [options?: object] = [],
|
||||
>(
|
||||
config: FactoryFunctionConfig<
|
||||
ServiceFactoryConfig<TService, TScope, TImpl, TDeps>,
|
||||
TOpts
|
||||
>,
|
||||
): FactoryFunctionWithOptions<ServiceFactory<TService>, TOpts> {
|
||||
): FactoryFunction<ServiceFactory<TService>, TOpts> {
|
||||
if (typeof config === 'function') {
|
||||
return (opts?: TOpts) => {
|
||||
const c = config(opts!);
|
||||
return (...opts: TOpts) => {
|
||||
const c = config(...opts);
|
||||
return { ...c, scope: c.service.scope } as ServiceFactory<TService>;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -15,26 +15,17 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Base type for options objects that aren't required.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
export type MaybeOptions = object | undefined;
|
||||
|
||||
/**
|
||||
* @ignore
|
||||
*/
|
||||
export type FactoryFunctionConfig<TConfig, TOptions> =
|
||||
export type FactoryFunctionConfig<TConfig, TParams extends unknown[]> =
|
||||
| TConfig
|
||||
| ((options: TOptions) => TConfig)
|
||||
| (() => TConfig);
|
||||
| ((...params: TParams) => TConfig);
|
||||
|
||||
/**
|
||||
* Helper type that makes the options argument optional if options are not required.
|
||||
*
|
||||
* @ignore
|
||||
*/
|
||||
export type FactoryFunctionWithOptions<TResult, TOptions> =
|
||||
undefined extends TOptions
|
||||
? (options?: TOptions) => TResult
|
||||
: (options: TOptions) => TResult;
|
||||
export type FactoryFunction<TResult, TParams extends unknown[]> = (
|
||||
...params: TParams
|
||||
) => TResult;
|
||||
|
||||
@@ -14,11 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import {
|
||||
FactoryFunctionWithOptions,
|
||||
MaybeOptions,
|
||||
FactoryFunctionConfig,
|
||||
} from '../types';
|
||||
import { FactoryFunction, FactoryFunctionConfig } from '../types';
|
||||
import {
|
||||
BackendRegistrationPoints,
|
||||
BackendFeature,
|
||||
@@ -53,11 +49,11 @@ export interface BackendPluginConfig {
|
||||
}
|
||||
|
||||
/** @public */
|
||||
export function createBackendPlugin<TOptions extends MaybeOptions = undefined>(
|
||||
export function createBackendPlugin<TOptions extends [options?: object] = []>(
|
||||
config: FactoryFunctionConfig<BackendPluginConfig, TOptions>,
|
||||
): FactoryFunctionWithOptions<BackendFeature, TOptions> {
|
||||
): FactoryFunction<BackendFeature, TOptions> {
|
||||
if (typeof config === 'function') {
|
||||
return config as FactoryFunctionWithOptions<BackendFeature, TOptions>;
|
||||
return config as FactoryFunction<BackendFeature, TOptions>;
|
||||
}
|
||||
|
||||
return () => config;
|
||||
@@ -86,12 +82,12 @@ export interface BackendModuleConfig {
|
||||
*
|
||||
* The `pluginId` should exactly match the `id` of the plugin that the module extends.
|
||||
*/
|
||||
export function createBackendModule<TOptions extends MaybeOptions = undefined>(
|
||||
export function createBackendModule<TOptions extends [options?: object] = []>(
|
||||
config: FactoryFunctionConfig<BackendModuleConfig, TOptions>,
|
||||
): FactoryFunctionWithOptions<BackendFeature, TOptions> {
|
||||
): FactoryFunction<BackendFeature, TOptions> {
|
||||
if (typeof config === 'function') {
|
||||
return (options?: TOptions) => {
|
||||
const c = config(options!);
|
||||
return (...options: TOptions) => {
|
||||
const c = config(...options);
|
||||
return {
|
||||
id: `${c.pluginId}.${c.moduleId}`,
|
||||
register: c.register,
|
||||
|
||||
Reference in New Issue
Block a user