Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/plugins-on-every-node.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@codama/spec': major
---

Give every node a `plugins` list via a new base-attribute mechanism. The meta-model's `Spec` type gains an optional `base` block (authored with the new `defineBase` helper) declaring attributes shared by every node; codegen targets append them after each node's declared attributes, so they always serialise last. The spec declares one base attribute — `plugins`, an optional array of `pluginNode` — making every node extensible with namespaced, consumer-defined data. `instructionNode` no longer declares `plugins` locally (the universal base attribute replaces it), and `validate` rejects base attributes that collide with declared attributes or carry unresolved references.
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,14 @@ Each node declares its attributes as an ordered array in `defineNode(...)`, and

Preserving declaration order keeps encoded IDLs readable: the identifying scalars of a node (`kind`, `name`, …) appear before its potentially large children, so a node's identity is legible at a glance even in a deeply nested IDL.

### Base attributes serialise last

The spec may declare **base attributes** (`Spec.base`): attributes shared by every node, declared once via `defineBase(...)` instead of repeated on each node. The current spec declares one — `plugins`, an optional array of `pluginNode`, making every node extensible with namespaced, consumer-defined data.

- **Codegen targets append base attributes after each node's declared attributes**, so they always serialise last (after the implicit `kind` discriminator and the declared attributes). They may also emit a shared `BaseNode` interface that every generated node type extends.
- Base attribute names never collide with declared attributes — `validate` rejects such specs.
- The array conventions above apply unchanged: an absent `plugins` array means "no plugins".

## Repository layout

