CUE basics
Applications in the Tailor Platform are defined using CUE files.
CUE is a powerful, open-source configuration language designed to simplify the creation and validation of data structures. With its unique combination of features, CUE offers developers a consistent and efficient way to manage configuration files, data validation, and code generation.
This page covers the basics of the CUE language in the context of its features and functionality as they relate to the Tailor Platform.
Syntax
CUE is a superset of JSON: any valid JSON file is a valid CUE file. CUE provides type checking, validation, imports and many more features.
JSON objects are called structs in CUE. An object member is called a field.
The basic building block of a CUE configuration is a key-value pair, where the key is a string and the value can be of any type. For example:
<span><span style="color: var(--shiki-color-text)">name: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">John Smith</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)">age: </span><span style="color: var(--shiki-token-constant)">30</span></span>
<span></span>
In addition to simple key-value pairs, CUE supports a variety of other expression types for defining more complex data structures, for instance:
<span><span style="color: var(--shiki-color-text)">person: {</span></span>
<span><span style="color: var(--shiki-color-text)"> name: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">John Smith</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> age: </span><span style="color: var(--shiki-token-constant)">30</span></span>
<span><span style="color: var(--shiki-color-text)"> hobbies: [</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">Fishing</span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-punctuation)">,</span></span>
<span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">Gaming</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> ]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
CUE also supports schema definitions for validating and structuring data. A schema is a set of rules that define the structure and constraints of a configuration:
<span><span style="color: var(--shiki-token-comment)">// define a schema representing a person with type constraints on its fields</span></span>
<span><span style="color: var(--shiki-color-text)">#Person: {</span></span>
<span><span style="color: var(--shiki-color-text)"> name: </span><span style="color: var(--shiki-token-constant)">string</span></span>
<span><span style="color: var(--shiki-color-text)"> age: </span><span style="color: var(--shiki-token-constant)">int</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span><span style="color: var(--shiki-token-comment)">// reference the Person schema</span></span>
<span><span style="color: var(--shiki-color-text)">person: #Person </span><span style="color: var(--shiki-token-keyword)">&</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> name: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">John Smith</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> age: </span><span style="color: var(--shiki-token-constant)">30</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
For a complete reference of the CUE syntax and all CUE's features, see:
Authoring CUE files
CUE files have the .cue
extension and can be processed using the cue
command line tools.
On macOS, you can install the CUE command line tools using Homebrew:
<span><span style="color: var(--shiki-token-function)">brew</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">install</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">cue-lang/tap/cue</span></span>
<span></span>
Please refer to the official documentation for other operating systems.
When authoring a CUE schema locally, you can verify its correctness by running cue eval
:
<span><span style="color: var(--shiki-token-function)">cue</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">eval</span><span style="color: var(--shiki-color-text)"> [file.cue]</span></span>
<span><span style="color: var(--shiki-token-comment)"># => result of evaluation</span></span>
<span></span>
For an overview of the cue commands, see this page.
CUE Manifest
The Tailor Platform features a manifest, a set of rules that describes how to construct a CUE file. The manifest is used to ensure that the configuration is well-formed and that any errors are detected before the application is run. It is also used to prevent malicious or unexpected behavior.
The CUE manifest and services definitions reside in the cue.mod
directory, which can be downloaded by running:
<span><span style="color: var(--shiki-token-function)">tailorctl</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">manifest</span><span style="color: var(--shiki-color-text)"> </span><span style="color: var(--shiki-token-string)">tidy</span></span>
<span></span>
- The manifest and services are defined in
cue.mod/pkg/github.com/tailor-platform/tailorctl/schema/v2
The manifest contains the following definitions:
<span><span style="color: var(--shiki-color-text)">#Workspace: {</span></span>
<span><span style="color: var(--shiki-color-text)"> common.#WithKind</span></span>
<span><span style="color: var(--shiki-color-text)"> Kind: common.#KindWorkspace</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> Apps: [...application.#Spec]</span></span>
<span><span style="color: var(--shiki-color-text)"> Services: [...(auth.#Spec </span><span style="color: var(--shiki-token-keyword)">|</span><span style="color: var(--shiki-color-text)"> pipeline.#Spec </span><span style="color: var(--shiki-token-keyword)">|</span><span style="color: var(--shiki-color-text)"> executor.#Spec </span><span style="color: var(--shiki-token-keyword)">|</span><span style="color: var(--shiki-color-text)"> stateflow.#Spec </span><span style="color: var(--shiki-token-keyword)">|</span><span style="color: var(--shiki-color-text)"> tailordb.#Spec)]</span></span>
<span></span>
<span><span style="color: var(--shiki-color-text)"> Auths: [</span><span style="color: var(--shiki-token-keyword)">for</span><span style="color: var(--shiki-color-text)"> x </span><span style="color: var(--shiki-token-keyword)">in</span><span style="color: var(--shiki-color-text)"> Services </span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> x.Kind </span><span style="color: var(--shiki-token-keyword)">==</span><span style="color: var(--shiki-color-text)"> common.#Auth {x}]</span></span>
<span><span style="color: var(--shiki-color-text)"> Pipelines: [</span><span style="color: var(--shiki-token-keyword)">for</span><span style="color: var(--shiki-color-text)"> x </span><span style="color: var(--shiki-token-keyword)">in</span><span style="color: var(--shiki-color-text)"> Services </span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> x.Kind </span><span style="color: var(--shiki-token-keyword)">==</span><span style="color: var(--shiki-color-text)"> common.#Pipeline {x}]</span></span>
<span><span style="color: var(--shiki-color-text)"> Executors: [</span><span style="color: var(--shiki-token-keyword)">for</span><span style="color: var(--shiki-color-text)"> x </span><span style="color: var(--shiki-token-keyword)">in</span><span style="color: var(--shiki-color-text)"> Services </span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> x.Kind </span><span style="color: var(--shiki-token-keyword)">==</span><span style="color: var(--shiki-color-text)"> common.#Executor {x}]</span></span>
<span><span style="color: var(--shiki-color-text)"> Stateflows: [</span><span style="color: var(--shiki-token-keyword)">for</span><span style="color: var(--shiki-color-text)"> x </span><span style="color: var(--shiki-token-keyword)">in</span><span style="color: var(--shiki-color-text)"> Services </span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> x.Kind </span><span style="color: var(--shiki-token-keyword)">==</span><span style="color: var(--shiki-color-text)"> common.#StateFlow {x}]</span></span>
<span><span style="color: var(--shiki-color-text)"> Tailordbs: [</span><span style="color: var(--shiki-token-keyword)">for</span><span style="color: var(--shiki-color-text)"> x </span><span style="color: var(--shiki-token-keyword)">in</span><span style="color: var(--shiki-color-text)"> Services </span><span style="color: var(--shiki-token-keyword)">if</span><span style="color: var(--shiki-color-text)"> x.Kind </span><span style="color: var(--shiki-token-keyword)">==</span><span style="color: var(--shiki-color-text)"> common.#TailorDB {x}]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
Those definitions are then used, for instance, to define the Tailor DB:
<span><span style="color: var(--shiki-color-text)">tailordb.#Spec </span><span style="color: var(--shiki-token-keyword)">&</span><span style="color: var(--shiki-color-text)"> {</span></span>
<span><span style="color: var(--shiki-color-text)"> Namespace: </span><span style="color: var(--shiki-color-text)">"</span><span style="color: var(--shiki-token-string-expression)">my-tailordb</span><span style="color: var(--shiki-color-text)">"</span></span>
<span><span style="color: var(--shiki-color-text)"> Types: [</span></span>
<span><span style="color: var(--shiki-color-text)"> ...</span></span>
<span><span style="color: var(--shiki-color-text)"> ]</span></span>
<span><span style="color: var(--shiki-color-text)">}</span></span>
<span></span>
<span></span>