Respresso CLI config reference

The Respresso CLI is highly customizable tool that will let you adapt it to almost any project structure. You can have multi-module projects or a monolithic one, the CLI supports them. You can even re-route files with target overrides to easily organize your resource files in any directory structure you want.

Overview

The Respresso CLI config is a json file that must be named respresso.json. You can initiate it with the respresso init command, or you can create is manually.

You can use any text editor to edit the config file. If your editor supports JSON schema (E.g.: VSCode or IntelliJ), you can add it to get validation, and autocomplete support along the documentation hints:
"$schema": "https://app.respresso.io/public/schema/respresso-sync-config.schema.json"

Note: Paths or path patterns are not restricted to you the current directory. If the path starts with a slash, it will be resolved as an absolute path. If the path does not start with a slash it will be resolved relative from the directory in which the config file is located.

Before diving into the details, lets look at the config structure:

respresso.json
{
  "$schema": "https://app.respresso.io/public/schema/respresso-sync-config.schema.json",
  "server": "https://app.respresso.io",
  "strict": false,
  "localGitIgnore": false,
  "target": "./path/to/default/directory",
  "projects": [
    {
      "name": "core-project"
      "server": "https://your-own-on-premise-respresso-server.intra",
      "token": "YOUR_PROJECT_TOKEN",
      "target": "./path/to/project/directory",
      "resources": [
        "localization:json:feature-add-about-page",
        {
          "category": "color",
          "version": "1.2+",
          "groups": ["ios", "swift"]
        }
        "image:web,scss:1.2.5+",
        "font:android:1.0.0",
        "raw:android:1.0.0"
      ],
      "targetOverrides": [
          // Target overrides just for this project      
      ]
    }
  ],
  "targetOverrides": [{
      "match": {
        "category": "RegEx",
        "group": "RegEx",
        "path": "RegEx",
      },
      "override": {
        "target": "./change/the/default/directory/for/the/matched/files",
        "targetPattern": "./chnage/matched/files/{path}/using/placeholders/like/{fileName}.{extension}"
      }
  }]
}

Global parameters and options

Server

The server parameter is an optional string that needs to be a http or https url. It defaults to https://app.respresso.io. It specifies the server to be used during sync. You only need use this parameter if you have an on-premise installation of Respresso.

Learn more about the on-premise installation option on the pricing page.

Strict mode

The strict parameter is an optional boolean value. It defaults to false.

When strict mode is turned on, the sync will fail if any the required versions are dynamic (e.g.: 1.1.4+) or mutable (not finalized). If the sync succeeds with strict mode, it means that the current state is read-only, thus your build will be repeatable. (You must keep all the required versions on the Respresso server.)

Ignore files from Git

The localGitIgnore parameter is an optional boolean value. It defaults to false.

When enabled, all files handled by Respresso (except the respresso.json config file) will be ignored from Git using the .git/info/exclude. This will help you avoid merge conflicts of all the files generated by Respresso and the respresso.lock file.

This option will work only if the respresso.json config file is in a directory tracked by Git. Please note that, it will search for the .git directory in only 3 levels of parent directories. If you placed the config file in deeper directory structure, this feature will not work.

Respresso uses the .git/info/exclude file to ignore files as it is not part of your repository. Using this, it avoids updating your tracked .gitignore file(s) as it would need merging. Learn more about gitignore rules

Target directory

The target parameter is an optional string that must specify a path. It defaults to ./ which is the current directory (where the config is located). It specifies the directory where to place the synced files.

It's the lowest priority target directory, any global/project target override or project target will override it.

Target overrides

The targetOverrides parameter is an optional array that contains target overrides rules that will be applied to the files that were not matched by and project level target overrides or project level target.

See the Target overrides section to learn about target override rules.

Projects

The projects field is required and must be an array in the config. It lists all the Respresso projects you want to sync.

Project parameters and options

All of these parameters and options are part of a project config object in the projects array.

Project name

The name parameter in the project is an optional string that is a human-readable identifier of the project. Therefore, it must be unique if specified.

This helps you and your colleagues to identify the project they are configuring, and also you can use it with the --only-project <name or token> option of the sync command.

Server

The server parameter in the project is the same as the global server parameter, but it only applies to the current project. It is also optional.

Project token

The token parameter in the project is a required string parameter containing the project's token. This is a read-only token that can be found on the project's dashboard or the project settings page in the Respresso app.

This token is used to authenticate the CLI to the server and to identify the Respresso project you want to use.

It should be a uuid v4 that looks like xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx, where x is a hexadecimal digit. E.g.: * 16d83926-8d94-4f61-9de8-6a0da156b052*.

You can learn more about it on the Get started with the Respresso CLI page.

Target directory

The target parameter in the project is an optional string parameter containing a path representing the project's default directory. When you define it, it is the same as adding the following target override to the project overrides options as the last override:

