Merge pull request #33878 from backstage/rugvip/harmonize-phantom-t-getter
backend-plugin-api: harmonize phantom .T getter behavior
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/backend-plugin-api': patch
|
||||
---
|
||||
|
||||
Aligned `.T` behavior between `ExtensionPoint` and `ServiceRef` to consistently return `null` instead of throwing.
|
||||
@@ -25,6 +25,18 @@ const rootDep = createServiceRef<number>({ id: 'y', scope: 'root' });
|
||||
const pluginDep = createServiceRef<boolean>({ id: 'z' });
|
||||
function unused(..._any: any[]) {}
|
||||
|
||||
describe('createServiceRef', () => {
|
||||
it('should create a ServiceRef', () => {
|
||||
expect(ref.id).toBe('x');
|
||||
expect(ref.scope).toBe('plugin');
|
||||
expect(ref.T).toBe(null);
|
||||
expect(String(ref)).toBe('serviceRef{x}');
|
||||
expect(JSON.stringify(ref)).toBe(
|
||||
'{"$$type":"@backstage/ServiceRef","id":"x","scope":"plugin","multiton":false}',
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('createServiceFactory', () => {
|
||||
it('should create a plugin scoped factory', () => {
|
||||
const factory = createServiceFactory({
|
||||
|
||||
@@ -50,7 +50,7 @@ export type ServiceRef<
|
||||
|
||||
/**
|
||||
* Utility for getting the type of the service, using `typeof serviceRef.T`.
|
||||
* Attempting to actually read this value will result in an exception.
|
||||
* Reading this value will always return `null`. It is only intended for use with `typeof serviceRef.T`.
|
||||
*/
|
||||
T: TService;
|
||||
|
||||
@@ -143,14 +143,11 @@ export function createServiceRef<
|
||||
id,
|
||||
scope,
|
||||
multiton,
|
||||
get T(): TService {
|
||||
throw new Error(`tried to read ServiceRef.T of ${this}`);
|
||||
},
|
||||
T: null as TService,
|
||||
toString() {
|
||||
return `serviceRef{${options.id}}`;
|
||||
},
|
||||
toJSON() {
|
||||
// This avoids accidental calls to T happening e.g. in tests
|
||||
return {
|
||||
$$type: '@backstage/ServiceRef',
|
||||
id,
|
||||
|
||||
@@ -18,10 +18,10 @@ import { createExtensionPoint } from './createExtensionPoint';
|
||||
|
||||
describe('createExtensionPoint', () => {
|
||||
it('should create an ExtensionPoint', () => {
|
||||
const extensionPoint = createExtensionPoint({ id: 'x' });
|
||||
const extensionPoint = createExtensionPoint<string>({ id: 'x' });
|
||||
expect(extensionPoint).toBeDefined();
|
||||
expect(extensionPoint.id).toBe('x');
|
||||
expect(() => extensionPoint.T).not.toThrow();
|
||||
expect(extensionPoint.T).toBe(null);
|
||||
expect(String(extensionPoint)).toBe('extensionPoint{x}');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -43,13 +43,7 @@ export function createExtensionPoint<T>(
|
||||
): ExtensionPoint<T> {
|
||||
return {
|
||||
id: options.id,
|
||||
get T(): T {
|
||||
if (process.env.NODE_ENV === 'test') {
|
||||
// Avoid throwing errors so tests asserting extensions' properties cannot be easily broken
|
||||
return null as T;
|
||||
}
|
||||
throw new Error(`tried to read ExtensionPoint.T of ${this}`);
|
||||
},
|
||||
T: null as T,
|
||||
toString() {
|
||||
return `extensionPoint{${options.id}}`;
|
||||
},
|
||||
|
||||
@@ -27,7 +27,7 @@ export type ExtensionPoint<T> = {
|
||||
|
||||
/**
|
||||
* Utility for getting the type of the extension point, using `typeof extensionPoint.T`.
|
||||
* Attempting to actually read this value will result in an exception.
|
||||
* Reading this value will always return `null`. It is only intended for use with `typeof extensionPoint.T`.
|
||||
*/
|
||||
T: T;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user