feat: start implementing multiple service factories

Co-authored-by: Patrik Oldsberg <poldsberg@gmail.com>
Signed-off-by: Camila Belo <camilaibs@gmail.com>
This commit is contained in:
Camila Belo
2024-07-08 16:08:04 +02:00
committed by Patrik Oldsberg
parent 88ed7f5926
commit 11aaaa496a
33 changed files with 563 additions and 250 deletions
+90 -33
View File
@@ -156,7 +156,7 @@ export namespace mockServices {
// (undocumented)
export namespace auth {
const // (undocumented)
factory: ServiceFactoryCompat<AuthService, 'plugin', undefined>;
factory: ServiceFactoryCompat<AuthService, 'plugin', true, undefined>;
const // (undocumented)
mock: (
partialImpl?: Partial<AuthService> | undefined,
@@ -165,7 +165,7 @@ export namespace mockServices {
// (undocumented)
export namespace cache {
const // (undocumented)
factory: ServiceFactoryCompat<CacheService, 'plugin', undefined>;
factory: ServiceFactoryCompat<CacheService, 'plugin', true, undefined>;
const // (undocumented)
mock: (
partialImpl?: Partial<CacheService> | undefined,
@@ -174,7 +174,7 @@ export namespace mockServices {
// (undocumented)
export namespace database {
const // (undocumented)
factory: ServiceFactoryCompat<DatabaseService, 'plugin', undefined>;
factory: ServiceFactoryCompat<DatabaseService, 'plugin', true, undefined>;
const // (undocumented)
mock: (
partialImpl?: Partial<DatabaseService> | undefined,
@@ -185,7 +185,12 @@ export namespace mockServices {
// (undocumented)
export namespace discovery {
const // (undocumented)
factory: ServiceFactoryCompat<DiscoveryService, 'plugin', undefined>;
factory: ServiceFactoryCompat<
DiscoveryService,
'plugin',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<DiscoveryService> | undefined,
@@ -194,7 +199,7 @@ export namespace mockServices {
// (undocumented)
export namespace events {
const // (undocumented)
factory: ServiceFactoryCompat<EventsService, 'plugin', undefined>;
factory: ServiceFactoryCompat<EventsService, 'plugin', true, undefined>;
const // (undocumented)
mock: (
partialImpl?: Partial<EventsService> | undefined,
@@ -208,8 +213,8 @@ export namespace mockServices {
export namespace httpAuth {
const factory: ((options?: {
defaultCredentials?: BackstageCredentials;
}) => ServiceFactory<HttpAuthService, 'plugin'>) &
ServiceFactory<HttpAuthService, 'plugin'>;
}) => ServiceFactory<HttpAuthService, 'plugin', true>) &
ServiceFactory<HttpAuthService, 'plugin', true>;
const // (undocumented)
mock: (
partialImpl?: Partial<HttpAuthService> | undefined,
@@ -218,7 +223,12 @@ export namespace mockServices {
// (undocumented)
export namespace httpRouter {
const // (undocumented)
factory: ServiceFactoryCompat<HttpRouterService, 'plugin', undefined>;
factory: ServiceFactoryCompat<
HttpRouterService,
'plugin',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<HttpRouterService> | undefined,
@@ -229,7 +239,7 @@ export namespace mockServices {
// (undocumented)
export namespace identity {
const // (undocumented)
factory: ServiceFactoryCompat<IdentityService, 'plugin', undefined>;
factory: ServiceFactoryCompat<IdentityService, 'plugin', true, undefined>;
const // (undocumented)
mock: (
partialImpl?: Partial<IdentityService> | undefined,
@@ -238,7 +248,12 @@ export namespace mockServices {
// (undocumented)
export namespace lifecycle {
const // (undocumented)
factory: ServiceFactoryCompat<LifecycleService, 'plugin', undefined>;
factory: ServiceFactoryCompat<
LifecycleService,
'plugin',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<LifecycleService> | undefined,
@@ -247,7 +262,7 @@ export namespace mockServices {
// (undocumented)
export namespace logger {
const // (undocumented)
factory: ServiceFactoryCompat<LoggerService, 'plugin', undefined>;
factory: ServiceFactoryCompat<LoggerService, 'plugin', true, undefined>;
const // (undocumented)
mock: (
partialImpl?: Partial<LoggerService> | undefined,
@@ -256,7 +271,12 @@ export namespace mockServices {
// (undocumented)
export namespace permissions {
const // (undocumented)
factory: ServiceFactoryCompat<PermissionsService, 'plugin', undefined>;
factory: ServiceFactoryCompat<
PermissionsService,
'plugin',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<PermissionsService> | undefined,
@@ -271,15 +291,15 @@ export namespace mockServices {
data?: JsonObject;
};
const // (undocumented)
factory: ServiceFactory<RootConfigService, 'root'> &
factory: ServiceFactory<RootConfigService, 'root', boolean> &
((
options?: Options | undefined,
) => ServiceFactory<RootConfigService, 'root'>);
) => ServiceFactory<RootConfigService, 'root', boolean>);
}
// (undocumented)
export namespace rootHealth {
const // (undocumented)
factory: ServiceFactoryCompat<RootHealthService, 'root', undefined>;
factory: ServiceFactoryCompat<RootHealthService, 'root', true, undefined>;
const // (undocumented)
mock: (
partialImpl?: Partial<RootHealthService> | undefined,
@@ -290,8 +310,8 @@ export namespace mockServices {
const // (undocumented)
factory: ((
options?: RootHttpRouterFactoryOptions | undefined,
) => ServiceFactory<RootHttpRouterService, 'root'>) &
ServiceFactory<RootHttpRouterService, 'root'>;
) => ServiceFactory<RootHttpRouterService, 'root', true>) &
ServiceFactory<RootHttpRouterService, 'root', true>;
const // (undocumented)
mock: (
partialImpl?: Partial<RootHttpRouterService> | undefined,
@@ -300,7 +320,12 @@ export namespace mockServices {
// (undocumented)
export namespace rootLifecycle {
const // (undocumented)
factory: ServiceFactoryCompat<RootLifecycleService, 'root', undefined>;
factory: ServiceFactoryCompat<
RootLifecycleService,
'root',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<RootLifecycleService> | undefined,
@@ -315,10 +340,10 @@ export namespace mockServices {
level?: 'none' | 'error' | 'warn' | 'info' | 'debug';
};
const // (undocumented)
factory: ServiceFactory<LoggerService, 'root'> &
factory: ServiceFactory<LoggerService, 'root', boolean> &
((
options?: Options | undefined,
) => ServiceFactory<LoggerService, 'root'>);
) => ServiceFactory<LoggerService, 'root', boolean>);
const // (undocumented)
mock: (
partialImpl?: Partial<RootLoggerService> | undefined,
@@ -327,7 +352,12 @@ export namespace mockServices {
// (undocumented)
export namespace scheduler {
const // (undocumented)
factory: ServiceFactoryCompat<SchedulerService, 'plugin', undefined>;
factory: ServiceFactoryCompat<
SchedulerService,
'plugin',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<SchedulerService> | undefined,
@@ -338,7 +368,12 @@ export namespace mockServices {
// (undocumented)
export namespace tokenManager {
const // (undocumented)
factory: ServiceFactoryCompat<TokenManagerService, 'plugin', undefined>;
factory: ServiceFactoryCompat<
TokenManagerService,
'plugin',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<TokenManagerService> | undefined,
@@ -347,7 +382,12 @@ export namespace mockServices {
// (undocumented)
export namespace urlReader {
const // (undocumented)
factory: ServiceFactoryCompat<UrlReaderService, 'plugin', undefined>;
factory: ServiceFactoryCompat<
UrlReaderService,
'plugin',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<UrlReaderService> | undefined,
@@ -358,7 +398,12 @@ export namespace mockServices {
): UserInfoService;
// (undocumented)
export namespace userInfo {
const factory: ServiceFactoryCompat<UserInfoService, 'plugin', undefined>;
const factory: ServiceFactoryCompat<
UserInfoService,
'plugin',
true,
undefined
>;
const // (undocumented)
mock: (
partialImpl?: Partial<UserInfoService> | undefined,
@@ -374,22 +419,34 @@ export function registerMswTestHooks(worker: {
}): void;
// @public
export class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin'> {
static from<TService, TScope extends 'root' | 'plugin'>(
subject: ServiceFactory<TService, TScope>,
export class ServiceFactoryTester<
TService,
TScope extends 'root' | 'plugin',
TSingleton extends boolean = true,
> {
static from<
TService,
TScope extends 'root' | 'plugin',
TSingleton extends boolean = true,
>(
subject: ServiceFactory<TService, TScope, TSingleton>,
options?: ServiceFactoryTesterOptions,
): ServiceFactoryTester<TService, TScope>;
): ServiceFactoryTester<TService, TScope, TSingleton>;
// @deprecated
get(
...args: 'root' extends TScope ? [] : [pluginId?: string]
): Promise<TService>;
getService<TGetService, TGetScope extends 'root' | 'plugin'>(
service: ServiceRef<TGetService, TGetScope>,
): Promise<TSingleton extends true ? TService : TService[]>;
getService<
TGetService,
TGetScope extends 'root' | 'plugin',
TGetSingleton extends boolean,
>(
service: ServiceRef<TGetService, TGetScope, TGetSingleton>,
...args: 'root' extends TGetScope ? [] : [pluginId?: string]
): Promise<TGetService>;
): Promise<TGetSingleton extends true ? TGetService : TGetService[]>;
getSubject(
...args: 'root' extends TScope ? [] : [pluginId?: string]
): Promise<TService>;
): Promise<TSingleton extends true ? TService : TService[]>;
}
// @public
@@ -43,8 +43,12 @@ export interface ServiceFactoryTesterOptions {
*
* @public
*/
export class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin'> {
readonly #subject: ServiceRef<TService, TScope>;
export class ServiceFactoryTester<
TService,
TScope extends 'root' | 'plugin',
TSingleton extends boolean = true,
> {
readonly #subject: ServiceRef<TService, TScope, TSingleton>;
readonly #registry: ServiceRegistry;
/**
@@ -54,10 +58,14 @@ export class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin'> {
* @param options - Additional options
* @returns A new tester instance for the provided subject.
*/
static from<TService, TScope extends 'root' | 'plugin'>(
subject: ServiceFactory<TService, TScope>,
static from<
TService,
TScope extends 'root' | 'plugin',
TSingleton extends boolean = true,
>(
subject: ServiceFactory<TService, TScope, TSingleton>,
options?: ServiceFactoryTesterOptions,
) {
): ServiceFactoryTester<TService, TScope, TSingleton> {
const registry = ServiceRegistry.create([
...defaultServiceFactories,
...(options?.dependencies ?? []),
@@ -67,7 +75,7 @@ export class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin'> {
}
private constructor(
subject: ServiceRef<TService, TScope>,
subject: ServiceRef<TService, TScope, TSingleton>,
registry: ServiceRegistry,
) {
this.#subject = subject;
@@ -81,7 +89,7 @@ export class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin'> {
*/
async get(
...args: 'root' extends TScope ? [] : [pluginId?: string]
): Promise<TService> {
): Promise<TSingleton extends true ? TService : TService[]> {
return this.getSubject(...args);
}
@@ -97,9 +105,10 @@ export class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin'> {
*/
async getSubject(
...args: 'root' extends TScope ? [] : [pluginId?: string]
): Promise<TService> {
): Promise<TSingleton extends true ? TService : TService[]> {
const [pluginId] = args;
return this.#registry.get(this.#subject, pluginId ?? 'test')!;
const instance = this.#registry.get(this.#subject, pluginId ?? 'test')!;
return instance;
}
/**
@@ -109,10 +118,14 @@ export class ServiceFactoryTester<TService, TScope extends 'root' | 'plugin'> {
*
* A plugin ID can optionally be provided for plugin scoped services, otherwise the plugin ID 'test' is used.
*/
async getService<TGetService, TGetScope extends 'root' | 'plugin'>(
service: ServiceRef<TGetService, TGetScope>,
async getService<
TGetService,
TGetScope extends 'root' | 'plugin',
TGetSingleton extends boolean,
>(
service: ServiceRef<TGetService, TGetScope, TGetSingleton>,
...args: 'root' extends TGetScope ? [] : [pluginId?: string]
): Promise<TGetService> {
): Promise<TGetSingleton extends true ? TGetService : TGetService[]> {
const [pluginId] = args;
const instance = await this.#registry.get(service, pluginId ?? 'test');
if (instance === undefined) {