frontend-plugin-api: type safe attachTo references

Signed-off-by: Patrik Oldsberg <poldsberg@gmail.com>
This commit is contained in:
Patrik Oldsberg
2025-11-08 19:49:22 +01:00
parent 8b84f39946
commit c6b9f50337
14 changed files with 469 additions and 205 deletions
@@ -391,51 +391,30 @@ const childExtension = createExtension({
});
```
## Direct extension input references
## Extension input references
Building on the relative attachment point concept, you can also reference extension inputs directly via the `inputs` property of an extension definition. This provides a more convenient and type-safe way to attach child extensions, especially when working with blueprints within a plugin.
Building on the relative attachment point concept, you can also reference extension inputs directly via the `inputs` property of an extension definition. This provides a more convenient and type-safe way to attach child extensions, especially when using blueprints that provide a nested hierarchy of extensions.
Extension inputs references are always relative, this means that they can only be used for referencing extensions within the same plugin.
Each extension definition exposes an `inputs` property that contains references to all of its defined inputs. These references can be passed directly to the `attachTo` option when creating child extensions:
```tsx
// Create a parent extension using a blueprint
const page = PageBlueprint.make({
params: {
path: '/example',
loader: () => import('./ExamplePage'),
const parent = createExtension({
inputs: {
children: createExtensionInput([coreExtensionData.reactElement]),
},
// other options...
});
// Create a child extension that attaches to the parent's input
const widget = CardBlueprint.make({
const child = createExtension({
attachTo: page.inputs.children, // Direct reference to the input
params: {
title: 'Example Widget',
content: <div>Widget Content</div>,
},
output: [coreExtensionData.reactElement], // Outputs are verified against the parent input
// other options...
});
```
This approach is functionally equivalent to using relative attachment points, but offers several advantages:
- **Type safety**: The TypeScript compiler will verify that the referenced input exists and is spelled correctly
- **IDE support**: Your editor can provide autocomplete suggestions for available inputs
- **Clearer intent**: The code explicitly shows the relationship between parent and child extensions
The direct input reference syntax works with both single attachment points and arrays of attachment points, and can be mixed with other attachment point formats:
```tsx
// Attach to multiple parents using a mix of styles
const multiAttachChild = ExampleBlueprint.make({
attachTo: [
page.inputs.children, // Direct reference
{ relative: { kind: 'sidebar' }, input: 'items' }, // Relative
{ id: 'app/nav', input: 'items' }, // Absolute ID
],
params: {
/* ... */
},
});
```
These references are a type-safe way to attach child extensions, it both ensures that the parent input is present, as well as the child providing the required data for the parent.
Under the hood, input references are resolved in the same way as relative attachment points, using the extension's kind, namespace, and name to construct the final attachment target.