Skip to main content

Configuration

Finsemble is a configuration-driven platform. Configuration is your way to manage a large system logically: you can assemble your config from multiple pieces. Additionally, Finsemble’s config is dynamic, so your smart desktop can adapt to entitlements, environments, and preferences.

Finsemble's configuration is pulled from JSON files on start-up and made available to all components and services for reference. Configuration can be partitioned into two main categories: Finsemble's core configuration and Finsemble's application-level configuration. Typically, when developing Finsemble smart desktops, a developer uses the application-level configuration, contained in ../configs/application/config.json.

This tutorial describes the underlying structure of how Finsemble uses configuration.

For a complete reference, you can take a look at the config reference tree.

Start-up

Finsemble starts as directed by the manifest file located in your repo at ../configs/application/manifest-local.json. Immediately after start-up, Finsemble spawns the Config Service to dynamically assemble the full Finsemble configuration. The Config Service is started early so it is always available to other components and services through the Config Client API. The Config Service follows these steps:

  • Step 1: Pull in the Finsemble properties that are defined within the manifest file (you can see the finsemble property at the bottom of the manifest file). This provides enough Finsemble configuration to bootstrap the rest of Finsemble and assemble the complete configuration.
  • Step 2: Pull in the Finsemble core configuration from internal JSON files. These files are stored either on a server or within a development build directory (e.g., "dist") under ../configs/core.
  • Step 3: Pull in the application-level config, stored in your repository under ../configs/application/config.json.
  • Step 4: Apply Dynamic Configuration. This is optional, but can be used to distribute different entitlements to different users.
  • Step 5: Retrieve the user preference configuration from storage.

Each successive "wave" of configuration overlays the previous ones.

After the Finsemble configuration has been assembled by these steps, the Finsemble start-up sequence continues by launching services and components.


Using the Config Client to retrieve Finsemble's configuration

After start-up, the Config Service is available to respond to configuration queries from any service or component.

Important

Generally, no service or component should ever read config settings directly from JSON files. Instead, you should use the Config Client, which interfaces with the Config Service, to retrieve config settings.

The Config Client can return a copy of all or part of the finsemble object. The field value passed through is specified in path array notation in which you specify the object property that you want to target as an array of strings. Here are some examples using the Config Client to retrieve configuration data.

Getting the entire Finsemble configuration:

FSBL.Clients.ConfigClient.get(['finsemble'], function (err, finsembleConfig) {
console.log(finsembleConfig);
});

Getting a list of all the configured apps:

FSBL.Clients.ConfigClient.get(['finsemble', 'apps'], function (err, components) {
console.log(components);
});

To get multiple values from the config, use the getMultiple method instead. Here is an example:

FSBL.Clients.ConfigClient.getMultiple(
[
['finsemble', 'servicesConfig','launcher'],
['finsemble', 'servicesConfig','assimilation']
],
(err, finsembleConfig) => {
console.log(finsembleConfig);
}
);
note

In the earlier versions of Finsemble we didn't use path arrays, we used path strings instead. As a result, if you had a period "." or array notation characters "[ ]" in any of your property names, you had to encapsulate the name as an index per the JSON spec. With path arrays, you don't need to do that, which makes your code simpler.

In addition to the get function, Finsemble also provides the set and remove functions allowing you to edit the configuration. Similarly, in addition to the getMultiple function, we also have setMultiple and removeMultiple functions. See the Config Client for details.


Manifest macros

Macros such as $applicationRoot or $moduleRoot are automatically defined, or may be explicitly set in the manifest, and can be used as substitutions throughout config. You may also create your own custom macros.

See Manifest Macros in the deployment tutorial for information on creating and using macros.


Partitioning Finsemble's configuration using import files

Deprecated

We don't recommend partioning configuration into separate import files anymore. Finsemble's seed project now contains only manifest-local.json, config.json, appd.json (DEPRECATED) and apps.json.

