Home

Awesome

smithy-playground

This is an experimental, work-in-progress project to develop a query language for Smithy.

Currently available as a LSP server with a client implementation for VS Code.

Usage

  1. Make sure you have Coursier available on the PATH as cs, running Java 11 or above
  2. Get the extension from Marketplace
  3. Create a file, smithy-build.json. Example:
{
  // This comes from https://github.com/aws/aws-sdk-js-v3/blob/main/codegen/sdk-codegen/aws-models/kinesis.json
  "imports": ["/Users/kubukoz/projects/aws-sdk-js-v3/codegen/sdk-codegen/aws-models/kinesis.json"],
  // For Smithy specs exported in jars
  "mavenDependencies": [
    "com.kubukoz:service-api:0.0.1"
  ],
  // To access non-standard Maven repositories
  "mavenRepositories": [
    "https://<path-to-artifactory>"
  ],
  // for Playground plugins
  "smithyPlayground": {
    "extensions": [
      "com.kubukoz::playground-extension:0.0.1"
    ]
  }
}
  1. Open/create a .smithyql file
  2. You should see output in the "Smithy Playground" panel, and after a while syntax/error highlighting in the open .smithyql files.

Here's an example of a SmithyQL file that works without any setup (or even a smithy-build.json):

use service playground.std#Clock

CurrentTimestamp {}

It uses a "standard library" of smithy-playground, which is always available.

Here's a more verbose example showcasing most of the language syntax. DemoService is defined in this repository's test suite.

use service demo.smithy#DemoService

CreateHero {
  hero: {
    good: {
      howGood: 42,
    },
  },
  friends: [
    {
      bad: {
        evilName: "Vader",
        powerLevel: 9001,
      },
    },
  ],
  doc: [
    "this is a document, so you can do pretty much anything here",
    null,
    false,
    42,
    {
      nested: "key",
    },
    [ ],
  ],
  hasNewtypes: {
    anInstant: "2022-10-08T00:46:31.378493Z",
    anUUID: "cd4f93e0-fd11-41f0-8f13-44f66e1f0997",
    power: "FIRE",
    powerMap: {
      FIRE: {
        good: {
          howGood: 10,
        },
      },
    },
  },
}

Running queries

The runner needs a base URL to target with its queries. This defaults to http://localhost:8080 and can be configured in the extention's preferences (a more first-class solution is planned):

preferences

or by manually changing the key in ./vscode/settings.json.

If a query typechecks, it can be executed by clicking on the "Run SmithyQL file" code lens...

code lens

or triggering the command from the Command Palette:

command

Supported features

Syntax

Here's a more verbose description of the SmithyQL syntax.

Literals

In general, in SmithyQL, value literals look very similar to JSON, with minor differences. They are also very similar to Smithy's node values.

We have:

Type representation

Important note

Regardless of how SmithyQL treats the syntax for a given type, the way it's going to be sent over the wire is still defined by the protocol's client implementation serializes it.

For example, even though SmithyQL treats all unions as tagged unions, if the protocol chooses to treat a union as a discriminated one (e.g. @simpleRestJson will do so if you want), it's going to be a discriminated one in the payload sent to the service.


Most Smithy types map directly to a kind of literal, but there are some additions.

For the following union:

union A {
  f: Integer,
  g: String
}

to get a value corresponding to the f case, you should do something like { f: 40 }.

enum Temperature {
  HOT: "Hot",
  COLD: "Cold"
}

In this case, the syntax would be "HOT" or "COLD".

Prelude

A SmithyQL file starts with a section called a prelude. It can contain use clauses (described below) available to all queries in the file.

For example:

use service playground.std#Clock
use service playground.std#Random

Use clauses are optional, as queries can refer to a service explicitly.

Queries

A SmithyQL file can contain any number of Queries. A Query is formed of the following:

An operation name can be either:

Explicit (fully qualified) references always have priority over implicit ones.

use clauses - use service

A use service clause adds a service to the set of services that will implicitly be used as the default for all queries in a file.

For a single-query file, an explicit and implicit service reference are always equivalent:

use service playground.std#Clock

CurrentTimestamp {}

is the same as

playground.std#Clock.CurrentTimestamp {}

Operation inputs

The operation input is always a structure, even if there is no explicitly defined input for an operation (this is enforced by the Smithy language).

Extra notes on syntax / the language

Known issues

Contributing / development notes

See CONTRIBUTING.md