diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx index 003090668b..fa85cbf981 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.test.tsx @@ -443,17 +443,17 @@ describe('createExtensionBlueprint', () => { }), ]); - // Not enough values provided, checked at runtime + // Mismatched input override length expect(() => factoryOutput( Blueprint.makeWithOverrides({ - factory(origFactory) { + factory(origFactory, { inputs }) { return origFactory( {}, { inputs: { - single: [], - multi: [], + ...inputs, + multi: [[testDataRef1('multi1')]], }, }, ); @@ -465,6 +465,28 @@ describe('createExtensionBlueprint', () => { `"Invalid override provided for input 'multi', when overriding the input data the length must match the original input data"`, ); + // Required input not provided + expect(() => + factoryOutput( + Blueprint.makeWithOverrides({ + factory(origFactory, { inputs }) { + return origFactory( + {}, + { + inputs: { + ...inputs, + single: [testDataRef2('singleOpt')], + }, + }, + ); + }, + }), + mockParentInputs, + ), + ).toThrowErrorMatchingInlineSnapshot( + `"Missing required data values for 'test1'"`, + ); + // Wrong value provided expect(() => factoryOutput( @@ -490,7 +512,7 @@ describe('createExtensionBlueprint', () => { mockParentInputs, ), ).toThrowErrorMatchingInlineSnapshot( - `"Invalid override provided for input 'multi', when overriding the input data the length must match the original input data"`, + `"Invalid data value provided, 'test2' was not declared"`, ); // Forwarding entire inputs object diff --git a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts index 2bc5fda43d..2ad58e2ef9 100644 --- a/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts +++ b/packages/frontend-plugin-api/src/wiring/createExtensionBlueprint.ts @@ -259,13 +259,34 @@ export function createDataContainer( ? ExtensionDataValue : never >, + declaredRefs?: ExtensionDataRef[], ): ExtensionDataContainer { const container = new Map>(); + const verifyRefs = + declaredRefs && new Map(declaredRefs.map(ref => [ref.id, ref])); for (const output of values) { + if (verifyRefs) { + if (!verifyRefs.delete(output.id)) { + throw new Error( + `Invalid data value provided, '${output.id}' was not declared`, + ); + } + } container.set(output.id, output); } + const remainingRefs = + verifyRefs && + Array.from(verifyRefs.values()).filter(ref => !ref.config.optional); + if (remainingRefs && remainingRefs.length > 0) { + throw new Error( + `Missing required data values for '${remainingRefs + .map(ref => ref.id) + .join(', ')}'`, + ); + } + return { get(ref) { return container.get(ref.id)?.value; @@ -436,6 +457,7 @@ class ExtensionBlueprintImpl< if (providedData) { const providedContainer = createDataContainer( providedData as Iterable>, + declaredInput.extensionData, ); if (!originalInput) { throw new Error( @@ -467,6 +489,7 @@ class ExtensionBlueprintImpl< newInputs[name] = providedData.map((data, i) => { const providedContainer = createDataContainer( data as Iterable>, + declaredInput.extensionData, ); return Object.assign(providedContainer, { name: (originalInput[i] as ResolvedExtensionInput)