1 Variable Injection

As part of the configuration of your components, you may want to inject the contents of certain variables into files that will be part of your artifacts. In the standard library, the io.Open function allows you to read the contents of a file and use it as a string within your component configuration.

When you use io.Open, you can specify the path to the file you want to read. The contents of that file will then be available as a string, which you can use in various parts of your component definition, such as in configuration fields or within the file system definitions of your artifacts.

Refer to the io section of the standard library documentation for more details on how to use the io.Open function.

1.1 Templating your files

In order to take advantage of variable injection, the files you want to read must be templated following the syntax declared in the Handlebars.js library. Handlebars.js is a popular and simple templating engine that allows you to create dynamic content by embedding variables and expressions within your templates. The templating syntax uses double curly braces {{}} to denote variables and expressions that should be replaced with actual values during the rendering process.

The full reference for the templating syntax can be found in the Handlebars.js documentation.

1.2 Basic Example

To inject variables into your component configuration, you can use the second argument of the io.Open function. This argument allows you to pass a struct with an arbitrary set of key-value pairs that will be used for variable substitution.

Assume the following JSON file named my-json.json.template:

{
    "database": {
        "url": "{{url}}",
        "logging": {{logging}}
    }
}

You can populate the url and logging fields by passing them as part of the second argument to io.Open:

config {
    cnf io.Open("my-json.json.template", {
        url: "http://example.com",
        logging: false
    })
}

In this example, the url key will be replaced with the value "http://example.com" and the logging key will be replaced with the value false when the configuration is processed. The resulting configuration will look like this:

{
    "database": {
        "url": "http://example.com",
        "logging": false
    }
}

1.3 Nested structures

You can also pass nested structures as part of the variable injection. For example, consider the following template file named file.json.template:

{
    "debug": "{{mode}}",
    "structKey": "{{myStruct.firstKey}}",
    "nestedKey": "{{myStruct.secondKey.whatever}}",
    "numberKey": {{myStruct.thirdKey}}
}

[!NOTE] Pay attention to the fact that when injecting non-string values (like numbers or booleans), you should not wrap the placeholders in quotes in the template file. In the example above, numberKey is not enclosed in quotes to ensure it is treated as a number (it could also be a boolean).

You can populate the fields by passing a nested structure to io.Open:

component {
    artifact {
        fs {
            "data" io.Open("file.json.template", {
                mode [1,2,3]
                myStruct {
                    firstKey "value"
                    secondKey {
                        whatever "val"
                    }
                    thirdKey 1
                }
            })
        }
    }
}

In this example, the mode key will be replaced with the array [1,2,3], myStruct.firstKey will be replaced with "value", myStruct.secondKey.whatever will be replaced with "val", and myStruct.thirdKey will be replaced with 1. The resulting file will look like this:

{
    "debug": "1,2,3",
    "structKey": "value",
    "nestedKey": "val",
    "numberKey": 1
}