frontend-plugin-api: fix input incompatibility crash

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2025-11-19 17:42:16 +01:00
parent e99e24c342
commit 0bc1ce919e
6 changed files with 38 additions and 11 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/frontend-plugin-api': patch
---
Fixed a versioning conflict that could result in a `.withContext` is not a function error.
@@ -28,7 +28,7 @@ export const OpaqueExtensionInput = OpaqueType.create<{
versions: {
readonly version: undefined;
readonly context?: ExtensionInputContext;
withContext(context: ExtensionInputContext): ExtensionInput;
withContext?(context: ExtensionInputContext): ExtensionInput;
};
}>({
type: '@backstage/ExtensionInput',
@@ -1318,4 +1318,26 @@ describe('createExtension', () => {
);
});
});
it('should old inputs without context support', () => {
const legacyInput = createExtensionInput([numberDataRef]);
// old API without context
delete (legacyInput as any).context;
delete (legacyInput as any).withContext;
const extension = createExtension({
attachTo: { id: 'root', input: 'default' },
output: [stringDataRef],
inputs: {
foo: legacyInput,
},
factory({ inputs }) {
unused(inputs.foo);
return [stringDataRef('output')];
},
});
expect(extension.inputs.foo).toBe(legacyInput);
});
});
@@ -368,11 +368,11 @@ function bindInputs(
return Object.fromEntries(
Object.entries(inputs).map(([inputName, input]) => [
inputName,
OpaqueExtensionInput.toInternal(input).withContext({
OpaqueExtensionInput.toInternal(input).withContext?.({
kind,
name,
input: inputName,
}),
}) ?? input,
]),
);
}
@@ -60,7 +60,7 @@ describe('createExtensionInput', () => {
const input = createExtensionInput([stringDataRef, numberDataRef]);
const context = { input: 'test1', kind: 'test2', name: 'test3' };
const inputWithContext =
OpaqueExtensionInput.toInternal(input).withContext(context);
OpaqueExtensionInput.toInternal(input).withContext?.(context);
expect(inputWithContext).toEqual({
$$type: '@backstage/ExtensionInput',
extensionData: [stringDataRef, numberDataRef],
@@ -80,7 +80,7 @@ describe('resolveExtensionDefinition', () => {
resolveExtensionDefinition(
OpaqueExtensionDefinition.toInternal({
...baseDef,
attachTo: baseInpuf.withContext({
attachTo: baseInpuf.withContext?.({
kind: 'parent',
name: 'example',
input: 'children',
@@ -97,7 +97,7 @@ describe('resolveExtensionDefinition', () => {
resolveExtensionDefinition(
OpaqueExtensionDefinition.toInternal({
...baseDef,
attachTo: baseInpuf.withContext({
attachTo: baseInpuf.withContext?.({
name: 'example',
input: 'children',
}),
@@ -113,7 +113,7 @@ describe('resolveExtensionDefinition', () => {
resolveExtensionDefinition(
OpaqueExtensionDefinition.toInternal({
...baseDef,
attachTo: baseInpuf.withContext({
attachTo: baseInpuf.withContext?.({
kind: 'parent',
input: 'children',
}),
@@ -129,7 +129,7 @@ describe('resolveExtensionDefinition', () => {
resolveExtensionDefinition(
OpaqueExtensionDefinition.toInternal({
...baseDef,
attachTo: baseInpuf.withContext({
attachTo: baseInpuf.withContext?.({
input: 'children',
}),
}),
@@ -145,15 +145,15 @@ describe('resolveExtensionDefinition', () => {
OpaqueExtensionDefinition.toInternal({
...baseDef,
attachTo: [
baseInpuf.withContext({
baseInpuf.withContext?.({
kind: 'k1',
input: 'children',
}),
baseInpuf.withContext({
baseInpuf.withContext?.({
kind: 'k2',
input: 'children',
}),
baseInpuf.withContext({
baseInpuf.withContext?.({
kind: 'k3',
input: 'children',
}),