export const metadata = {
    title: "Extensions",
    description: "Extensions are a way to add custom functionality to Versia."
}

# Extensions

Versia provides a set of core entities and structures to build a barebones social network. However, it is not possible nor desirable to cover every use case. This is where extensions come in, allowing parts of the system to be extended or replaced with custom functionality. {{ className: 'lead' }}

By design, extensions can be mitchmatched in any combination, without requiring any changes to the core system. This allows for a high degree of customization and flexibility. Implementations that do not support a particular extension can simply ignore it without any issues.

Extensions **should** be standardized and publicly documented.

## Handling Unsupported Extensions

When an extension is not supported by an Implementation, it **can** be ignored. This means that the extension is not processed, and its data is not used. Implementations **must not** throw an error when encountering an unsupported extension, as long as the rest of the entity is valid.

Extensions **must not** be designed in a way that makes them required to understand or process other non-extension entities.

## Naming

Versia extension names are composed of two parts:
- The domain name of the extension author, in reverse order. Example: `pub.versia`
- The extension name, separated by a colon. `snake_case`. Example: `likes`

``` {{ title: "Example Extension Name" }}
pub.versia:likes
```

### Custom entities

Custom entities are named in the same way, but with an additional part:
- The entity name, separated by a slash. `PascalCase`. Example: `Like`

``` {{ title: "Example Custom Entity Type" }}
pub.versia:likes/Like
```

## Extension Definition

Extensions can be found in two places: an [Entity](/entities#entity-definition)'s `extensions` property, or as custom entities themselves. The former is used to add custom functionality to an existing entity, while the latter is used to define a new entity type.

### Entity Extension

<Row>
    <Col>
        <Properties>
            <Property name="extensions" type="Record<string, JSONData>" required={false}>
                Custom extensions to the entity.

                - `key`: The extension name.
                - `value`: Extension data. Can be any JSON-serializable data.

                Extension data can be any JSON-serializable data.
            </Property>
        </Properties>
    </Col>
    <Col sticky>

    ```jsonc {{ title: "Example Entity Extension" }}
    {
        "type": "Group",
        "id": "ed480922-b095-4f09-9da5-c995be8f5960",
        "uri": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960",
        "name": null,
        "description": null,
        "members": "https://example.com/groups/ed480922-b095-4f09-9da5-c995be8f5960/members",
        "extensions": { // [!code focus:100]
            "com.example:gps": {
                "location": {
                    "latitude": 37.7749,
                    "longitude": -122.4194
                },
                "accuracy": 10,
                "name": "San Francisco"
            }
        }
    }
    ```

    </Col>
</Row>

### Custom Entity

<Row>
    <Col>
        <Properties>
            <Property name="type" type="string" required={true}>
                The extension type. [Must follow naming conventions](#naming).
            </Property>
            <Property name="other">
                Other properties of the custom entity. These are specific to the extension, and should be documented by the extension author.

                Note that `id`, `uri` and `created_at` are still required for custom entities, unless the extension author specifies otherwise.
            </Property>
        </Properties>
    </Col>
    <Col sticky>

    ```jsonc {{ title: "Example Custom Entity" }}
    {
        "type": "com.example:poll/Poll",
        "id": "6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
        "uri": "https://example.com/actions/6f27bc77-58ee-4c9b-b804-8cc1c1182fa9",
        "author": "https://example.com/users/6e0204a2-746c-4972-8602-c4f37fc63bbe",
        "created_at": "2021-01-01T00:00:00.000Z",
        "question": "What is your favourite colour?",
        "options": [
            "Red",
            "Blue",
            "Green"
        ]
    }
    ```

    </Col>
</Row>