TGL: Syntax

TGL: Syntax

This page covers the basic shape of a TGL script: how to read input, build output, declare scratch variables, and lay out statements.

$row: the input record

$row is the record you’re transforming. It’s a plain JSON object: nested fields, arrays, strings, numbers, booleans, nulls. Read fields with dot or bracket notation:

$out.email = $row.email
$out.full_name = $row["First Name"]   // brackets when the key has spaces
$out.first_tag = $row.tags[0]
$out.deep = $row.user.profile.email

Reading a missing field returns null. TGL doesn’t throw on undefined access. Same for chains where a parent is null:

$out.x = $row.does.not.exist   // returns null, no error

$row is read-only. You can’t write to it: $row.x = 1 is a parse error.

$meta: platform metadata

$meta is a read-only object of platform metadata about the record, kept separate from the record’s own fields on $row. It’s how a transform reaches values Tailglow attaches when it ingests the data, rather than values that came in the payload.

One field is available today:

  • $meta.ingested_at (string): the platform source time for the record, as an ISO 8601 timestamp. For collection rows, this is the server ingest time unless the request overrode it with a ?ts= parameter. For transforms sourced from a ViewFile, including joins, it is that source file’s creation time. Reach for it when your data has no timestamp of its own, or when you want Tailglow’s time for the current transform stage.
$out.id = $row.id
$out.ingested_at = $meta.ingested_at

$meta is read-only, the same as $row: writing to it ($meta.x = 1) is a parse error. Unlike $row, reading a field that isn’t part of the contract (anything other than $meta.ingested_at today) is a compile error that lists the fields you can use, so a typo fails fast instead of quietly returning null.

$out: your output

$out starts as {} (an empty object) on every record. Build it up:

$out.id = $row.id
$out.name = lowerCase($row.name)
$out.created_at = $row.timestamp

Whatever’s in $out when the script ends is the output record.

You can also assign wholesale, copying every field:

$out = $row                  // mirror the entire input
$out = $row.payload          // promote a nested object to top-level

Wholesale assignment is filtered. Dangerous keys like __proto__ are stripped automatically. You don’t have to worry about prototype pollution from untrusted source data.

$varname: scratch variables

For intermediate values you don’t want in the output:

$first = upperCase($row.first_name)
$last = upperCase($row.last_name)
$out.display = concat($first, " ", $last)

Variable names must start with a letter or underscore, followed by letters, digits, or underscores. A few names are reserved, including names with a __ prefix, constructor, and prototype. Variables are scoped to the script. There’s no global state across records.

Statements

Each statement goes on its own line. Newlines are the separator; semicolons aren’t a thing.

$out.a = 1
$out.b = 2

Comments use //:

// strip the protocol prefix
$out.host = replace($row.url, "https://", "")

There’s no block syntax for grouping statements. Control flow is done with directives. See Control flow for #if/#each.

Data types

TGL works on the JSON-shaped data stored by Tailglow: strings, finite numbers, booleans, null, arrays, and objects. Date functions can parse ISO strings, Unix seconds or milliseconds, and timestamp objects with seconds and nanoseconds.

There are no:

  • Object literals like { a: 1 }. Build outputs by writing to $out field by field.
  • Array literals like [1, 2, 3]. Use push(null, x) to start an array.

What’s next