# Extension Properties

Apps can extend core YouTrack entities with custom properties. We refer to these as extension properties. With extension properties, you can store custom values for core YouTrack entities. An app can then work with these custom properties and their values in its JavaScript-based modules.

Extension properties are declared in a dedicated file named `entity-extensions.json`. To define custom extension properties, add this file to the root level of the app package and declare each property inside the file.

An app has access only to those properties that it declares itself. An app cannot access extension properties of other apps.

When you remove an app from YouTrack, all values of the app's extension properties are deleted. When you reimport an app after deleting or renaming some of its extension properties, their old values are also deleted.

## Supported Types

Here is the list of all types that are available for extension properties:

| Type | Allowed Values |
| --- | --- |
| `integer` | -9223372036854775808 to 9223372036854775807 |
| `float` | 4.94065645841246544e-324d to 1.79769313486231570e+308d (positive or negative) |
| `boolean` |  |
| `string` |  |
| YouTrack entity | Any YouTrack entity supported by the [Workflow API](v1-entities.html) |

> **Note: Storing Multiple Values**
> For YouTrack entities, you can declare an extension property that stores multiple values by adding the `"multi": true` parameter. An extension property declared with this parameter returns a [Set](v1-Set.html).
>
>
>
> This is not available for primitive types like `string`, `integer` , `boolean` , or `float`. As a workaround for string-type properties, use a primitive type with a strigified JSON object that contains the contents of the array.

## Sample Extension Property Declaration

Here you can see an example of an `entity-extensions.json` file. In this example, you can see declarations of extension properties of all possible types. These properties are declared for the issue entity. You can declare similar extension properties for other YouTrack entities. For the full list of entities that you can declare extension properties for, see [YouTrack entities](v1-entities.html).

```JSON
{
    "entityTypeExtensions": [
        {
            "entityType": "Issue",

            "properties": {
                "stringProp": {
                    "type": "string"
                },
                "integerProp": {
                    "type": "integer"
                },
                "floatProp": {
                    "type": "float"
                },
                "booleanProp": {
                    "type": "boolean"
                },
                "issueProp": {
                    "type": "Issue"
                },
                "issuesProp": {
                    "type": "Issue",
                    "multi": true
                }
            }
        }
    ]
}
```

You can refer to an extension property of an entity in a JavaScript script as `entityName.extensionProperties.propertyName`. Here are some examples:

* `ctx.issue.extensionProperties.stringProp`

* `entities.Issue.findById("DEMO-1").extensionProperties.stringProp`

For JavaScript code samples that use extension properties, see [How to Use Extension Properties](#use-extension-properties).

## App Global Storage

An app can declare extension properties at the global app level without linking these properties to a specific entity. You can access global extension properties through the script context (`ctx`) in any JavaScript-based module in the app. To declare this kind of extension property, use `AppGlobalStorage` as the entity type.

```JSON
{
    "entityTypeExtensions": [
        {
            "entityType": "AppGlobalStorage",

            "properties": {
                "globalCounter": {
                    "type": "integer"
                },
                "globalIssuesSet": {
                    "type": "Issue",
                    "multi": true
                }
            }
        }
    ]
}
```

You can refer to a global extension property as `ctx.globalStorage.extensionProperties.propertyName`.

For a JavaScript code sample that uses global extension properties, see [code sample below](#global-storage-code-sample).

## How to Use Extension Properties

You can refer to an extension property of an entity in a JavaScript script as `entityName.extensionProperties.propertyName`. Here are some examples:

* `ctx.issue.extensionProperties.stringProp`

* `entities.Issue.findById("DEMO-1").extensionProperties.stringProp`

Here is a code sample that shows how you can access extension properties declared in the [sample above](#declare-extension-properties) in a JavaScript app script.

```JAVASCRIPT
const entities = require('@jetbrains/youtrack-scripting-api/entities');

exports.rule = entities.Issue.action({
    command: 'test',
    action: function (ctx) {
        const printValues = () => {
            return 'stringProp:' + ctx.issue.extensionProperties.stringProp + ';'
                + 'integerProp:' + ctx.issue.extensionProperties.integerProp + ';'
                + 'booleanProp:' + ctx.issue.extensionProperties.booleanProp + ';'
                + 'issueProp:' + ctx.issue.extensionProperties.issueProp?.id + ';'
                + 'issuesProp:' + ctx.issue.extensionProperties.issuesProp?.first()?.id + ';'
        }
        ctx.issue.addComment(printValues());
    }
});
```

You can refer to a global extension property as `ctx.globalStorage.extensionProperties.propertyName`.

Here is an example of how you can access global extension properties declared in a [sample above](#declare-global-storage) in a JavaScript app script.

```JAVASCRIPT
const entities = require('@jetbrains/youtrack-scripting-api/entities');

exports.rule = entities.Issue.action({
    command: 'test',
    action: function (ctx) {
        ctx.globalStorage.extensionProperties.globalCounter++;
        ctx.globalStorage.extensionProperties.globalIssuesSet.add(ctx.issue);
    }
});
```