```
Expand Down
1 change: 1 addition & 0 deletions docs/AccountNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ An on-chain account: its name, data structure, optional fixed size, optional PDA
| `data` | [`NestedTypeNode`](./typeNodes/NestedTypeNode.md)<[`StructTypeNode`](./typeNodes/StructTypeNode.md)> | The struct describing the account data. It must be a struct so its fields can be referenced by other nodes — e.g. `accountFieldValueNode`. |
| `pda` | [`PdaLinkNode`](./linkNodes/PdaLinkNode.md) _(optional)_ | A link to the PDA the account is derived from, if applicable. |
| `discriminators` | [`DiscriminatorNode`](./discriminatorNodes/DiscriminatorNode.md)[] _(optional)_ | Discriminators that distinguish this account from others in the program. When multiple are listed, they are combined with a logical AND. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
9 changes: 5 additions & 4 deletions docs/ConstantNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ A named constant exposed by the program: a typed value associated with a name.

### Children

| Attribute | Type | Description |
| --------- | ---------------------------------------- | ----------------------------------- |
| `type` | [`TypeNode`](./typeNodes/TypeNode.md) | The type of the constant. |
| `value` | [`ValueNode`](./valueNodes/ValueNode.md) | The concrete value of the constant. |
| Attribute | Type | Description |
| --------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | [`TypeNode`](./typeNodes/TypeNode.md) | The type of the constant. |
| `value` | [`ValueNode`](./valueNodes/ValueNode.md) | The concrete value of the constant. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
7 changes: 4 additions & 3 deletions docs/DefinedTypeNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@ A reusable named type that can be referenced by `definedTypeLinkNode` from elsew

### Children

| Attribute | Type | Description |
| --------- | ------------------------------------- | -------------------- |
| `type` | [`TypeNode`](./typeNodes/TypeNode.md) | The type definition. |
| Attribute | Type | Description |
| --------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `type` | [`TypeNode`](./typeNodes/TypeNode.md) | The type definition. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
6 changes: 6 additions & 0 deletions docs/ErrorNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,12 @@ A program error — a numeric code paired with a name and human-readable message
| `message` | `string` | A human-readable description of the error. |
| `docs` | `string[]` _(optional)_ | Markdown documentation for the error. |

### Children

| Attribute | Type | Description |
| --------- | ---------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

### Create an error node from an input object
Expand Down
9 changes: 5 additions & 4 deletions docs/EventNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@ A program event: its data shape and optional discriminators used to identify it

### Children

| Attribute | Type | Description |
| ---------------- | ------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- |
| `data` | [`TypeNode`](./typeNodes/TypeNode.md) | The type describing the event payload. |
| `discriminators` | [`DiscriminatorNode`](./discriminatorNodes/DiscriminatorNode.md)[] _(optional)_ | Discriminators that distinguish this event from others. When multiple are listed, they are combined with a logical AND. |
| Attribute | Type | Description |
| ---------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `data` | [`TypeNode`](./typeNodes/TypeNode.md) | The type describing the event payload. |
| `discriminators` | [`DiscriminatorNode`](./discriminatorNodes/DiscriminatorNode.md)[] _(optional)_ | Discriminators that distinguish this event from others. When multiple are listed, they are combined with a logical AND. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
1 change: 1 addition & 0 deletions docs/InstructionAccountNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ An account participating in an instruction, with its name, signing/writability f
| `defaultValue` | [`InstructionInputValueNode`](./contextualValueNodes/InstructionInputValueNode.md) _(optional)_ | A default value used to fill the slot when the caller does not provide one. |
| `accountLink` | [`AccountLinkNode`](./linkNodes/AccountLinkNode.md) _(optional)_ | A reference to the account's data layout. Required for consumers (e.g. `accountFieldValueNode`) to read fields from the account. The link's optional `program` allows cross-program references via the root's `additionalPrograms`. |
| `display` | [`InstructionAccountDisplayNode`](./displayNodes/InstructionAccountDisplayNode.md) _(optional)_ | Display metadata describing how the account is presented. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
1 change: 1 addition & 0 deletions docs/InstructionArgumentNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Serialised next to each other, the arguments of an instruction form its data.
| `type` | [`TypeNode`](./typeNodes/TypeNode.md) | The type of the argument. |
| `defaultValue` | [`InstructionInputValueNode`](./contextualValueNodes/InstructionInputValueNode.md) _(optional)_ | A default value used when the argument is omitted by callers. |
| `display` | [`StructFieldDisplayNode`](./displayNodes/StructFieldDisplayNode.md) _(optional)_ | Display metadata describing how the argument is presented. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
7 changes: 4 additions & 3 deletions docs/InstructionByteDeltaNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,10 @@ For instance, if an instruction creates a new account of 42 bytes, this node can

### Children

| Attribute | Type | Description |
| --------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------- |
| `value` | [`InstructionByteDeltaValue`](./InstructionByteDeltaValue.md) | The source of the delta value — a literal number, a referenced account or argument, or a resolver. |
| Attribute | Type | Description |
| --------- | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `value` | [`InstructionByteDeltaValue`](./InstructionByteDeltaValue.md) | The source of the delta value — a literal number, a referenced account or argument, or a resolver. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
2 changes: 1 addition & 1 deletion docs/InstructionNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ A program instruction: its accounts, arguments, byte-delta hints, discriminators
| `subInstructions` | [`InstructionNode`](./InstructionNode.md)[] _(optional)_ | Nested instructions that split this instruction into distinct scenarios — e.g. one sub-instruction per version of the instruction. |
| `provides` | [`ProvidedNode`](./ProvidedNode.md)[] _(optional)_ | Named nodes exposed to consumers in the surrounding scope. Each entry pairs with an `injectedValueNode` that references it by key, so reusable types can pull contextual values without naming siblings directly. |
| `display` | [`InstructionDisplayNode`](./displayNodes/InstructionDisplayNode.md) _(optional)_ | Display metadata describing how the instruction is presented. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
9 changes: 5 additions & 4 deletions docs/InstructionRemainingAccountsNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ A "remaining accounts" slot in an instruction — a variable-length tail of acco

### Children

| Attribute | Type | Description |
| --------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| `value` | [`InstructionRemainingAccountsValue`](./InstructionRemainingAccountsValue.md) | The source of the remaining-accounts list — a referenced argument or a resolver. |
| `display` | [`InstructionAccountDisplayNode`](./displayNodes/InstructionAccountDisplayNode.md) _(optional)_ | Display metadata describing how the remaining-accounts group is presented as a whole. |
| Attribute | Type | Description |
| --------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `value` | [`InstructionRemainingAccountsValue`](./InstructionRemainingAccountsValue.md) | The source of the remaining-accounts list — a referenced argument or a resolver. |
| `display` | [`InstructionAccountDisplayNode`](./displayNodes/InstructionAccountDisplayNode.md) _(optional)_ | Display metadata describing how the remaining-accounts group is presented as a whole. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
7 changes: 4 additions & 3 deletions docs/InstructionStatusNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ An instruction without a status is considered live — a status node is typicall

### Children

| Attribute | Type | Description |
| ----------- | --------------------------------------------------------------- | -------------------- |
| `lifecycle` | [`InstructionLifecycle`](./sharedNodes/InstructionLifecycle.md) | The lifecycle stage. |
| Attribute | Type | Description |
| ----------- | --------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| `lifecycle` | [`InstructionLifecycle`](./sharedNodes/InstructionLifecycle.md) | The lifecycle stage. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
7 changes: 4 additions & 3 deletions docs/PdaNode.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,10 @@ A program-derived address: its name, optional program ID override, and the seeds

### Children

| Attribute | Type | Description |
| --------- | ------------------------------------------------ | ------------------------------------------- |
| `seeds` | [`PdaSeedNode`](./pdaSeedNodes/PdaSeedNode.md)[] | The seeds used to derive the PDA, in order. |
| Attribute | Type | Description |
| --------- | ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------- |
| `seeds` | [`PdaSeedNode`](./pdaSeedNodes/PdaSeedNode.md)[] | The seeds used to derive the PDA, in order. |
| `plugins` | [`PluginNode`](./PluginNode.md)[] _(optional)_ | Namespaced plugins with custom structured data. The universal extension point for renderer-specific or not-yet-standardised metadata. |

## Examples

Expand Down
Loading