{
  "match": {}, // Matches all files not matched by previous overrides
  "override": {"target":  "<your target directory>"}
}

See the Target overrides section to learn about target override rules.

Target overrides

The targetOverrides parameter in a project is an optional array of target override configs. See the Target overrides section to learn about target override rules.

The target overrides specified here has the highest priority.

Resources

The resources property in project is a required array of resources. It specifies which versions you need of which resources (category and groups). You can think of them as dependencies of your project/module.

For a quick overview of your options, check the Get started with the Respresso CLI page.

The resources array should specify all the category, version and group triplets you need to sync. This can be written as in most dependency managers: category:group:version.
Please note that logically, the category:version:group would be the proper order as the group is only a representation of the category's version. But we wanted to make it familiar to all of you, so we settled with the usual order even if it might be a bit confusing.

NameFormatCommon values
categoryString enumOnly localization, image, color, appIcon, font and raw are accepted.
groupAlphanumeric stringNo restrictions, but must match a group generated by the Flow. Some common values are: android, ios, web, json, jsonflat, scss, swift, objc, etc. You can find your actual sync groups in the version manager of the category.
versionSemantic version pattern or alphanumeric string with _ and -Exact version: 1.2.5 Patch pattern: 1.2.3+ Minor pattern: 1.2+ Named version: feature_about-us-screen Make sure you have at least one version matching the pattern in the version manager.

According to this, you will end up with a similar list:

[
  "localization:ios:1.0.0",
  "localization:swift:1.0.0",
  "color:ios:1.0.0",
  "color:swift:1.0.0",
  "appIcon:ios:1.0.0"
  // ... Other resources
]
Syntax sugar to avoid inconsistency

In the above example, you may notice, that we requested multiple groups from the same category version. This works fine if you always update all the resource versions at once. The problem comes when you change the localization:ios:1.0.0 to localization:ios:feature-my-feature but keep the localization:swift:1.0.0 resource.
This will work fine until you don't add, modify, or remove a localization key in the feature-my-feature version. Once the swift helper classes should update due to localization key changes, you will see that they won't update during sync.

To avoid referencing the same category version multiple times, we introduced multiple ways of writing them that can be mixed with each other. The following example will result in exactly the same behaviour as the previous one:

[
  {
    "category": "localization",
    "version": "1.0.0",
    "groups": ["ios", "swift"]
  },
  "color:ios,swift:1.0.0", // Listing groups separated by ',' works but not recommended
  "appIcon:ios:1.0.0"
]

You can notice that the localization version is now written only once, so the synced files will always be consistent with each other.
Similarly, the color version is written only once, while the syntax is more compact, but it may be a bit confusing. This is why we don't recommend the use of it.

Target overrides

Target overrides are a set of rules that gives you the ability to freely organize the synced resource files. The main goal of them is to let you adjust Respresso to almost any project structure. For simple project structures, you won't need to use them, but it comes handy when you need to comply to a different directory structure.

Most file names and paths can be customized in the Flow but you might find changing them with the Respresso CLI much easier.

A targetOverrides array can contain multiple override rules. Only the first matching target override will be applied to the file.

Local path resolution order

The priority of target overrides are the following:

  1. Project level targetOverrides, in order of their definition.
  2. Project level target directory. (When project target is defined, the global overrides will not be used as this matches all files.)
  3. Global targetOverrides, in order of their definition.
  4. Global target directory.
  5. If none of the previous rules can be applied, the files are placed in the directory of the respresso.json config file.

Target override options

Each target override rule contains a file matcher rule and an override rule. A target override is applied to all the files that match the matcher rule, otherwise the rule is ignored for that file.

Let's take a look at how a target override rule looks like:

{
  "description": "You can optionally describe the target override rule.",
  "match": {
    "category": "(localization|image)",
    "group": "(ios|swift|objc)",
    "path": "\\.(swift|h|m)$"
  },
  "override": {
    "target": "./path/to/the/desired/directory",
    "targetPattern": "./dynamic/pattern/{directory}/injected-sub-dir/{fileName}.{extension}"
  }
}

Matching files

The match object describes the matcher of the target override. All of its properties are optional, and should contain Regular Expressions. A matcher expression is considered a match if it has a match in the string that is matched against. So it does not have to match the whole string. (You can use the ^ start of string and the $ end of string tokens to force match the whole string.)

All the defined marcher expressions must match all the file meta they are matched against to match the file. So a file is matched if the category AND group AND path matches. (Not defined matcher is considered as matched.)

If you define an empty matcher or skip it entirely, then all the files will be matched and the override rule will be applied. This is how the target directory works.

Keep in mind, that you are editing a JSON file. You must escape the regular expression accordingly. So, e.g. instead of \ you must write \\ and \" instead of ";

Understand how the matchers are used:

