mirror of
https://github.com/Alfresco/alfresco-content-app.git
synced 2026-09-09 18:02:54 +00:00
[ACA-1889] Split Extending section into separate files (#784)
* [ACA-1889] Split Extending section into separate files * [ACA-1889] Split Extending section into separate files * [ACA-1889] Added recent changes and then deleted extending.md * [ACA-1889] Added Tutorials section
This commit is contained in:
@@ -0,0 +1,314 @@
|
||||
---
|
||||
---
|
||||
|
||||
# Extension format
|
||||
|
||||
The format is represented by a JSON file with the structure similar to the following:
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "app",
|
||||
"$version": "1.0.0",
|
||||
|
||||
"routes": [],
|
||||
"actions": [],
|
||||
"rules": [],
|
||||
"features": {}
|
||||
}
|
||||
```
|
||||
|
||||
## Schema
|
||||
|
||||
You can find the JSON schema at the project root folder: [extension.schema.json](https://github.com/Alfresco/alfresco-content-app/blob/master/extension.schema.json).
|
||||
|
||||
<p class="tip">
|
||||
The Schema allows you to validate extension files, provides code completion and documentation hints.
|
||||
</p>
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "../../extension.schema.json",
|
||||
"$name": "app",
|
||||
"$version": "1.0.0"
|
||||
}
|
||||
```
|
||||
|
||||
## Multiple files
|
||||
|
||||
You can have multiple extension files distributed separately.
|
||||
All additional files are linked via the `$references` property.
|
||||
The order of declaration defines the order of loading.
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "../../extension.schema.json",
|
||||
"$name": "app",
|
||||
"$version": "1.0.0",
|
||||
"$references": ["plugin1.json", "plugin2.json"]
|
||||
}
|
||||
```
|
||||
|
||||
<p class="warning">
|
||||
All extension files are merged together at runtime.
|
||||
This allows plugins to overwrite the code from the main application or to alter other plugins.
|
||||
</p>
|
||||
|
||||
## Startup behavior
|
||||
|
||||
First, the root `app.extensions.json` is loaded by means of the special `Loader` service.
|
||||
The file can contain all the necessary declarations for an application to function. Extra plugin files are fully optional.
|
||||
|
||||
Next, the `Loader` traverses the `$references` metadata and loads additional files if provided.
|
||||
For the sake of speed the files are loaded in parallel, however once everything is loaded, they are applied in the order of declaration.
|
||||
|
||||
After all the external files are fetched, the `Loader` sorts them, removes the metadata properties and stacks the resulting JSON objects on top of each other.
|
||||
|
||||
<p class="tip">
|
||||
Any top-level property name that starts with the `$` symbol is considered metadata and does not participate in the merge process.
|
||||
That allows a plugin to carry extra information for maintenance and visualisation purposes, for example: `$name`, `$version`, `$description`, `$license`, etc.
|
||||
</p>
|
||||
|
||||
### Merging properties
|
||||
|
||||
There are no limits in the JSON structure and level of nesting.
|
||||
All objects are merged into a single set based on property keys and object IDs (for arrays).
|
||||
|
||||
Before: Plugin 1
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "plugin1",
|
||||
"plugin1.key": "value",
|
||||
"plugin1.text": "string"
|
||||
}
|
||||
```
|
||||
|
||||
Before: Plugin 2
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "plugin2",
|
||||
"plugin2.key": "value",
|
||||
"plugin1.text": "custom string"
|
||||
}
|
||||
```
|
||||
|
||||
Final result:
|
||||
|
||||
```json
|
||||
{
|
||||
"plugin1.key": "value",
|
||||
"plugin1.text": "custom string",
|
||||
"plugin2.key": "value"
|
||||
}
|
||||
```
|
||||
|
||||
Note that as a result we have two unique properties `plugin1.key` and `plugin2.key`,
|
||||
and also a `plugin1.text` that was first defined in the `Plugin 1`, but then overwritten by the `Plugin 2`.
|
||||
|
||||
<p class="tip">
|
||||
JSON merging is a very powerful concept as it gives you the ability to alter any base application settings,
|
||||
or toggle features in other plugins without rebuilding the application or corresponding plugin libraries.
|
||||
</p>
|
||||
|
||||
### Merging objects
|
||||
|
||||
The complex objects are merged by properties. This process is recursive and has no limits for nesting levels.
|
||||
|
||||
Before: Plugin 1
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "plugin1",
|
||||
"features": {
|
||||
"title": "some title",
|
||||
"page1": {
|
||||
"title": "page 1"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Before: Plugin 2
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "plugin2",
|
||||
"features": {
|
||||
"page1": {
|
||||
"title": "custom title"
|
||||
},
|
||||
"page2": {
|
||||
"title": "page 2"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Final result:
|
||||
|
||||
```json
|
||||
{
|
||||
"features": {
|
||||
"title": "some title",
|
||||
"page1": {
|
||||
"title": "custom title"
|
||||
},
|
||||
"page2": {
|
||||
"title": "page 2"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can see the unique properties get merged together in a single object.
|
||||
However the last non-unique property overwrites the previous value.
|
||||
|
||||
Using the current design it is not possible to delete any application property from the plugin.
|
||||
The loader engine only supports overwriting values. Many components however support the `disabled` property you can change using an external definition:
|
||||
|
||||
Before: Plugin 1
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "plugin1",
|
||||
"feature1": {
|
||||
"disabled": false,
|
||||
"text": "some-feature",
|
||||
"icon": "some-icon"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Before: Plugin 2
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "plugin2",
|
||||
"feature1": {
|
||||
"disabled": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Final result:
|
||||
|
||||
```json
|
||||
{
|
||||
"feature1": {
|
||||
"disabled": true,
|
||||
"text": "some-feature",
|
||||
"icon": "some-icon"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
You can find more details in the [Disabling Content](/extending/extension-format/#disabling-content) section
|
||||
|
||||
### Merging arrays
|
||||
|
||||
The extension `Loader` provides a special support for merging Arrays.
|
||||
By default, two collections will be merged into a single array unless objects have `id` properties.
|
||||
|
||||
<p class="tip">
|
||||
If array contains two objects with the same `id` property, the objects will be merged rather than appended.
|
||||
</p>
|
||||
|
||||
Before: Plugin 1
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "plugin1",
|
||||
"features": [
|
||||
{ "text": "common 1" },
|
||||
{
|
||||
"id": "page1",
|
||||
"text": "page 1"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Before: Plugin 2
|
||||
|
||||
```json
|
||||
{
|
||||
"$name": "plugin2",
|
||||
"features": [
|
||||
{ "text": "common 2" },
|
||||
{
|
||||
"id": "page1",
|
||||
"text": "custom page"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Final result:
|
||||
|
||||
```json
|
||||
{
|
||||
"features": [
|
||||
{ "text": "common 1" },
|
||||
{ "text": "common 2" },
|
||||
{
|
||||
"id": "page1",
|
||||
"text": "custom page"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Note that objects with the same `page1` identifiers were merged while other unique entries were appended to the resulting array.
|
||||
|
||||
## Disabling content
|
||||
|
||||
Most of the schema elements can be switched off by using the `disabled` property:
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "../../extension.schema.json",
|
||||
"$name": "app",
|
||||
"$version": "1.0.0",
|
||||
|
||||
"features": {
|
||||
"create": [
|
||||
{
|
||||
"id": "app.create.folder",
|
||||
"disabled": true,
|
||||
"order": 100,
|
||||
"icon": "create_new_folder",
|
||||
"title": "Create Folder"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This feature becomes handy when you want to disable existing functionality from within the external plugin.
|
||||
|
||||
In the example below, the plugin called `plugin1` replaces standard `app.create.folder` menu
|
||||
exposed by the application with a custom one coming with the plugin.
|
||||
|
||||
```json
|
||||
{
|
||||
"$schema": "../../../extension.schema.json",
|
||||
"$version": "1.0.0",
|
||||
"$name": "plugin1",
|
||||
|
||||
"features": {
|
||||
"create": [
|
||||
{
|
||||
"id": "app.create.folder",
|
||||
"disabled": true,
|
||||
...
|
||||
},
|
||||
{
|
||||
"id": "plugin1.create.folder",
|
||||
"title": "Create Folder",
|
||||
...
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user