backend-plugin-api: allow service factories to be sync

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2023-01-14 12:46:29 +01:00
parent c1369c2cf4
commit f8c313f80f
5 changed files with 74 additions and 15 deletions
@@ -26,7 +26,7 @@ export const loggerFactory = createServiceFactory({
rootLogger: coreServices.rootLogger,
plugin: coreServices.pluginMetadata,
},
async factory({ rootLogger, plugin }) {
factory({ rootLogger, plugin }) {
return rootLogger.child({ plugin: plugin.getId() });
},
});
+3 -3
View File
@@ -305,14 +305,14 @@ export interface PluginServiceFactoryConfig<
// (undocumented)
createRootContext?(
deps: ServiceRefsToInstances<TDeps, 'root'>,
): Promise<TContext>;
): TContext | Promise<TContext>;
// (undocumented)
deps: TDeps;
// (undocumented)
factory(
deps: ServiceRefsToInstances<TDeps>,
context: TContext,
): Promise<TImpl>;
): TImpl | Promise<TImpl>;
// (undocumented)
service: ServiceRef<TService, 'plugin'>;
}
@@ -383,7 +383,7 @@ export interface RootServiceFactoryConfig<
// (undocumented)
deps: TDeps;
// (undocumented)
factory(deps: ServiceRefsToInstances<TDeps, 'root'>): Promise<TImpl>;
factory(deps: ServiceRefsToInstances<TDeps, 'root'>): TImpl | Promise<TImpl>;
// (undocumented)
service: ServiceRef<TService, 'root'>;
}
@@ -26,7 +26,56 @@ interface TestOptions {
function unused(..._any: any[]) {}
describe('createServiceFactory', () => {
it('should create a meta factory with no options', () => {
it('should create a sync factory with no options', () => {
const metaFactory = createServiceFactory({
service: ref,
deps: {},
createRootContext() {},
factory(_deps) {
return '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);
// @ts-expect-error
metaFactory(undefined);
metaFactory();
});
it('should create a sync root factory with no options', () => {
const metaFactory = createServiceFactory({
service: rootDep,
deps: {},
factory(_deps) {
return 0;
},
});
expect(metaFactory).toEqual(expect.any(Function));
expect(metaFactory().service).toBe(rootDep);
// @ts-expect-error
metaFactory('string');
// @ts-expect-error
metaFactory({});
// @ts-expect-error
metaFactory({ x: 1 });
// @ts-expect-error
metaFactory(null);
// @ts-expect-error
metaFactory(undefined);
metaFactory();
});
it('should create a factory with no options', () => {
const metaFactory = createServiceFactory({
service: ref,
deps: {},
@@ -51,7 +100,7 @@ describe('createServiceFactory', () => {
metaFactory();
});
it('should create a meta factory with optional options', () => {
it('should create a factory with optional options', () => {
const metaFactory = createServiceFactory((_opts?: { x: number }) => ({
service: ref,
deps: {},
@@ -75,7 +124,7 @@ describe('createServiceFactory', () => {
metaFactory();
});
it('should create a meta factory with required options', () => {
it('should create a factory with required options', () => {
const metaFactory = createServiceFactory((_opts: { x: number }) => ({
service: ref,
deps: {},
@@ -101,7 +150,7 @@ describe('createServiceFactory', () => {
metaFactory();
});
it('should create a meta factory with optional options as interface', () => {
it('should create a factory with optional options as interface', () => {
const metaFactory = createServiceFactory((_opts?: TestOptions) => ({
service: ref,
deps: {},
@@ -125,7 +174,7 @@ describe('createServiceFactory', () => {
metaFactory();
});
it('should create a meta factory with required options as interface', () => {
it('should create a factory with required options as interface', () => {
const metaFactory = createServiceFactory((_opts: TestOptions) => ({
service: ref,
deps: {},
@@ -144,7 +144,7 @@ export interface RootServiceFactoryConfig<
> {
service: ServiceRef<TService, 'root'>;
deps: TDeps;
factory(deps: ServiceRefsToInstances<TDeps, 'root'>): Promise<TImpl>;
factory(deps: ServiceRefsToInstances<TDeps, 'root'>): TImpl | Promise<TImpl>;
}
/** @public */
@@ -158,11 +158,11 @@ export interface PluginServiceFactoryConfig<
deps: TDeps;
createRootContext?(
deps: ServiceRefsToInstances<TDeps, 'root'>,
): Promise<TContext>;
): TContext | Promise<TContext>;
factory(
deps: ServiceRefsToInstances<TDeps>,
context: TContext,
): Promise<TImpl>;
): TImpl | Promise<TImpl>;
}
/**
@@ -278,6 +278,16 @@ export function createServiceFactory<
const configCallback = typeof config === 'function' ? config : () => config;
return (options: TOpts) => {
const c = configCallback(options);
return { ...c, scope: c.service.scope } as ServiceFactory<TService>;
return {
...c,
...('createRootContext' in c
? {
createRootContext: async (deps: TDeps) =>
c?.createRootContext?.(deps),
}
: {}),
factory: async (deps: TDeps, ctx: TContext) => c.factory(deps, ctx),
scope: c.service.scope,
} as ServiceFactory<TService>;
};
}