Browse documentation

DNML

DNML (Dynomate Markup Language) is the file format of a Dynomate request. A request is one .dnml file with named, ordered operations for DynamoDB, Athena and Amazon Aurora DSQL.

One file, two runners

The app and the CLI read, validate and run the same .dnml files with the same rules. You can save a file in the app and run it in the CLI, or edit it by hand and open it in the app.

Collection layout

A collection is a folder with a collection.dnml marker file and zero or more request files:

Text
orders/  collection.dnml             # collection marker (required)  find-and-update-order.dnml  # request named "find-and-update-order"  list-open-orders.dnml       # request named "list-open-orders"  archive/    old-request.dnml          # not discovered: nested one level too deep
  • A folder is a collection only if it contains a valid collection.dnml.
  • Each other .dnml file directly in the folder is one request. The request name must be the same as the filename.
  • Dynomate does not find request files in subfolders. It does not read other file types.
  • If a file is not valid, Dynomate shows a diagnostic with its path. The other requests stay available.

The CLI can also run a .dnml file outside a collection. See also Request collections.

Running example

The DNML, Requests and CLI pages use one example request. find-and-update-order finds the most recent order for an account, marks it reviewed, and reads it back:

version = "1.0"name = "find-and-update-order"description = "Find the most recent order for an account, mark it reviewed, and read it back."[variables]accountId = "account#42"pageSize = "1"[defaults]profileName = "commerce-dev"[[dynamodb.query]]name = "Find recent order"tableArn = "arn:aws:dynamodb:ap-southeast-2:111122223333:table/Orders"keyConditionExpression = "accountId = :accountId"limit = "${cast(pageSize, 'integer')}"scanIndexForward = false[dynamodb.query.expressionAttributeValues]":accountId" = "${accountId}"[[dynamodb.update]]name = "Mark reviewed"dependsOn = "Find recent order"tableArn = "arn:aws:dynamodb:ap-southeast-2:111122223333:table/Orders"updateExpression = "SET #status = :status"[dynamodb.update.keyValues]accountId = "${accountId}"orderId = "${find_recent_order.items[0].orderId}"[dynamodb.update.expressionAttributeNames]"#status" = "status"[dynamodb.update.expressionAttributeValues]":status" = "REVIEWED"[[dynamodb.get]]name = "Read back"dependsOn = "Mark reviewed"tableArn = "arn:aws:dynamodb:ap-southeast-2:111122223333:table/Orders"consistentRead = true[dynamodb.get.keyValues]accountId = "${accountId}"orderId = "${find_recent_order.items[0].orderId}"
Lines 1–20 of 46
TOML · DNML 1.0 · 46 lines
The same request in the app, as a DNML file, and in the CLI.
  • [variables] and [defaults] hold request values and the AWS profile.
  • Each [[dynamodb.…]] block is one operation.
  • dependsOn refers to another operation by its exact name.
  • ${find_recent_order.items[0].orderId} reads the query result through the normalized name.
  • ${cast(pageSize, 'integer')} changes the string "1" into the integer that limit needs.

If the query returns no items, items[0] does not resolve, and the update fails before its AWS call.

TOML basis

A DNML file is a valid TOML 1.1 document in UTF-8, without a byte order mark. In TOML 1.1, an inline table can use many lines and end with a trailing comma.

DNML adds a set of keys for each operation, ${…} templates and run rules. In DNML, the order of the operation blocks is important. In TOML, it is not.

A minimal request:

DNML
version = "1.0"name = "list-users"[[dynamodb.query]]name = "Users by tenant"tableArn = "arn:aws:dynamodb:us-east-1:123456789012:table/Users"keyConditionExpression = "#pk = :pk"[dynamodb.query.expressionAttributeNames]"#pk" = "pk"[dynamodb.query.expressionAttributeValues]":pk" = "tenant#acme"

Versioning

Each request file starts with version, in the form MAJOR.MINOR. A request with an Aurora DSQL operation uses version = "1.1". Other requests use version = "1.0".

  • A request file without version is not valid.
  • Dynomate accepts all 1.x versions. Keys that it does not know are unknown keys.
  • A higher major version, such as "2.0", causes DNML_UNSUPPORTED_VERSION.
  • When Dynomate saves a request, it writes the lowest version that the file needs. A file with an Aurora DSQL operation gets "1.1", also if the operation is disabled. Other files get "1.0".
  • A file with version = "1.0" and an Aurora DSQL operation still runs. Dynomate saves it as "1.1".
  • Dynomate 2.0 rejects Aurora DSQL operations with DNML_UNSUPPORTED_OPERATION. Dynomate CLI 0.0.21 and earlier also reject them.

The collection marker has version = "1.0".

Where to next