# Introduction

This is a Google example service representing a simple digital library.
It manages a collection of shelf resources, and each shelf owns a collection
of book resources.

The original gRPC-based API definition is in the [googleapis/googleapis](https://github.com/googleapis/googleapis/) repository.

It follows the [Google API Design Guidelines](https://cloud.google.com/apis/design). We have taken the `gRPC` representation of this service and converted it into `TypeSpec` to understand what gaps might be in the language. Note we're not trying to create an `TypeSpec` which could create the equivalent `protobuf` as an output format, but are focusing on the swagger created from both `gRPC` and `TypeSpec` and trying to understand the differences.

## Files

- [library.proto](library.proto) - The original `proto` file from the [googleapis/googleapis](https://github.com/googleapis/googleapis/tree/master/google/example/library) repo.
- [library.swagger.json](library.swagger.json) - Swagger generated from the `library.proto` file using `protoc-gen-openapiv2`.
- [library.tsp](library.tsp) - A hand-written TypeSpec file which tries to stay as close as possible to a RPC based request/response model.
- [openapi.json](openapi.json) - Swagger generated by `tsp compile` from `library.tsp`.

## Open Questions

### How to handle a empty response

for an op of form `op Foo(): null` we currently emit the `responses` block as follows:

```json
 "responses": {
    "200": {
        "description": "Null response"
    },
```

whereas when generated from gRPC definition it is:

```json
"responses": {
    "200": {
        "description": "A successful response.",
        "schema": {
            "properties": {}
        }
    },
```

### GRPC path mapping

Google uses structured names for [resource names](https://cloud.google.com/apis/design/resource_names). e.g.

```protobuf
// A Shelf contains a collection of books with a theme.
message Shelf {
  option (google.api.resource) = {
    type: "library-example.googleapis.com/Shelf",
    pattern: "shelves/{shelf_id}"
  };
  // The resource name of the shelf.
  // Shelf names have the form `shelves/{shelf_id}`.
  // The name is ignored when creating a shelf.
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference).type = "library-example.googleapis.com/Shelf"
  ];
}
```

Since the name includes part of the standard REST path, gRPC allows a more complex path mapping for the gRPC reverse proxy - (ref: [gRPC transcoding](https://cloud.google.com/endpoints/docs/grpc-service-config/reference/rpc/google.api#google.api.HttpRule)). In particular it allows for constructs like:

```
// Gets a shelf. Returns NOT_FOUND if the shelf does not exist.
  rpc GetShelf(GetShelfRequest) returns (Shelf) {
    option (google.api.http) = {
      get: "/v1/{name=shelves/*}"
    };
    option (google.api.method_signature) = "name";
  }
```

This means the URI for a GET on a shelf with name `shelves/fiction` is `/v1/shelves/fiction`. The grpc-openapiv2 generator doesn't handle this path mapping so you actually get invalid paths in the swagger. See the [Kiosk gRPC example](../grpc-kiosk-example) for a gRPC examples with OpenAPI compatible path definitions.
