# SDTF Query Language

The SDTF Query Language is a JSON structure describing several match criteria used to select nodes - tokens, groups and collections - within the token tree.

### Examples

{% tabs %}
{% tab title="Collection and tokens" %}
Get a collection exactly named "Colors" and all its children of kind: "token"

```json
{
  "where": {
    "collection": "^Colors$",
    "select": {
      "collection": true,
      "children": {
        "tokens": true
      }
    }
  }
}
```

{% endtab %}

{% tab title="Tokens by type" %}
Select all tokens of type: "color". See all available types in [Supported types](https://docs.specifyapp.com/concepts/specify-design-token-format#supported-types).

```json
{
  "where": {
    "token": ".*",
    "withTypes": { "include": ["color"] },
    "select": true
  }
}
```

{% endtab %}

{% tab title="Tokens in a particular location" %}
Select the tokens of type: "color", only within a group named "components" nested in a collection named "Colors".

```json
{
  "where": {
    "collection": "^Colors$",
    "andWhere": {
      "group": "^components$",
      "andWhere": {
        "token": ".*",
        "withTypes": { "include": ["color"] },
        "select": {
          "token": true,
          "parents": true
        }
      }
    }
  }
}
```

Notice it also selects the containing "components" group and "Colors" collection thanks to `select.parents: true`.
{% endtab %}
{% endtabs %}

## Query Language Structure

Every `SDTFQuery` holds a single a `where` property being:

* &#x20;an object: to select one branch of the graph
* an array of objects: to select many branches of the graph - equivalent to an OR statement.

```javascript
type SDTFQuery = { where: Where | Array<Where> }
```

The `where` property splits in 3 kinds: token, group, collection - offering a dedicated set of options to match against the given kind.

### Where Token

```typescript
type WhereToken = {
  token:
    | string // regex compatible
    | {
      name?: string; // regex compatible
      description?: string; // regex compatible
    };
  select:
    | true
    | {
      token?: boolean;
      parents?:
        | true
        | {
          groups?: true;
          collections?: true;
        };
    };
  withTypes?: {
    include?: Array<TokenTypeName>;
    exclude?: Array<TokenTypeName>;
  };
  withModes?: {
    include?: Array<string>;
    exclude?: Array<string>;
  }
};
```

### Where Group

```typescript
type WhereGroup = {
  group:
    | string // regex compatible
    | {
      name?: string; // regex compatible
      description?: string; // regex compatible
    };
  select:
    | true
    | {
    group?: boolean;
    parents?:
      | true
      | {
        groups?: true;
        collections?: true;
      };
    children:
      | true
      | {
        groups?: true;
        collections?: true;
        tokens?: true;
      };
  };
};
```

### Where Collection

```typescript
type WhereCollection = {
  collection:
    | string // regex compatible
    | {
      name?: string; // regex compatible
      description?: string; // regex compatible
    };
  select:
    | true
    | {
      collection?: boolean;
      parents?:
        | true
        | {
          groups?: true;
        };
      children:
        | true
        | {
          groups?: true;
          tokens?: true;
        };
    };
  withModes?: {
    include?: Array<string>;
    exclude?: Array<string>;
  }
};
```

## Recursion

The `where` property can alternatively holds a `andWhere` property instead of the `select` property.

Doing so, the `andWhere` property can receive any `where` operator described earlier.

> Note: since Collections cannot be nested, we cannot nest a `andWhere` Collection operator into another `where` or `andWhere` Collection

```json
{
  "where": {
    "collection": "^colors$",
    "andWhere": {
      "group": "^base",
      "andWhere": {
        "token": ".*",
        "withTypes": { "include": ["color"] },
        "select": {
          "token": true,
          "parents": true
        }
      }
    }
  }
}
```

## Query Result

Once executed by the engine, the query returns a [QueryResult](https://docs.specifyapp.com/reference/sdtf-engine/sdtf-queryresult) that helps to work with the matched tree nodes.