Finsemble's configuration starts in the manifest file. However, Finsemble was designed to easily support multiple configuration files, providing a much better organization for config settings. Because JSON doesn't have any kind of "import" or "include" capabilities, Finsemble defines two special import properties into JSON that can be used by the developer to dynamically import other config files. This importing is part of the start-up "assembling" done by the Config Service. The two properties and their functions are as follows:

  • "importConfig" defines an array of JSON URLs to be imported into the top-level finsemble object. Note that this will overwrite any existing config settings, with a few exceptions:

    1. New apps and app services defined under finsemble.apps will be added to the list of existing apps (as opposed to replacing the list of existing apps).

    2. New custom services (DEPRECATED) defined under finsemble.services will be added to the list of existing services (as opposed to replacing the existing list of services).

    3. New UI components defined under finsemble.components will be added to the list of existing components (as opposed to replacing the list of existing components).

    4. New workspaces defined finsemble.workspaceTemplates will be added to the list of existing workspaceTemplates (as opposed to replacing the list of existing workspaceTemplates).

    Regardless of the exception above, a new app, app service or UI component with the same name or appId as an existing one will replace the existing definition.

  • "importThirdPartyConfig" defines an array of JSON URLs to be imported into the top-level finsemble object. This import is essentially the same as importConfig with one notable difference: the imported configuration settings cannot overwrite any existing settings. In this case, the settings for any potential overwrite will be discarded with a warning message written to the Config Service's log.

Again, the following snippet from the manifest file shows the application-level config is being pulled from another file.

"finsemble": {
"applicationRoot": "http://localhost:3375/yourSubDirectory/dist",
"moduleRoot": "http://localhost:3375/yourSubDirectory/node_modules/@finsemble/finsemble-core/dist",
"importConfig": [
"$applicationRoot/configs/application/config.json"
]
}

The Central Logger is a unified console for viewing messages across all components and services. It can be used to view import errors and debug the configuration process.

More about configuration format and imports

All configuration properties are always inserted directly under the finsemble object, independent from where the import occurred. In other words, regardless of where the JSON data is pulled from, it is always defined under finsemble.

For example, consider the following import contents contained in the file someConfig.json:

{
"myConfigValue": {
"first": 1,
"last": 99
},
"myOtherConfigValue": 456,
"services": {
"aChatService": {
"visible": false,
"active": true,
"name": "aChatService",
"html": "achat/chat.html",
"file": "achat/chatService.js"
}
},
"importConfig": [
"configs/application/myOtherConfig.json"
]
}

This references the import file configs/application/myOtherConfig.json with the following contents:

{
"myConfigValue": {
"first": 0,
"last": 100
},
"myNewConfigValue": 0,
}

After the first pass of processing the data (all data but the imports) in someConfig.json, the equivalent of the following will exist in the finsemble object:

finsemble.myConfigValue = {"first": 1, "last": 99};
finsemble.myOtherConfigValue = 456;
finsemble.services.aChatService = {"visible": false, "active": true, ...};

Then, after configs/application/myOtherConfig.json is imported (from the importConfig), the finsemble object will effectively contain:

finsemble.myConfigValue = { "first": 0, "last": 100};
finsemble.myOtherConfigValue = 456;
finsemble.myNewConfigValue = 0;
finsemble.services.aChatService = {"visible": false, "active": true, ...};

Note the value of myConfigValue was overwritten by the import. Also, a new value named myNewConfigValue was added.


User preferences

User preferences are developer-defined options that give end users the ability to fine-tune their Finsemble experience. They are set prior to the initialization of the Finsemble services, and are applied to the main configuration, overriding or augmenting it (similar to dynamic configuration) with the user's chosen settings. The user can only modify what you give them access to.

User preferences are the last configuration applied. Thus, they will always overwrite any config that comes before it. This means they are powerful and should be implemented carefully.

The API methods for preferences are FSBL.Clients.ConfigClient.setPreference and FSBL.Clients.ConfigClient.getPreferences.

Our seed project includes an example implementation that allows users to customize the following configs:

  • Specify a time for Finsemble to automatically restart itself.
  • Specify which workspace will load on start-up.

Additional notes

  • Each URL in a list of imports will be completely assembled before going to the next URL in the list. Given that any imported file can contain other imports, the process of importing operates recursively in a depth-first fashion. This provides a well-defined ordering when imports redefine config settings.
  • importConfig and importThirdPartyConfig are always processed last in a file, independent from where they are placed in the JSON. For this reason it's a good practice to put imports at the bottom.
  • Any property directly defined under finsemble that matches the RegEx /comment.*/ will be stripped out at run-time (e.g., finsemble.comment, finsemble.comment1).
  • Configuration processing, as well as error reporting, can be seen in the Config Service's console output.

See also

The AppD format

Add an app to your smart desktop

API documentation about the Config Client

The Config Reference explains the configuration tree.

For a discussion about dynamic configuration, as opposed to the static configuration described here, check out the Dynamic Configuration tutorial