← all lessons

Lesson 10

Resources

Resources

A resource is an entity with a stable identity. Instead of a loose bag of operations, you describe what the thing is — its identifiers — and bind lifecycle operations whose meaning Smithy understands.

resource City {
    identifiers: { cityId: CityId }
    read: GetCity
}

Lifecycle operations

Smithy knows these lifecycle verbs and validates their contracts:

  • Instance operations act on one identified resource: read, update, delete, put. Their input must include every identifier.
  • Collection operations act across instances: create, list.

For example, read must be @readonly, and its input must reference the resource’s identifier(s).

Target elision

Restating an identifier’s name and type in every operation is error-prone. Smithy 2.0 lets you elide it: input := for City brings the resource into scope, and $cityId pulls the member’s name and target from the resource, guaranteeing they match.

resource City {
    identifiers: { cityId: CityId }
    read: GetCity
}

string CityId

@readonly
operation GetCity {
    input := for City {
        @required
        $cityId
    }

    output := {
        @required
        name: String
    }
}

A service binds resources just like operations:

service CityService {
    version: "2024-01-01"
    resources: [
        City
    ]
}

Operations reachable through a bound resource don’t need to be listed under the service’s operations: — the resource binding pulls them in. (That’s why the serviceHasOperation check still finds GetCity below even though it’s only listed on the resource.)

Your turn

Wire up the resource. The starter gives you the service, resource, and CityId; you write GetCity using target elision. The checks confirm City is a resource and that CityService reaches GetCity through it.