MatcherMatched against
categoryThe resource category of the file. E.g.: localization or color. It's the same as the requested category in the project resources.
groupThe sync group of the file. E.g.: ios, json or swift. It's the same as the requested group in the project resources.
pathThe path of the file generated by the Respresso server based on your Flow. It uses UNIX file separators (/). E.g.: respresso/images/logo.svg.

Overriding the target path

The override object describes how the matched files' local path should be created.

The target property in the override object is an optional string containing a path to the base directory of the matched files. This is the one you need if you are happy with the subdirectories generated by Respresso, but you need to place some files in other directory.

The targetPattern property in the override object is an optional string containing a full path pattern of the matched files. The path is relative to the directory defined in the override.target property. If the target is not defined, than it is relative to the directory where the resoresso.json is located. Global and project level target are not used here, as it would be really confusing.

Available placeholders in a target pattern

There are a plenty of placeholders you can use to generate a new path for your synced files:

PlaceholderValue inserted
{category}The resource category of the file. E.g.: localization or color. It's the same as the requested category in the project resources.
{group}The sync group of the file. E.g.: ios, json or swift. It's the same as the requested group in the project resources.
{version}The actual version of the category from where the file is downloaded. E.g.: 1.2.4 or feature_add-about-us.
{path}The full path of the file generated by the Respresso server based on your Flow. E.g.: respresso/images/logo.svg.
{directory}The directory part of the file path generated by the Respresso server based on your Flow. E.g.: respresso/images.
{file}The file's name including the extension of the path generated by the Respresso server based on your Flow. E.g.: logo.svg.
{fileName}The file's name excluding the extension and the separating dot of the path generated by the Respresso server based on your Flow. E.g.: logo.
{extension}The file's extension without the separating dot of the path generated by the Respresso server based on your Flow. E.g.: svg.
{pathMatch<n>}The nth matching group of the Regular Expression defined in the path matcher. {pathMatch0} means the whole matched string. (Not the whole string.) Only the first match is used.

Keep in mind, that these placeholders will only be replaced in case of exact match.

The resolved patterns is normalized before usage. Thanks to this, you can have multiple file separators (like dir//file.ext), or you can mix \ and / separators, it will be normalized.

Common examples

There are common cases when these target override rules come handy. We collected some of them to showcase the config options. You can also create an example respresso.json config file containing a few advanced examples with the respresso init --example command.

Change target directory - keeping the original directory structure

This example shows you how to place all the files of a category (localization) and group (json) to a specific directory keeping the nested directory structure.

{
  "match": {
    "category": "localization",
    "group": "json"
  },
  "override": {
    "target": "./i18n"
  }
}

Change target directory - ignoring the original directory structure

This example shows you how to place all the files of a category (localization) and group (json) to a specific directory dropping the nested directory structure.

{
  "match": {
    "category": "localization",
    "group": "json"
  },
  "override": {
    "targetPattern": "./i18n/{file}"
  }
}

Restructure directories by localization languages

This example shows you how to place all the localization JSON files to a separate directory based on its language.

To understand this example, you need to know, that Respresso uses the following pattern to generate JSON files:
respresso/localization/respresso.strings-{{language}}.json

Using this knowledge, we can define a path matcher Regular Expression that will capture the language code in the first matching group.

{
  "match": {
    "path": "respresso\\.strings-(.+)\\.json$"
  },
  "override": {
    "targetPattern": "./i18n/{pathMatch1}/respresso.json"
  }
}

Place raster images to the static directory

This example shows you how to place raster images to a specific directory based on their extension. (Keeping the nested directory structure.)

{
  "match": {
    "path": "\\.(png|jpg|webp)$"
  },
  "override": {
    "targetPattern": "./static/image/{path}"
  }
}

You can ignore the nested directory structure by using the ./static/image/{file} target pattern. Keep in mind, that when you reorganize your files, there might be multiple files with the same name and extension.

Move all .xcassets directories to a single asset directory

This example shows you how to place all .xcassets directories (e.g.: images and colors) to a specific directory while ignoring any parent directories but keeping the nested directories.

{
  "match": {
    "path": "([\\w-]+)\\.xcassets/.*$"
  },
  "override": {
    "targetPattern": "assets/{pathMatch0}"
  }
}

Override default Localizable strings

This example shows you how to override your Localizable strings with the files generated by Respresso. (Instead of using RespressoStrings table)

{
  "match": {
    "path": "RespressoStrings/([a-zA-Z_-]+.lproj)/RespressoStrings\\.strings$"
  },
  "override": {
    "targetPattern": "Localizable/{pathMatch1}/Localizable.strings"
  }
}

Organize everything nicely

This example shows you how to use most of the non-regex patterns to organize your files.

{
  "match": {}, // Empty match matches all files. You can also omit the match object to match everything.
  "override": {
    "targetPattern": "{category}/{group}/{version}/{directory}/{fileName}.{extension}"
  }
}

The target pattern could be simplified to {category}/{group}/{version}/{path} and get the same results.