Generating a client#
Smithy code generators are implemented as smithy-build plugins that run when the Smithy model is built. The plugins generate the equivalent of packages in their respective languages, configured to be used by language idiomatic tooling.
Add the Codegen Plugin#
TypeScript clients are generated by the typescript-codegen
plugin. Configure
the plugin by adding it to smithy-build.json
:
{
"version": "1.0",
"sources": ["model"],
"plugins": {
"typescript-codegen": {
"package": "@weather-service/client",
"packageVersion": "0.0.1"
}
}
}
In this case, we've configured the typescript-codegen
plugin to generate a package
named @weather-service/client
with version 0.0.1
.
{
"version": "1.0",
"sources": ["model"],
"maven": {
"dependencies": [
"software.amazon.smithy.typescript:smithy-aws-typescript-codegen:0.25.0"
]
},
"...": "..."
}
Next, add a build-time dependency on the code generator:
dependencies {
smithyBuild("software.amazon.smithy.typescript:smithy-aws-typescript-codegen:0.25.0")
}
dependencies {
smithyBuild 'software.amazon.smithy.typescript:smithy-aws-typescript-codegen:0.25.0'
}
Important
smithy-aws-typescript-codegen is used here because it provides a protocol generator for the @aws.protocols#restJson1 protocol. As mentioned in Updating the Smithy Model, code generators must know how to generate code for the specified protocol.
Now run smithy build
to build the model and generate the code. The TypeScript
package is written to the typescript-codegen
directory:
.
├── build
│ └── smithy
│ └── source
│ ├── build-info/
│ ├── model/
│ ├── sources/
│ └── typescript-codegen
│ ├── LICENSE
│ ├── package.json
│ ├── src/
│ ├── tsconfig.cjs.json
│ ├── tsconfig.es.json
│ ├── tsconfig.json
│ ├── tsconfig.types.json
│ └── typedoc.json
├── model
│ └── weather.smithy
└── smithy-build.json
Now run gradle build
to build the model and generate the code. The TypeScript
package is written to the typescript-codegen
directory:
.
├── build
│ ├── smithyprojections
│ │ └── weather-service
│ │ └── source
│ │ ├── build-info/
│ │ ├── model/
│ │ ├── sources/
│ │ └── typescript-codegen
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── src/
│ │ ├── tsconfig.cjs.json
│ │ ├── tsconfig.es.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.types.json
│ │ └── typedoc.json
│ └── tmp
├── build.gradle.kts
├── model
│ └── weather.smithy
└── smithy-build.json
.
├── build
│ ├── smithyprojections
│ │ └── weather-service
│ │ └── source
│ │ ├── build-info/
│ │ ├── model/
│ │ ├── sources/
│ │ └── typescript-codegen
│ │ ├── LICENSE
│ │ ├── package.json
│ │ ├── src/
│ │ ├── tsconfig.cjs.json
│ │ ├── tsconfig.es.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.types.json
│ │ └── typedoc.json
│ └── tmp
├── build.gradle
├── model
│ └── weather.smithy
└── smithy-build.json
Using the generated code#
The generated code is just a normal TypeScript package. Each time the model
is built and the code generated, the TypeScript code also has to be compiled.
The generated package.json
contains scripts to do so:
"scripts": {
"build": "concurrently 'yarn:build:cjs' 'yarn:build:es' 'yarn:build:types'",
"build:cjs": "tsc -p tsconfig.cjs.json",
"build:docs": "typedoc",
"build:es": "tsc -p tsconfig.es.json",
"build:types": "tsc -p tsconfig.types.json",
"build:types:downlevel": "downlevel-dts dist-types dist-types/ts3.4",
"clean": "rimraf ./dist-* && rimraf *.tsbuildinfo",
"prepack": "yarn run clean && yarn run build"
}
This example creates a mono-repo using Yarn Workspaces that
integrates building the Smithy model and generating the code into the
development workflow. First, move the Smithy project into its own
directory named smithy/
:
.
└── smithy
├── build
├── model
└── smithy-build.json
.
└── smithy
├── build
├── build.gradle.kts
├── model
└── smithy-build.json
.
└── smithy
├── build
├── build.gradle
├── model
└── smithy-build.json
Next, create a package.json
in the root of the project with the following
contents:
{
"name": "weather-service",
"scripts": {
"generate": "cd smithy && gradle clean build",
"build": "yarn workspace @weather-service/client build"
},
"dependencies": {
"@weather-service/client": "0.0.1"
},
"private": true,
"workspaces": [
"smithy/build/smithy/source/typescript-codegen"
]
}
{
"name": "weather-service",
"scripts": {
"generate": "cd smithy && gradle clean build",
"build": "yarn workspace @weather-service/client build",
},
"dependencies": {
"@weather-service/client": "0.0.1"
},
"private": true,
"workspaces": [
"smithy/build/smithyprojections/smithy/source/typescript-codegen"
]
}
A few things to note:
- The path under
workspaces
is the path to the root of the generated TypeScript package. - A
generate
script which builds the model, re-generating the code. - The
build
script compiles the generated TypeScript package, referred to by the name specified in thetypescript-codegen
plugin configuration insmithy-build.json
. - A dependency has been added on the generated TypeScript package, using the
name and version specified in the
typescript-codegen
plugin configuration insmithy-build.json
After making model updates, use yarn generate && yarn build
to run the
code generator and build the generated code. You will have to do this before
using the client in this example, because the output directory path has changed
after moving the Smithy project into the smithy
directory.
Finally, create an app.ts
file to use the client:
import {
GetCityCommandInput,
GetCityCommandOutput,
Weather
} from '@weather-service/client';
const client: Weather = new Weather({ endpoint: 'some-endpoint' });
const getCityInput: GetCityCommandInput = {
cityId: 'foo'
};
client.getCity(getCityInput).then((getCityOutput: GetCityCommandOutput) => {
// TODO Handle response
});
The typescript-codegen
plugin has generated a client, Weather
, with methods
for each of the operations, as well as types for the inputs and outputs of those
operations.