frontend-plugin-api: improved forwarding of inputs
Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
@@ -767,35 +767,37 @@ describe('createExtension', () => {
|
||||
opt: inputs.opt?.get(testDataRef1) ?? 'none',
|
||||
single: inputs.single.get(testDataRef1),
|
||||
singleOpt: inputs.single.get(testDataRef2) ?? 'none',
|
||||
multi: inputs.multi.map(i => i.get(testDataRef1)).join(','),
|
||||
multi: inputs.multi
|
||||
.map(i => `${i.node.spec.id}=${i.get(testDataRef1)}`)
|
||||
.join(','),
|
||||
}),
|
||||
];
|
||||
},
|
||||
});
|
||||
|
||||
const optExt = createExtension({
|
||||
name: 'opt',
|
||||
name: 'o',
|
||||
attachTo: { id: 'subject', input: 'opt' },
|
||||
output: [testDataRef1],
|
||||
factory: () => [testDataRef1('orig-opt')],
|
||||
});
|
||||
|
||||
const singleExt = createExtension({
|
||||
name: 'single',
|
||||
name: 's',
|
||||
attachTo: { id: 'subject', input: 'single' },
|
||||
output: [testDataRef1, testDataRef2.optional()],
|
||||
factory: () => [testDataRef1('orig-single')],
|
||||
});
|
||||
|
||||
const multi1Ext = createExtension({
|
||||
name: 'multi1',
|
||||
name: 'm1',
|
||||
attachTo: { id: 'subject', input: 'multi' },
|
||||
output: [testDataRef1],
|
||||
factory: () => [testDataRef1('orig-multi1')],
|
||||
});
|
||||
|
||||
const multi2Ext = createExtension({
|
||||
name: 'multi2',
|
||||
name: 'm2',
|
||||
attachTo: { id: 'subject', input: 'multi' },
|
||||
output: [testDataRef1],
|
||||
factory: () => [testDataRef1('orig-multi2')],
|
||||
@@ -812,7 +814,7 @@ describe('createExtension', () => {
|
||||
opt: 'orig-opt',
|
||||
single: 'orig-single',
|
||||
singleOpt: 'none',
|
||||
multi: 'orig-multi1,orig-multi2',
|
||||
multi: 'm1=orig-multi1,m2=orig-multi2',
|
||||
});
|
||||
|
||||
// All values provided
|
||||
@@ -839,7 +841,7 @@ describe('createExtension', () => {
|
||||
opt: 'opt',
|
||||
single: 'single',
|
||||
singleOpt: 'singleOpt',
|
||||
multi: 'multi1,multi2',
|
||||
multi: 'm1=multi1,m2=multi2',
|
||||
});
|
||||
|
||||
// Minimal values provided
|
||||
@@ -888,7 +890,7 @@ describe('createExtension', () => {
|
||||
opt: 'orig-opt',
|
||||
single: 'orig-single',
|
||||
singleOpt: 'none',
|
||||
multi: 'orig-multi1,orig-multi2',
|
||||
multi: 'm1=orig-multi1,m2=orig-multi2',
|
||||
});
|
||||
|
||||
// Forward inputs separately
|
||||
@@ -915,7 +917,61 @@ describe('createExtension', () => {
|
||||
opt: 'orig-opt',
|
||||
single: 'orig-single',
|
||||
singleOpt: 'none',
|
||||
multi: 'orig-multi1,orig-multi2',
|
||||
multi: 'm1=orig-multi1,m2=orig-multi2',
|
||||
});
|
||||
|
||||
// Reordering inputs
|
||||
expect(
|
||||
createExtensionTester(
|
||||
subject.override({
|
||||
factory(originalFactory, { inputs }) {
|
||||
return originalFactory({
|
||||
inputs: {
|
||||
opt: inputs.opt,
|
||||
single: inputs.single,
|
||||
multi: [inputs.multi[1], inputs.multi[0]],
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
)
|
||||
.add(optExt)
|
||||
.add(singleExt)
|
||||
.add(multi1Ext)
|
||||
.add(multi2Ext)
|
||||
.data(outputRef),
|
||||
).toEqual({
|
||||
opt: 'orig-opt',
|
||||
single: 'orig-single',
|
||||
singleOpt: 'none',
|
||||
multi: 'm2=orig-multi2,m1=orig-multi1',
|
||||
});
|
||||
|
||||
// Filter out inputs
|
||||
expect(
|
||||
createExtensionTester(
|
||||
subject.override({
|
||||
factory(originalFactory, { inputs }) {
|
||||
return originalFactory({
|
||||
inputs: {
|
||||
opt: inputs.opt,
|
||||
single: inputs.single,
|
||||
multi: inputs.multi.filter(i => i.node.spec.id.endsWith('2')),
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
)
|
||||
.add(optExt)
|
||||
.add(singleExt)
|
||||
.add(multi1Ext)
|
||||
.add(multi2Ext)
|
||||
.data(outputRef),
|
||||
).toEqual({
|
||||
opt: 'orig-opt',
|
||||
single: 'orig-single',
|
||||
singleOpt: 'none',
|
||||
multi: 'm2=orig-multi2',
|
||||
});
|
||||
|
||||
// Overriding based on original input
|
||||
@@ -946,7 +1002,7 @@ describe('createExtension', () => {
|
||||
opt: 'none',
|
||||
single: 'override-orig-single',
|
||||
singleOpt: 'new-singleOpt',
|
||||
multi: 'override-orig-multi1,override-orig-multi2',
|
||||
multi: 'm1=override-orig-multi1,m2=override-orig-multi2',
|
||||
});
|
||||
|
||||
// Mismatched input override length
|
||||
@@ -972,6 +1028,29 @@ describe('createExtension', () => {
|
||||
`"Failed to instantiate extension 'subject', override data provided for input 'multi' must match the length of the original inputs"`,
|
||||
);
|
||||
|
||||
// Mix forward and data override
|
||||
expect(() =>
|
||||
createExtensionTester(
|
||||
subject.override({
|
||||
factory(originalFactory, { inputs }) {
|
||||
return originalFactory({
|
||||
inputs: {
|
||||
...inputs,
|
||||
multi: [inputs.multi[0], [testDataRef1('multi2')]],
|
||||
},
|
||||
});
|
||||
},
|
||||
}),
|
||||
)
|
||||
.add(optExt)
|
||||
.add(singleExt)
|
||||
.add(multi1Ext)
|
||||
.add(multi2Ext)
|
||||
.data(outputRef),
|
||||
).toThrowErrorMatchingInlineSnapshot(
|
||||
`"Failed to instantiate extension 'subject', override data for input 'multi' may not mix forwarded inputs with data overrides"`,
|
||||
);
|
||||
|
||||
// Required input not provided
|
||||
expect(() =>
|
||||
createExtensionTester(
|
||||
|
||||
@@ -129,7 +129,7 @@ export function resolveInputOverrides(
|
||||
);
|
||||
}
|
||||
newInputs[name] = Object.assign(providedContainer, {
|
||||
name: (originalInput as ResolvedExtensionInput<any>).node,
|
||||
node: (originalInput as ResolvedExtensionInput<any>).node,
|
||||
}) as any;
|
||||
}
|
||||
} else {
|
||||
@@ -139,23 +139,40 @@ export function resolveInputOverrides(
|
||||
`override data provided for input '${name}' must be an array`,
|
||||
);
|
||||
}
|
||||
if (
|
||||
originalInput.length !== providedData.length &&
|
||||
providedData.length > 0
|
||||
) {
|
||||
throw new Error(
|
||||
`override data provided for input '${name}' must match the length of the original inputs`,
|
||||
);
|
||||
|
||||
// Regular inputs can be overridden in two different ways:
|
||||
// 1) Forward a subset of the original inputs in a new order
|
||||
// 2) Provide new data for each original input
|
||||
|
||||
// First check if all inputs are being removed
|
||||
if (providedData.length === 0) {
|
||||
newInputs[name] = [];
|
||||
} else {
|
||||
// Check how many of the provided data items have a node property, i.e. is a forwarded input
|
||||
const withNodesCount = providedData.filter(d => 'node' in d).length;
|
||||
if (withNodesCount === 0) {
|
||||
if (originalInput.length !== providedData.length) {
|
||||
throw new Error(
|
||||
`override data provided for input '${name}' must match the length of the original inputs`,
|
||||
);
|
||||
}
|
||||
newInputs[name] = providedData.map((data, i) => {
|
||||
const providedContainer = createExtensionDataContainer(
|
||||
data as Iterable<ExtensionDataValue<any, any>>,
|
||||
declaredInput.extensionData,
|
||||
);
|
||||
return Object.assign(providedContainer, {
|
||||
node: (originalInput[i] as ResolvedExtensionInput<any>).node,
|
||||
}) as any;
|
||||
});
|
||||
} else if (withNodesCount === providedData.length) {
|
||||
newInputs[name] = providedData as any;
|
||||
} else {
|
||||
throw new Error(
|
||||
`override data for input '${name}' may not mix forwarded inputs with data overrides`,
|
||||
);
|
||||
}
|
||||
}
|
||||
newInputs[name] = providedData.map((data, i) => {
|
||||
const providedContainer = createExtensionDataContainer(
|
||||
data as Iterable<ExtensionDataValue<any, any>>,
|
||||
declaredInput.extensionData,
|
||||
);
|
||||
return Object.assign(providedContainer, {
|
||||
name: (originalInput[i] as ResolvedExtensionInput<any>).node,
|
||||
}) as any;
|
||||
});
|
||||
}
|
||||
}
|
||||
return newInputs;
|
||||
|
||||
Reference in New Issue
Block a user